summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2013-07-05 11:47:20 +0200
committerantirez <antirez@gmail.com>2013-07-05 11:47:20 +0200
commit98eecb70ebd215d4bc5a9a6917cd9ef04f9e01cf (patch)
treed2baa963e4badd0629486752fc2ca79cc172d6fb
parent2160effc78463d6602082302486beb51eb6a999d (diff)
downloadredis-98eecb70ebd215d4bc5a9a6917cd9ef04f9e01cf.tar.gz
Binding multiple IPs done properly with multiple sockets.
-rw-r--r--src/aof.c3
-rw-r--r--src/cluster.c26
-rw-r--r--src/rdb.c3
-rw-r--r--src/redis.c71
-rw-r--r--src/redis.h7
5 files changed, 79 insertions, 31 deletions
diff --git a/src/aof.c b/src/aof.c
index 9ad85c536..89f17abab 100644
--- a/src/aof.c
+++ b/src/aof.c
@@ -962,8 +962,7 @@ int rewriteAppendOnlyFileBackground(void) {
char tmpfile[256];
/* Child */
- if (server.ipfd > 0) close(server.ipfd);
- if (server.sofd > 0) close(server.sofd);
+ closeListeningSockets(0);
redisSetProcTitle("redis-aof-rewrite");
snprintf(tmpfile,256,"temp-rewriteaof-bg-%d.aof", (int) getpid());
if (rewriteAppendOnlyFile(tmpfile) == REDIS_OK) {
diff --git a/src/cluster.c b/src/cluster.c
index 2f77941d4..1682b436d 100644
--- a/src/cluster.c
+++ b/src/cluster.c
@@ -224,7 +224,7 @@ void clusterSaveConfigOrDie(void) {
}
void clusterInit(void) {
- int saveconf = 0;
+ int saveconf = 0, j;
server.cluster = zmalloc(sizeof(clusterState));
server.cluster->myself = NULL;
@@ -251,14 +251,24 @@ void clusterInit(void) {
}
if (saveconf) clusterSaveConfigOrDie();
/* We need a listening TCP port for our cluster messaging needs */
- server.cfd = anetTcpServer(server.neterr,
- server.port+REDIS_CLUSTER_PORT_INCR, server.bindaddr);
- if (server.cfd == -1) {
- redisLog(REDIS_WARNING, "Opening cluster TCP port: %s", server.neterr);
- exit(1);
+ server.cfd_count = 0;
+ if (server.bindaddr_count == 0) server.bindaddr[0] = NULL;
+ for (j = 0; j < server.bindaddr_count || j == 0; j++) {
+ server.cfd[j] = anetTcpServer(
+ server.neterr, server.port+REDIS_CLUSTER_PORT_INCR,
+ server.bindaddr[j]);
+ if (server.cfd[j] == -1) {
+ redisLog(REDIS_WARNING,
+ "Opening cluster listening TCP socket %s:%d: %s",
+ server.bindaddr[j] ? server.bindaddr[j] : "*",
+ server.port+REDIS_CLUSTER_PORT_INCR,
+ server.neterr);
+ exit(1);
+ }
+ if (aeCreateFileEvent(server.el, server.cfd[j], AE_READABLE,
+ clusterAcceptHandler, NULL) == AE_ERR) redisPanic("Unrecoverable error creating Redis Cluster file event.");
+ server.cfd_count++;
}
- if (aeCreateFileEvent(server.el, server.cfd, AE_READABLE,
- clusterAcceptHandler, NULL) == AE_ERR) redisPanic("Unrecoverable error creating Redis Cluster file event.");
server.cluster->slots_to_keys = zslCreate();
}
diff --git a/src/rdb.c b/src/rdb.c
index f403e27c8..c24f2d58f 100644
--- a/src/rdb.c
+++ b/src/rdb.c
@@ -729,8 +729,7 @@ int rdbSaveBackground(char *filename) {
int retval;
/* Child */
- if (server.ipfd > 0) close(server.ipfd);
- if (server.sofd > 0) close(server.sofd);
+ closeListeningSockets(0);
redisSetProcTitle("redis-rdb-bgsave");
retval = rdbSave(filename);
if (retval == REDIS_OK) {
diff --git a/src/redis.c b/src/redis.c
index a78ecfb51..adea459a8 100644
--- a/src/redis.c
+++ b/src/redis.c
@@ -1224,7 +1224,7 @@ void initServerConfig() {
server.bindaddr_count = 0;
server.unixsocket = NULL;
server.unixsocketperm = REDIS_DEFAULT_UNIX_SOCKET_PERM;
- server.ipfd = -1;
+ server.ipfd_count = 0;
server.sofd = -1;
server.dbnum = REDIS_DEFAULT_DBNUM;
server.verbosity = REDIS_DEFAULT_VERBOSITY;
@@ -1425,14 +1425,25 @@ void initServer() {
server.el = aeCreateEventLoop(server.maxclients+REDIS_EVENTLOOP_FDSET_INCR);
server.db = zmalloc(sizeof(redisDb)*server.dbnum);
+ /* Open the TCP listening sockets. */
if (server.port != 0) {
- server.ipfd = anetTcpServer(server.neterr,server.port,server.bindaddr,server.bindaddr_count);
- if (server.ipfd == ANET_ERR) {
- redisLog(REDIS_WARNING, "Opening port %d: %s",
- server.port, server.neterr);
- exit(1);
+ /* Force binding of 0.0.0.0 if no bind address is specified, always
+ * entering the loop if j == 0. */
+ if (server.bindaddr_count == 0) server.bindaddr[0] = NULL;
+ for (j = 0; j < server.bindaddr_count || j == 0; j++) {
+ server.ipfd[server.ipfd_count] = anetTcpServer(server.neterr,server.port,server.bindaddr[j]);
+ if (server.ipfd[server.ipfd_count] == ANET_ERR) {
+ redisLog(REDIS_WARNING,
+ "Creating Server TCP listening socket %s:%d: %s",
+ server.bindaddr[j] ? server.bindaddr[j] : "*",
+ server.port, server.neterr);
+ exit(1);
+ }
+ server.ipfd_count++;
}
}
+
+ /* Open the listening Unix domain socket. */
if (server.unixsocket != NULL) {
unlink(server.unixsocket); /* don't care if this fails */
server.sofd = anetUnixServer(server.neterr,server.unixsocket,server.unixsocketperm);
@@ -1441,10 +1452,14 @@ void initServer() {
exit(1);
}
}
- if (server.ipfd < 0 && server.sofd < 0) {
+
+ /* Abort if there are no listening sockets at all. */
+ if (server.ipfd_count == 0 && server.sofd < 0) {
redisLog(REDIS_WARNING, "Configured to not listen anywhere, exiting.");
exit(1);
}
+
+ /* Create the Redis databases, and initialize other internal state. */
for (j = 0; j < server.dbnum; j++) {
server.db[j].dict = dictCreate(&dbDictType,NULL);
server.db[j].expires = dictCreate(&keyptrDictType,NULL);
@@ -1487,15 +1502,28 @@ void initServer() {
server.unixtime = time(NULL);
server.lastbgsave_status = REDIS_OK;
server.repl_good_slaves_count = 0;
+
+ /* Create the serverCron() time event, that's our main way to process
+ * background operations. */
if(aeCreateTimeEvent(server.el, 1, serverCron, NULL, NULL) == AE_ERR) {
redisPanic("Can't create the serverCron time event.");
exit(1);
}
- if (server.ipfd > 0 && aeCreateFileEvent(server.el,server.ipfd,AE_READABLE,
- acceptTcpHandler,NULL) == AE_ERR) redisPanic("Unrecoverable error creating server.ipfd file event.");
+
+ /* Create an event handler for accepting new connections in TCP and Unix
+ * domain sockets. */
+ for (j = 0; j < server.ipfd_count; j++) {
+ if (aeCreateFileEvent(server.el, server.ipfd[j], AE_READABLE,
+ acceptTcpHandler,NULL) == AE_ERR)
+ {
+ redisPanic(
+ "Unrecoverable error creating server.ipfd file event.");
+ }
+ }
if (server.sofd > 0 && aeCreateFileEvent(server.el,server.sofd,AE_READABLE,
acceptUnixHandler,NULL) == AE_ERR) redisPanic("Unrecoverable error creating server.sofd file event.");
+ /* Open the AOF file if needed. */
if (server.aof_state == REDIS_AOF_ON) {
server.aof_fd = open(server.aof_filename,
O_WRONLY|O_APPEND|O_CREAT,0644);
@@ -1930,6 +1958,21 @@ int processCommand(redisClient *c) {
/*================================== Shutdown =============================== */
+/* Close listening sockets. Also unlink the unix domain socket if
+ * unlink_unix_socket is non-zero. */
+void closeListeningSockets(int unlink_unix_socket) {
+ int j;
+
+ for (j = 0; j < server.ipfd_count; j++) close(server.ipfd[j]);
+ if (server.sofd != -1) close(server.sofd);
+ if (server.cluster_enabled)
+ for (j = 0; j < server.cfd_count; j++) close(server.cfd[j]);
+ if (unlink_unix_socket && server.unixsocket) {
+ redisLog(REDIS_NOTICE,"Removing the unix socket file.");
+ unlink(server.unixsocket); /* don't care if this fails */
+ }
+}
+
int prepareForShutdown(int flags) {
int save = flags & REDIS_SHUTDOWN_SAVE;
int nosave = flags & REDIS_SHUTDOWN_NOSAVE;
@@ -1973,13 +2016,7 @@ int prepareForShutdown(int flags) {
unlink(server.pidfile);
}
/* Close the listening sockets. Apparently this allows faster restarts. */
- if (server.ipfd != -1) close(server.ipfd);
- if (server.sofd != -1) close(server.sofd);
- if (server.unixsocket) {
- redisLog(REDIS_NOTICE,"Removing the unix socket file.");
- unlink(server.unixsocket); /* don't care if this fails */
- }
-
+ closeListeningSockets(1);
redisLog(REDIS_WARNING,"Redis is now ready to exit, bye bye...");
return REDIS_OK;
}
@@ -2936,7 +2973,7 @@ int main(int argc, char **argv) {
exit(1);
}
}
- if (server.ipfd > 0)
+ if (server.ipfd_count > 0)
redisLog(REDIS_NOTICE,"The server is now ready to accept connections on port %d", server.port);
if (server.sofd > 0)
redisLog(REDIS_NOTICE,"The server is now ready to accept connections at %s", server.unixsocket);
diff --git a/src/redis.h b/src/redis.h
index 1df4084ed..e3542967f 100644
--- a/src/redis.h
+++ b/src/redis.h
@@ -735,9 +735,11 @@ struct redisServer {
int bindaddr_count; /* Number of addresses in server.bindaddr[] */
char *unixsocket; /* UNIX socket path */
mode_t unixsocketperm; /* UNIX socket permission */
- int ipfd; /* TCP socket file descriptor */
+ int ipfd[REDIS_BINDADDR_MAX]; /* TCP socket file descriptors */
+ int ipfd_count; /* Used slots in ipfd[] */
int sofd; /* Unix socket file descriptor */
- int cfd; /* Cluster bus listening socket */
+ int cfd[REDIS_BINDADDR_MAX];/* Cluster bus listening socket */
+ int cfd_count; /* Used slots in cfd[] */
list *clients; /* List of active clients */
list *clients_to_close; /* Clients to close asynchronously */
list *slaves, *monitors; /* List of slaves and MONITORs */
@@ -1246,6 +1248,7 @@ void oom(const char *msg);
void populateCommandTable(void);
void resetCommandTableStats(void);
void adjustOpenFilesLimit(void);
+void closeListeningSockets(int unlink_unix_socket);
/* Set data type */
robj *setTypeCreate(robj *value);