#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;
}
/* 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;
}
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)
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;
}
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;
#ifndef __AE_H__
#define __AE_H__
-#define AE_SETSIZE (1024*10) /* Max number of fd supported */
-
#define AE_OK 0
#define AE_ERR -1
/* 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 */
} 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,
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;
}
aeApiState *state = eventLoop->apidata;
close(state->epfd);
+ zfree(state->events);
zfree(state);
}
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;
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;
}
aeApiState *state = eventLoop->apidata;
close(state->kqfd);
+ zfree(state->events);
zfree(state);
}
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;
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;
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;
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) {
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