/* 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},
/*============================ 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
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 */
}
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);
}
}
+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) {
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));
}
}
/* Finally remove the selected key. */
if (bestkey) {
robj *keyobj = createStringObject(bestkey,sdslen(bestkey));
+ propagateExpire(db,keyobj);
dbDelete(db,keyobj);
server.stat_evictedkeys++;
decrRefCount(keyobj);
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 */