diff --git a/src/config.c b/src/config.c index cd0ef04e2..ae1c7abc3 100644 --- a/src/config.c +++ b/src/config.c @@ -559,10 +559,35 @@ void configSetCommand(redisClient *c) { } freeMemoryIfNeeded(); } + } else if (!strcasecmp(c->argv[2]->ptr,"maxclients")) { + int orig_value = server.maxclients; + + if (getLongLongFromObject(o,&ll) == REDIS_ERR || ll < 0) goto badfmt; + + /* Try to check if the OS is capable of supporting so many FDs. */ + server.maxclients = ll; + if (ll > orig_value) { + adjustOpenFilesLimit(); + if (server.maxclients != ll) { + addReplyErrorFormat(c,"The operating system is not able to handle the specified number of clients, try with %d", server.maxclients); + server.maxclients = orig_value; + return; + } + if (aeGetSetSize(server.el) < + server.maxclients + REDIS_EVENTLOOP_FDSET_INCR) + { + if (aeResizeSetSize(server.el, + server.maxclients + REDIS_EVENTLOOP_FDSET_INCR) == AE_ERR) + { + addReplyError(c,"The event loop API used by Redis is not able to handle the specified number of clients"); + server.maxclients = orig_value; + return; + } + } + } } else if (!strcasecmp(c->argv[2]->ptr,"hz")) { - if (getLongLongFromObject(o,&ll) == REDIS_ERR || - ll < 0) goto badfmt; - server.hz = (int) ll; + if (getLongLongFromObject(o,&ll) == REDIS_ERR || ll < 0) goto badfmt; + server.hz = ll; if (server.hz < REDIS_MIN_HZ) server.hz = REDIS_MIN_HZ; if (server.hz > REDIS_MAX_HZ) server.hz = REDIS_MAX_HZ; } else if (!strcasecmp(c->argv[2]->ptr,"maxmemory-policy")) { diff --git a/src/redis.c b/src/redis.c index c23978346..e16c9bb2e 100644 --- a/src/redis.c +++ b/src/redis.c @@ -1422,7 +1422,7 @@ void initServer() { createSharedObjects(); adjustOpenFilesLimit(); - server.el = aeCreateEventLoop(server.maxclients+1024); + server.el = aeCreateEventLoop(server.maxclients+REDIS_EVENTLOOP_FDSET_INCR); server.db = zmalloc(sizeof(redisDb)*server.dbnum); if (server.port != 0) { diff --git a/src/redis.h b/src/redis.h index 78d97ca22..dade5e2a2 100644 --- a/src/redis.h +++ b/src/redis.h @@ -130,6 +130,10 @@ #define REDIS_MBULK_BIG_ARG (1024*32) #define REDIS_LONGSTR_SIZE 21 /* Bytes needed for long -> str */ #define REDIS_AOF_AUTOSYNC_BYTES (1024*1024*32) /* fdatasync every 32MB */ +/* When configuring the Redis eventloop, we setup it so that the total number + * of file descriptors we can handle are server.maxclients + FDSET_INCR + * that is our safety margin. */ +#define REDIS_EVENTLOOP_FDSET_INCR 128 /* Hash table parameters */ #define REDIS_HT_MINFILL 10 /* Minimal hash table fill 10% */ @@ -1239,6 +1243,7 @@ int htNeedsResize(dict *dict); void oom(const char *msg); void populateCommandTable(void); void resetCommandTableStats(void); +void adjustOpenFilesLimit(void); /* Set data type */ robj *setTypeCreate(robj *value);