/*============================ Utility functions ============================ */
-void redisLog(int level, const char *fmt, ...) {
+/* Low level logging. To use only for very big messages, otherwise
+ * redisLog() is to prefer. */
+void redisLogRaw(int level, const char *msg) {
const int syslogLevelMap[] = { LOG_DEBUG, LOG_INFO, LOG_NOTICE, LOG_WARNING };
const char *c = ".-*#";
time_t now = time(NULL);
- va_list ap;
FILE *fp;
char buf[64];
- char msg[REDIS_MAX_LOGMSG_LEN];
if (level < server.verbosity) return;
fp = (server.logfile == NULL) ? stdout : fopen(server.logfile,"a");
if (!fp) return;
- va_start(ap, fmt);
- vsnprintf(msg, sizeof(msg), fmt, ap);
- va_end(ap);
-
strftime(buf,sizeof(buf),"%d %b %H:%M:%S",localtime(&now));
fprintf(fp,"[%d] %s %c %s\n",(int)getpid(),buf,c[level],msg);
fflush(fp);
if (server.syslog_enabled) syslog(syslogLevelMap[level], "%s", msg);
}
+/* Like redisLogRaw() but with printf-alike support. This is the funciton that
+ * is used across the code. The raw version is only used in order to dump
+ * the INFO output on crash. */
+void redisLog(int level, const char *fmt, ...) {
+ va_list ap;
+ char msg[REDIS_MAX_LOGMSG_LEN];
+
+ if (level < server.verbosity) return;
+
+ va_start(ap, fmt);
+ vsnprintf(msg, sizeof(msg), fmt, ap);
+ va_end(ap);
+
+ redisLogRaw(level,msg);
+}
+
/* Redis generally does not try to recover from out of memory conditions
* when allocating objects or strings, it is not clear if it will be possible
* to report this condition to the client since the networking layer itself
signal(SIGHUP, SIG_IGN);
signal(SIGPIPE, SIG_IGN);
- setupSigSegvAction();
+ setupSignalHandlers();
if (server.syslog_enabled) {
openlog(server.syslog_ident, LOG_PID | LOG_NDELAY | LOG_NOWAIT,
}
if (server.ds_enabled) dsInit();
+ srand(time(NULL)^getpid());
}
/* Populates the Redis Command Table starting from the hard coded list
info = sdscatprintf(info,
"cache_max_memory:%llu\r\n"
"cache_blocked_clients:%lu\r\n"
+ "cache_io_queue_len:%lu\r\n"
+ "cache_io_jobs_new:%lu\r\n"
+ "cache_io_jobs_processing:%lu\r\n"
+ "cache_io_jobs_processed:%lu\r\n"
+ "cache_io_ready_clients:%lu\r\n"
,(unsigned long long) server.cache_max_memory,
- (unsigned long) server.cache_blocked_clients
+ (unsigned long) server.cache_blocked_clients,
+ (unsigned long) listLength(server.cache_io_queue),
+ (unsigned long) listLength(server.io_newjobs),
+ (unsigned long) listLength(server.io_processing),
+ (unsigned long) listLength(server.io_processed),
+ (unsigned long) listLength(server.io_ready_clients)
);
unlockThreadedIO();
}
}
int main(int argc, char **argv) {
- time_t start;
+ long long start;
initServerConfig();
if (argc == 2) {
#ifdef __linux__
linuxOvercommitMemoryWarning();
#endif
- start = time(NULL);
+ start = ustime();
if (server.ds_enabled) {
redisLog(REDIS_NOTICE,"DB not loaded (running with disk back end)");
} else if (server.appendonly) {
if (loadAppendOnlyFile(server.appendfilename) == REDIS_OK)
- redisLog(REDIS_NOTICE,"DB loaded from append only file: %ld seconds",time(NULL)-start);
+ redisLog(REDIS_NOTICE,"DB loaded from append only file: %.3f seconds",(float)(ustime()-start)/1000000);
} else {
if (rdbLoad(server.dbfilename) == REDIS_OK)
- redisLog(REDIS_NOTICE,"DB loaded from disk: %ld seconds",time(NULL)-start);
+ redisLog(REDIS_NOTICE,"DB loaded from disk: %.3f seconds",(float)(ustime()-start)/1000000);
}
if (server.ipfd > 0)
redisLog(REDIS_NOTICE,"The server is now ready to accept connections on port %d", server.port);
return 0;
}
-/* ============================= Backtrace support ========================= */
-
#ifdef HAVE_BACKTRACE
-void *getMcontextEip(ucontext_t *uc) {
+static void *getMcontextEip(ucontext_t *uc) {
#if defined(__FreeBSD__)
return (void*) uc->uc_mcontext.mc_eip;
#elif defined(__dietlibc__)
#endif
}
-void segvHandler(int sig, siginfo_t *info, void *secret) {
+static void sigsegvHandler(int sig, siginfo_t *info, void *secret) {
void *trace[100];
char **messages = NULL;
int i, trace_size = 0;
redisLog(REDIS_WARNING,
"======= Ooops! Redis %s got signal: -%d- =======", REDIS_VERSION, sig);
infostring = genRedisInfoString("all");
- redisLog(REDIS_WARNING, "%s",infostring);
+ redisLogRaw(REDIS_WARNING, infostring);
/* It's not safe to sdsfree() the returned string under memory
* corruption conditions. Let it leak as we are going to abort */
sigaction (sig, &act, NULL);
kill(getpid(),sig);
}
+#endif /* HAVE_BACKTRACE */
-void sigtermHandler(int sig) {
+static void sigtermHandler(int sig) {
REDIS_NOTUSED(sig);
- redisLog(REDIS_WARNING,"SIGTERM received, scheduling shutting down...");
+ redisLog(REDIS_WARNING,"Received SIGTERM, scheduling shutdown...");
server.shutdown_asap = 1;
}
-void setupSigSegvAction(void) {
+void setupSignalHandlers(void) {
struct sigaction act;
- sigemptyset (&act.sa_mask);
- /* When the SA_SIGINFO flag is set in sa_flags then sa_sigaction
- * is used. Otherwise, sa_handler is used */
- act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND | SA_SIGINFO;
- act.sa_sigaction = segvHandler;
- sigaction (SIGSEGV, &act, NULL);
- sigaction (SIGBUS, &act, NULL);
- sigaction (SIGFPE, &act, NULL);
- sigaction (SIGILL, &act, NULL);
- sigaction (SIGBUS, &act, NULL);
-
+ /* When the SA_SIGINFO flag is set in sa_flags then sa_sigaction is used.
+ * Otherwise, sa_handler is used. */
+ sigemptyset(&act.sa_mask);
act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND;
act.sa_handler = sigtermHandler;
- sigaction (SIGTERM, &act, NULL);
- return;
-}
+ sigaction(SIGTERM, &act, NULL);
-#else /* HAVE_BACKTRACE */
-void setupSigSegvAction(void) {
+#ifdef HAVE_BACKTRACE
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND | SA_SIGINFO;
+ act.sa_sigaction = sigsegvHandler;
+ sigaction(SIGSEGV, &act, NULL);
+ sigaction(SIGBUS, &act, NULL);
+ sigaction(SIGFPE, &act, NULL);
+ sigaction(SIGILL, &act, NULL);
+#endif
+ return;
}
-#endif /* HAVE_BACKTRACE */
/* The End */