]> git.saurik.com Git - redis.git/blobdiff - src/redis.c
conflict resolved in cherry pick
[redis.git] / src / redis.c
index f299dcab6ffe492d75295ba060768187f998e577..84e5560e055e7012d8eb4fefd99ef99a3e1bd709 100644 (file)
@@ -68,7 +68,7 @@ double R_Zero, R_PosInf, R_NegInf, R_Nan;
 /* Global vars */
 struct redisServer server; /* server global state */
 struct redisCommand *commandTable;
-struct redisCommand readonlyCommandTable[] = {
+struct redisCommand redisCommandTable[] = {
     {"get",getCommand,2,0,NULL,1,1,1,0,0},
     {"set",setCommand,3,REDIS_CMD_DENYOOM,NULL,0,0,0,0,0},
     {"setnx",setnxCommand,3,REDIS_CMD_DENYOOM,NULL,0,0,0,0,0},
@@ -192,24 +192,20 @@ struct redisCommand readonlyCommandTable[] = {
 
 /*============================ 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);
@@ -219,6 +215,22 @@ void redisLog(int level, const char *fmt, ...) {
     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
@@ -864,10 +876,13 @@ void initServer() {
     createSharedObjects();
     server.el = aeCreateEventLoop();
     server.db = zmalloc(sizeof(redisDb)*server.dbnum);
-    server.ipfd = anetTcpServer(server.neterr,server.port,server.bindaddr);
-    if (server.ipfd == ANET_ERR) {
-        redisLog(REDIS_WARNING, "Opening port: %s", server.neterr);
-        exit(1);
+
+    if (server.port != 0) {
+        server.ipfd = anetTcpServer(server.neterr,server.port,server.bindaddr);
+        if (server.ipfd == ANET_ERR) {
+            redisLog(REDIS_WARNING, "Opening port: %s", server.neterr);
+            exit(1);
+        }
     }
     if (server.unixsocket != NULL) {
         unlink(server.unixsocket); /* don't care if this fails */
@@ -930,16 +945,17 @@ void initServer() {
     }
 
     if (server.ds_enabled) dsInit();
+    srand(time(NULL)^getpid());
 }
 
 /* Populates the Redis Command Table starting from the hard coded list
  * we have on top of redis.c file. */
 void populateCommandTable(void) {
     int j;
-    int numcommands = sizeof(readonlyCommandTable)/sizeof(struct redisCommand);
+    int numcommands = sizeof(redisCommandTable)/sizeof(struct redisCommand);
 
     for (j = 0; j < numcommands; j++) {
-        struct redisCommand *c = readonlyCommandTable+j;
+        struct redisCommand *c = redisCommandTable+j;
         int retval;
 
         retval = dictAdd(server.commands, sdsnew(c->name), c);
@@ -947,6 +963,18 @@ void populateCommandTable(void) {
     }
 }
 
+void resetCommandTableStats(void) {
+    int numcommands = sizeof(redisCommandTable)/sizeof(struct redisCommand);
+    int j;
+
+    for (j = 0; j < numcommands; j++) {
+        struct redisCommand *c = redisCommandTable+j;
+
+        c->microseconds = 0;
+        c->calls = 0;
+    }
+}
+
 /* ====================== Commands lookup and execution ===================== */
 
 struct redisCommand *lookupCommand(sds name) {
@@ -1405,13 +1433,15 @@ sds genRedisInfoString(char *section) {
     if (allsections || !strcasecmp(section,"commandstats")) {
         if (sections++) info = sdscat(info,"\r\n");
         info = sdscatprintf(info, "# Commandstats\r\n");
-        numcommands = sizeof(readonlyCommandTable)/sizeof(struct redisCommand);
+        numcommands = sizeof(redisCommandTable)/sizeof(struct redisCommand);
         for (j = 0; j < numcommands; j++) {
-            struct redisCommand *c = readonlyCommandTable+j;
+            struct redisCommand *c = redisCommandTable+j;
 
-            if (!c->microseconds) continue;
-            info = sdscatprintf(info,"cmdstat_%s:calls=%lld,usec=%lld\r\n",
-                c->name, c->calls, c->microseconds);
+            if (!c->calls) continue;
+            info = sdscatprintf(info,
+                "cmdstat_%s:calls=%lld,usec=%lld,usec_per_call=%.2f\r\n",
+                c->name, c->calls, c->microseconds,
+                (c->calls == 0) ? 0 : ((float)c->microseconds/c->calls));
         }
     }
 
@@ -1550,6 +1580,7 @@ void freeMemoryIfNeeded(void) {
             /* Finally remove the selected key. */
             if (bestkey) {
                 robj *keyobj = createStringObject(bestkey,sdslen(bestkey));
+                propagateExpire(db,keyobj);
                 dbDelete(db,keyobj);
                 server.stat_evictedkeys++;
                 decrRefCount(keyobj);
@@ -1707,7 +1738,7 @@ void segvHandler(int sig, siginfo_t *info, void *secret) {
     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 */