summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2011-12-15 11:42:40 +0100
committerantirez <antirez@gmail.com>2011-12-15 11:42:40 +0100
commite074416be49947c7bab5e237fab7210441bd99e5 (patch)
treee126e02f9fca9f4ed38fe58d9d2e622257c46369 /src
parent503d87a818ffd11c275bba6479bcd5b4a855e8ca (diff)
downloadredis-e074416be49947c7bab5e237fab7210441bd99e5.tar.gz
Max limit to 10k clients removed, this implements feature request on issue #194
Diffstat (limited to 'src')
-rw-r--r--src/ae.c24
-rw-r--r--src/ae.h11
-rw-r--r--src/ae_epoll.c11
-rw-r--r--src/ae_kqueue.c17
-rw-r--r--src/redis-benchmark.c2
-rw-r--r--src/redis.c72
6 files changed, 84 insertions, 53 deletions
diff --git a/src/ae.c b/src/ae.c
index 058028900..98ff7a8ee 100644
--- a/src/ae.c
+++ b/src/ae.c
@@ -52,12 +52,22 @@
#endif
#endif
-aeEventLoop *aeCreateEventLoop(void) {
+aeEventLoop *aeCreateEventLoop(int setsize) {
aeEventLoop *eventLoop;
int i;
- eventLoop = zmalloc(sizeof(*eventLoop));
- if (!eventLoop) return NULL;
+ if ((eventLoop = zmalloc(sizeof(*eventLoop))) == NULL) return NULL;
+ eventLoop->events = NULL;
+ eventLoop->fired = NULL;
+ eventLoop->events = zmalloc(sizeof(aeFileEvent)*setsize);
+ eventLoop->fired = zmalloc(sizeof(aeFiredEvent)*setsize);
+ if (eventLoop->events == NULL || eventLoop->fired == NULL) {
+ zfree(eventLoop->events);
+ zfree(eventLoop->fired);
+ zfree(eventLoop);
+ return NULL;
+ }
+ eventLoop->setsize = setsize;
eventLoop->timeEventHead = NULL;
eventLoop->timeEventNextId = 0;
eventLoop->stop = 0;
@@ -69,7 +79,7 @@ aeEventLoop *aeCreateEventLoop(void) {
}
/* Events with mask == AE_NONE are not set. So let's initialize the
* vector with it. */
- for (i = 0; i < AE_SETSIZE; i++)
+ for (i = 0; i < setsize; i++)
eventLoop->events[i].mask = AE_NONE;
return eventLoop;
}
@@ -86,7 +96,7 @@ void aeStop(aeEventLoop *eventLoop) {
int aeCreateFileEvent(aeEventLoop *eventLoop, int fd, int mask,
aeFileProc *proc, void *clientData)
{
- if (fd >= AE_SETSIZE) return AE_ERR;
+ if (fd >= eventLoop->setsize) return AE_ERR;
aeFileEvent *fe = &eventLoop->events[fd];
if (aeApiAddEvent(eventLoop, fd, mask) == -1)
@@ -102,7 +112,7 @@ int aeCreateFileEvent(aeEventLoop *eventLoop, int fd, int mask,
void aeDeleteFileEvent(aeEventLoop *eventLoop, int fd, int mask)
{
- if (fd >= AE_SETSIZE) return;
+ if (fd >= eventLoop->setsize) return;
aeFileEvent *fe = &eventLoop->events[fd];
if (fe->mask == AE_NONE) return;
@@ -119,7 +129,7 @@ void aeDeleteFileEvent(aeEventLoop *eventLoop, int fd, int mask)
}
int aeGetFileEvents(aeEventLoop *eventLoop, int fd) {
- if (fd >= AE_SETSIZE) return 0;
+ if (fd >= eventLoop->setsize) return 0;
aeFileEvent *fe = &eventLoop->events[fd];
return fe->mask;
diff --git a/src/ae.h b/src/ae.h
index 9e23a6fde..e1dccfc76 100644
--- a/src/ae.h
+++ b/src/ae.h
@@ -33,8 +33,6 @@
#ifndef __AE_H__
#define __AE_H__
-#define AE_SETSIZE (1024*10) /* Max number of fd supported */
-
#define AE_OK 0
#define AE_ERR -1
@@ -87,10 +85,11 @@ typedef struct aeFiredEvent {
/* State of an event based program */
typedef struct aeEventLoop {
- int maxfd;
+ int maxfd; /* highest file descriptor currently registered */
+ int setsize; /* max number of file descriptors tracked */
long long timeEventNextId;
- aeFileEvent events[AE_SETSIZE]; /* Registered events */
- aeFiredEvent fired[AE_SETSIZE]; /* Fired events */
+ aeFileEvent *events; /* Registered events */
+ aeFiredEvent *fired; /* Fired events */
aeTimeEvent *timeEventHead;
int stop;
void *apidata; /* This is used for polling API specific data */
@@ -98,7 +97,7 @@ typedef struct aeEventLoop {
} aeEventLoop;
/* Prototypes */
-aeEventLoop *aeCreateEventLoop(void);
+aeEventLoop *aeCreateEventLoop(int setsize);
void aeDeleteEventLoop(aeEventLoop *eventLoop);
void aeStop(aeEventLoop *eventLoop);
int aeCreateFileEvent(aeEventLoop *eventLoop, int fd, int mask,
diff --git a/src/ae_epoll.c b/src/ae_epoll.c
index 5680b6a27..fc6d9ccdd 100644
--- a/src/ae_epoll.c
+++ b/src/ae_epoll.c
@@ -6,15 +6,21 @@
typedef struct aeApiState {
int epfd;
- struct epoll_event events[AE_SETSIZE];
+ struct epoll_event *events;
} aeApiState;
static int aeApiCreate(aeEventLoop *eventLoop) {
aeApiState *state = zmalloc(sizeof(aeApiState));
if (!state) return -1;
+ state->events = zmalloc(sizeof(epoll_event)*eventLoop->setsize);
+ if (!state->events) {
+ zfree(state);
+ return -1;
+ }
state->epfd = epoll_create(1024); /* 1024 is just an hint for the kernel */
if (state->epfd == -1) {
+ zfree(state->events);
zfree(state);
return -1;
}
@@ -26,6 +32,7 @@ static void aeApiFree(aeEventLoop *eventLoop) {
aeApiState *state = eventLoop->apidata;
close(state->epfd);
+ zfree(state->events);
zfree(state);
}
@@ -70,7 +77,7 @@ static int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp) {
aeApiState *state = eventLoop->apidata;
int retval, numevents = 0;
- retval = epoll_wait(state->epfd,state->events,AE_SETSIZE,
+ retval = epoll_wait(state->epfd,state->events,eventLoop->setsize,
tvp ? (tvp->tv_sec*1000 + tvp->tv_usec/1000) : -1);
if (retval > 0) {
int j;
diff --git a/src/ae_kqueue.c b/src/ae_kqueue.c
index 6bf64f4ef..e91a254d5 100644
--- a/src/ae_kqueue.c
+++ b/src/ae_kqueue.c
@@ -8,15 +8,21 @@
typedef struct aeApiState {
int kqfd;
- struct kevent events[AE_SETSIZE];
+ struct kevent *events;
} aeApiState;
static int aeApiCreate(aeEventLoop *eventLoop) {
aeApiState *state = zmalloc(sizeof(aeApiState));
if (!state) return -1;
+ state->events = zmalloc(sizeof(struct kevent)*eventLoop->setsize);
+ if (!state->events) {
+ zfree(state);
+ return -1;
+ }
state->kqfd = kqueue();
if (state->kqfd == -1) {
+ zfree(state->events);
zfree(state);
return -1;
}
@@ -29,6 +35,7 @@ static void aeApiFree(aeEventLoop *eventLoop) {
aeApiState *state = eventLoop->apidata;
close(state->kqfd);
+ zfree(state->events);
zfree(state);
}
@@ -69,10 +76,12 @@ static int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp) {
struct timespec timeout;
timeout.tv_sec = tvp->tv_sec;
timeout.tv_nsec = tvp->tv_usec * 1000;
- retval = kevent(state->kqfd, NULL, 0, state->events, AE_SETSIZE, &timeout);
+ retval = kevent(state->kqfd, NULL, 0, state->events, eventLoop->setsize,
+ &timeout);
} else {
- retval = kevent(state->kqfd, NULL, 0, state->events, AE_SETSIZE, NULL);
- }
+ retval = kevent(state->kqfd, NULL, 0, state->events, eventLoop->setsize,
+ NULL);
+ }
if (retval > 0) {
int j;
diff --git a/src/redis-benchmark.c b/src/redis-benchmark.c
index b22322f4a..f7ca312de 100644
--- a/src/redis-benchmark.c
+++ b/src/redis-benchmark.c
@@ -490,7 +490,7 @@ int main(int argc, const char **argv) {
config.numclients = 50;
config.requests = 10000;
config.liveclients = 0;
- config.el = aeCreateEventLoop();
+ config.el = aeCreateEventLoop(1024*10);
aeCreateTimeEvent(config.el,1,showThroughput,NULL,NULL);
config.keepalive = 1;
config.datasize = 3;
diff --git a/src/redis.c b/src/redis.c
index 6926458b2..28240b03d 100644
--- a/src/redis.c
+++ b/src/redis.c
@@ -954,6 +954,43 @@ void initServerConfig() {
server.bug_report_start = 0;
}
+/* This function will try to raise the max number of open files accordingly to
+ * the configured max number of clients. It will also account for 32 additional
+ * file descriptors as we need a few more for persistence, listening
+ * sockets, log files and so forth.
+ *
+ * If it will not be possible to set the limit accordingly to the configured
+ * max number of clients, the function will do the reverse setting
+ * server.maxclients to the value that we can actually handle. */
+void adjustOpenFilesLimit(void) {
+ rlim_t maxfiles = server.maxclients+32;
+ struct rlimit limit;
+
+ if (maxfiles < 1024) maxfiles = 1024;
+ if (getrlimit(RLIMIT_NOFILE,&limit) == -1) {
+ redisLog(REDIS_WARNING,"Unable to obtain the current NOFILE limit (%s), assuming 1024 and setting the max clients configuration accordingly.",
+ strerror(errno));
+ server.maxclients = 1024-32;
+ } else {
+ rlim_t oldlimit = limit.rlim_cur;
+
+ /* Set the max number of files if the current limit is not enough
+ * for our needs. */
+ if (oldlimit < maxfiles) {
+ limit.rlim_cur = maxfiles;
+ limit.rlim_max = maxfiles;
+ if (setrlimit(RLIMIT_NOFILE,&limit) == -1) {
+ server.maxclients = oldlimit-32;
+ redisLog(REDIS_WARNING,"Unable to set the max number of files limit to %d (%s), setting the max clients configuration to %d.",
+ (int) maxfiles, strerror(errno), (int) server.maxclients);
+ } else {
+ redisLog(REDIS_NOTICE,"Max number of open files set to %d",
+ (int) maxfiles);
+ }
+ }
+ }
+}
+
void initServer() {
int j;
@@ -972,7 +1009,8 @@ void initServer() {
server.unblocked_clients = listCreate();
createSharedObjects();
- server.el = aeCreateEventLoop();
+ adjustOpenFilesLimit();
+ server.el = aeCreateEventLoop(server.maxclients+1024);
server.db = zmalloc(sizeof(redisDb)*server.dbnum);
if (server.port != 0) {
@@ -1045,38 +1083,6 @@ void initServer() {
bioInit();
srand(time(NULL)^getpid());
- /* Try to raise the max number of open files accordingly to the
- * configured max number of clients. Also account for 32 additional
- * file descriptors as we need a few more for persistence, listening
- * sockets, log files and so forth. */
- {
- rlim_t maxfiles = server.maxclients+32;
- struct rlimit limit;
-
- if (maxfiles < 1024) maxfiles = 1024;
- if (getrlimit(RLIMIT_NOFILE,&limit) == -1) {
- redisLog(REDIS_WARNING,"Unable to obtain the current NOFILE limit (%s), assuming 1024 and setting the max clients configuration accordingly.",
- strerror(errno));
- server.maxclients = 1024-32;
- } else {
- rlim_t oldlimit = limit.rlim_cur;
-
- /* Set the max number of files if the current limit is not enough
- * for our needs. */
- if (oldlimit < maxfiles) {
- limit.rlim_cur = maxfiles;
- limit.rlim_max = maxfiles;
- if (setrlimit(RLIMIT_NOFILE,&limit) == -1) {
- server.maxclients = oldlimit-32;
- redisLog(REDIS_WARNING,"Unable to set the max number of files limit to %d (%s), setting the max clients configuration to %d.",
- (int) maxfiles, strerror(errno), (int) server.maxclients);
- } else {
- redisLog(REDIS_NOTICE,"Max number of open files set to %d",
- (int) maxfiles);
- }
- }
- }
- }
}
/* Populates the Redis Command Table starting from the hard coded list