Skip to content

Commit d6704c9

Browse files
committed
hiredis library updated.
This version of hiredis merges modifications of the Redis fork with latest changes in the hiredis repository. The same version was pushed on the hiredis repository and will probably merged into the master branch in short time.
1 parent cada7f9 commit d6704c9

File tree

5 files changed

+90
-28
lines changed

5 files changed

+90
-28
lines changed

Diff for: deps/hiredis/README.md

+28-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ convert it to the protocol used to communicate with Redis.
7373
One or more spaces separates arguments, so you can use the specifiers
7474
anywhere in an argument:
7575

76-
reply = redisCommand("SET key:%s %s", myid, value);
76+
reply = redisCommand(context, "SET key:%s %s", myid, value);
7777

7878
### Using replies
7979

@@ -320,6 +320,10 @@ The reply parsing API consists of the following functions:
320320
int redisReaderFeed(redisReader *reader, const char *buf, size_t len);
321321
int redisReaderGetReply(redisReader *reader, void **reply);
322322

323+
The same set of functions are used internally by hiredis when creating a
324+
normal Redis context, the above API just exposes it to the user for a direct
325+
usage.
326+
323327
### Usage
324328

325329
The function `redisReaderCreate` creates a `redisReader` structure that holds a
@@ -346,6 +350,29 @@ immediately after creating the `redisReader`.
346350
For example, [hiredis-rb](https://github.com/pietern/hiredis-rb/blob/master/ext/hiredis_ext/reader.c)
347351
uses customized reply object functions to create Ruby objects.
348352

353+
### Reader max buffer
354+
355+
Both when using the Reader API directly or when using it indirectly via a
356+
normal Redis context, the redisReader structure uses a buffer in order to
357+
accumulate data from the server.
358+
Usually this buffer is destroyed when it is empty and is larger than 16
359+
kb in order to avoid wasting memory in unused buffers
360+
361+
However when working with very big payloads destroying the buffer may slow
362+
down performances considerably, so it is possible to modify the max size of
363+
an idle buffer changing the value of the `maxbuf` field of the reader structure
364+
to the desired value. The special value of 0 means that there is no maximum
365+
value for an idle buffer, so the buffer will never get freed.
366+
367+
For instance if you have a normal Redis context you can set the maximum idle
368+
buffer to zero (unlimited) just with:
369+
370+
context->reader->maxbuf = 0;
371+
372+
This should be done only in order to maximize performances when working with
373+
large payloads. The context should be set back to `REDIS_READER_MAX_BUF` again
374+
as soon as possible in order to prevent allocation of useless memory.
375+
349376
## AUTHORS
350377

351378
Hiredis was written by Salvatore Sanfilippo (antirez at gmail) and

Diff for: deps/hiredis/async.c

+29-11
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,11 @@ void redisProcessCallbacks(redisAsyncContext *ac) {
372372
__redisAsyncDisconnect(ac);
373373
return;
374374
}
375+
376+
/* If monitor mode, repush callback */
377+
if(c->flags & REDIS_MONITORING) {
378+
__redisPushCallback(&ac->replies,&cb);
379+
}
375380

376381
/* When the connection is not being disconnected, simply stop
377382
* trying to get replies and wait for the next loop tick. */
@@ -381,22 +386,31 @@ void redisProcessCallbacks(redisAsyncContext *ac) {
381386
/* Even if the context is subscribed, pending regular callbacks will
382387
* get a reply before pub/sub messages arrive. */
383388
if (__redisShiftCallback(&ac->replies,&cb) != REDIS_OK) {
384-
/* A spontaneous reply in a not-subscribed context can only be the
385-
* error reply that is sent when a new connection exceeds the
386-
* maximum number of allowed connections on the server side. This
387-
* is seen as an error instead of a regular reply because the
388-
* server closes the connection after sending it. To prevent the
389-
* error from being overwritten by an EOF error the connection is
390-
* closed here. See issue #43. */
391-
if ( !(c->flags & REDIS_SUBSCRIBED) && ((redisReply*)reply)->type == REDIS_REPLY_ERROR ) {
389+
/*
390+
* A spontaneous reply in a not-subscribed context can be the error
391+
* reply that is sent when a new connection exceeds the maximum
392+
* number of allowed connections on the server side.
393+
*
394+
* This is seen as an error instead of a regular reply because the
395+
* server closes the connection after sending it.
396+
*
397+
* To prevent the error from being overwritten by an EOF error the
398+
* connection is closed here. See issue #43.
399+
*
400+
* Another possibility is that the server is loading its dataset.
401+
* In this case we also want to close the connection, and have the
402+
* user wait until the server is ready to take our request.
403+
*/
404+
if (((redisReply*)reply)->type == REDIS_REPLY_ERROR) {
392405
c->err = REDIS_ERR_OTHER;
393406
snprintf(c->errstr,sizeof(c->errstr),"%s",((redisReply*)reply)->str);
394407
__redisAsyncDisconnect(ac);
395408
return;
396409
}
397-
/* No more regular callbacks and no errors, the context *must* be subscribed. */
398-
assert(c->flags & REDIS_SUBSCRIBED);
399-
__redisGetSubscribeCallback(ac,reply,&cb);
410+
/* No more regular callbacks and no errors, the context *must* be subscribed or monitoring. */
411+
assert((c->flags & REDIS_SUBSCRIBED || c->flags & REDIS_MONITORING));
412+
if(c->flags & REDIS_SUBSCRIBED)
413+
__redisGetSubscribeCallback(ac,reply,&cb);
400414
}
401415

402416
if (cb.fn != NULL) {
@@ -557,6 +571,10 @@ static int __redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void
557571
/* (P)UNSUBSCRIBE does not have its own response: every channel or
558572
* pattern that is unsubscribed will receive a message. This means we
559573
* should not append a callback function for this command. */
574+
} else if(strncasecmp(cstr,"monitor\r\n",9) == 0) {
575+
/* Set monitor flag and push callback */
576+
c->flags |= REDIS_MONITORING;
577+
__redisPushCallback(&ac->replies,&cb);
560578
} else {
561579
if (c->flags & REDIS_SUBSCRIBED)
562580
/* This will likely result in an error reply, but it needs to be

Diff for: deps/hiredis/hiredis.c

+3-4
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,7 @@ static int processMultiBulkItem(redisReader *r) {
446446
long elements;
447447
int root = 0;
448448

449-
/* Set error for nested multi bulks with depth > 2 */
449+
/* Set error for nested multi bulks with depth > 7 */
450450
if (r->ridx == 8) {
451451
__redisReaderSetError(r,REDIS_ERR_PROTOCOL,
452452
"No support for nested multi bulk replies with depth > 7");
@@ -564,6 +564,7 @@ redisReader *redisReaderCreate(void) {
564564
r->errstr[0] = '\0';
565565
r->fn = &defaultFunctions;
566566
r->buf = sdsempty();
567+
r->maxbuf = REDIS_READER_MAX_BUF;
567568
if (r->buf == NULL) {
568569
free(r);
569570
return NULL;
@@ -590,17 +591,15 @@ int redisReaderFeed(redisReader *r, const char *buf, size_t len) {
590591

591592
/* Copy the provided buffer. */
592593
if (buf != NULL && len >= 1) {
593-
#if 0
594594
/* Destroy internal buffer when it is empty and is quite large. */
595-
if (r->len == 0 && sdsavail(r->buf) > 16*1024) {
595+
if (r->len == 0 && r->maxbuf != 0 && sdsavail(r->buf) > r->maxbuf) {
596596
sdsfree(r->buf);
597597
r->buf = sdsempty();
598598
r->pos = 0;
599599

600600
/* r->buf should not be NULL since we just free'd a larger one. */
601601
assert(r->buf != NULL);
602602
}
603-
#endif
604603

605604
newbuf = sdscatlen(r->buf,buf,len);
606605
if (newbuf == NULL) {

Diff for: deps/hiredis/hiredis.h

+6
Original file line numberDiff line numberDiff line change
@@ -76,13 +76,18 @@
7676
/* Flag that is set when the async context has one or more subscriptions. */
7777
#define REDIS_SUBSCRIBED 0x20
7878

79+
/* Flag that is set when monitor mode is active */
80+
#define REDIS_MONITORING 0x40
81+
7982
#define REDIS_REPLY_STRING 1
8083
#define REDIS_REPLY_ARRAY 2
8184
#define REDIS_REPLY_INTEGER 3
8285
#define REDIS_REPLY_NIL 4
8386
#define REDIS_REPLY_STATUS 5
8487
#define REDIS_REPLY_ERROR 6
8588

89+
#define REDIS_READER_MAX_BUF (1024*16) /* Default max unused reader buffer. */
90+
8691
#ifdef __cplusplus
8792
extern "C" {
8893
#endif
@@ -122,6 +127,7 @@ typedef struct redisReader {
122127
char *buf; /* Read buffer */
123128
size_t pos; /* Buffer cursor */
124129
size_t len; /* Buffer length */
130+
size_t maxbuf; /* Max length of unused buffer */
125131

126132
redisReadTask rstack[9];
127133
int ridx; /* Index of current read task */

Diff for: deps/hiredis/net.c

+24-12
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@
4545
#include <errno.h>
4646
#include <stdarg.h>
4747
#include <stdio.h>
48+
#include <poll.h>
49+
#include <limits.h>
4850

4951
#include "net.h"
5052
#include "sds.h"
@@ -121,28 +123,38 @@ static int redisSetTcpNoDelay(redisContext *c, int fd) {
121123
return REDIS_OK;
122124
}
123125

126+
#define __MAX_MSEC (((LONG_MAX) - 999) / 1000)
127+
124128
static int redisContextWaitReady(redisContext *c, int fd, const struct timeval *timeout) {
125-
struct timeval to;
126-
struct timeval *toptr = NULL;
127-
fd_set wfd;
129+
struct pollfd wfd[1];
130+
long msec;
131+
132+
msec = -1;
133+
wfd[0].fd = fd;
134+
wfd[0].events = POLLOUT;
128135

129136
/* Only use timeout when not NULL. */
130137
if (timeout != NULL) {
131-
to = *timeout;
132-
toptr = &to;
138+
if (timeout->tv_usec > 1000000 || timeout->tv_sec > __MAX_MSEC) {
139+
close(fd);
140+
return REDIS_ERR;
141+
}
142+
143+
msec = (timeout->tv_sec * 1000) + ((timeout->tv_usec + 999) / 1000);
144+
145+
if (msec < 0 || msec > INT_MAX) {
146+
msec = INT_MAX;
147+
}
133148
}
134149

135150
if (errno == EINPROGRESS) {
136-
FD_ZERO(&wfd);
137-
FD_SET(fd, &wfd);
151+
int res;
138152

139-
if (select(FD_SETSIZE, NULL, &wfd, NULL, toptr) == -1) {
140-
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"select(2)");
153+
if ((res = poll(wfd, 1, msec)) == -1) {
154+
__redisSetErrorFromErrno(c, REDIS_ERR_IO, "poll(2)");
141155
close(fd);
142156
return REDIS_ERR;
143-
}
144-
145-
if (!FD_ISSET(fd, &wfd)) {
157+
} else if (res == 0) {
146158
errno = ETIMEDOUT;
147159
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
148160
close(fd);

0 commit comments

Comments
 (0)