/*
- * Copyright (c) 2009-2010, Salvatore Sanfilippo <antirez at gmail dot com>
+ * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
#include <math.h>
#include <sys/resource.h>
#include <sys/utsname.h>
+#include <lmdb.h>
/* Our shared "common" objects */
return memcmp(key1, key2, l1) == 0;
}
-/* A case insensitive version used for the command lookup table. */
+/* A case insensitive version used for the command lookup table and other
+ * places where case insensitive non binary-safe comparison is needed. */
int dictSdsKeyCaseCompare(void *privdata, const void *key1,
const void *key2)
{
dictRedisObjectDestructor /* val destructor */
};
+/* server.lua_scripts sha (as sds string) -> scripts (as robj) cache. */
+dictType shaScriptObjectDictType = {
+ dictSdsCaseHash, /* hash function */
+ NULL, /* key dup */
+ NULL, /* val dup */
+ dictSdsKeyCaseCompare, /* key compare */
+ dictSdsDestructor, /* key destructor */
+ dictRedisObjectDestructor /* val destructor */
+};
+
/* Db->expires */
dictType keyptrDictType = {
dictSdsHash, /* hash function */
if (pid == server.rdb_child_pid) {
backgroundSaveDoneHandler(exitcode,bysignal);
- } else {
+ } else if (pid == server.aof_child_pid) {
backgroundRewriteDoneHandler(exitcode,bysignal);
+ } else {
+ redisLog(REDIS_WARNING,
+ "Warning, detected child with unmatched pid: %ld",
+ (long)pid);
}
updateDictResizePolicy();
}
"-READONLY You can't write against a read only slave.\r\n"));
shared.oomerr = createObject(REDIS_STRING,sdsnew(
"-OOM command not allowed when used memory > 'maxmemory'.\r\n"));
+ shared.execaborterr = createObject(REDIS_STRING,sdsnew(
+ "-EXECABORT Transaction discarded because of previous errors.\r\n"));
shared.space = createObject(REDIS_STRING,sdsnew(" "));
shared.colon = createObject(REDIS_STRING,sdsnew(":"));
shared.plus = createObject(REDIS_STRING,sdsnew("+"));
server.pidfile = zstrdup("/var/run/redis.pid");
server.rdb_filename = zstrdup("dump.rdb");
server.aof_filename = zstrdup("appendonly.aof");
+ server.mdb_state = REDIS_MDB_OFF;
+ server.mdb_environment = zstrdup("archive");
+ server.mdb_mapsize = 10485760;
server.requirepass = NULL;
server.rdb_compression = 1;
server.rdb_checksum = 1;
}
}
+ if (server.aof_state == REDIS_MDB_ON) {
+ int retval = startKeyArchive();
+ if (retval != 0) {
+ redisLog(REDIS_WARNING, "Can't open the key-archive environment: %s",
+ mdb_strerror(retval));
+ exit(1);
+ }
+ }
+
/* 32 bit instances are limited to 4GB of address space, so if there is
* no explicit limit in the user provided configuration we set a limit
* at 3 GB using maxmemory with 'noeviction' policy'. This avoids
}
/* If this function gets called we already read a whole
- * command, argments are in the client argv/argc fields.
+ * command, arguments are in the client argv/argc fields.
* processCommand() execute the command or prepare the
* server for a bulk read from the client.
*
* such as wrong arity, bad command name and so forth. */
c->cmd = c->lastcmd = lookupCommand(c->argv[0]->ptr);
if (!c->cmd) {
+ flagTransaction(c);
addReplyErrorFormat(c,"unknown command '%s'",
(char*)c->argv[0]->ptr);
return REDIS_OK;
} else if ((c->cmd->arity > 0 && c->cmd->arity != c->argc) ||
(c->argc < -c->cmd->arity)) {
+ flagTransaction(c);
addReplyErrorFormat(c,"wrong number of arguments for '%s' command",
c->cmd->name);
return REDIS_OK;
/* Check if the user is authenticated */
if (server.requirepass && !c->authenticated && c->cmd->proc != authCommand)
{
+ flagTransaction(c);
addReplyError(c,"operation not permitted");
return REDIS_OK;
}
if (server.maxmemory) {
int retval = freeMemoryIfNeeded();
if ((c->cmd->flags & REDIS_CMD_DENYOOM) && retval == REDIS_ERR) {
+ flagTransaction(c);
addReply(c, shared.oomerr);
return REDIS_OK;
}
&& server.lastbgsave_status == REDIS_ERR &&
c->cmd->flags & REDIS_CMD_WRITE)
{
+ flagTransaction(c);
addReply(c, shared.bgsaveerr);
return REDIS_OK;
}
server.repl_serve_stale_data == 0 &&
!(c->cmd->flags & REDIS_CMD_STALE))
{
+ flagTransaction(c);
addReply(c, shared.masterdownerr);
return REDIS_OK;
}
c->argc == 2 &&
tolower(((char*)c->argv[1]->ptr)[0]) == 'k'))
{
+ flagTransaction(c);
addReply(c, shared.slowscripterr);
return REDIS_OK;
}
(long)server.unixtime-server.repl_down_since);
}
info = sdscatprintf(info,
- "slave_priority:%d\r\n", server.slave_priority);
+ "slave_priority:%d\r\n"
+ "slave_read_only:%d\r\n",
+ server.slave_priority,
+ server.repl_slave_ro);
}
info = sdscatprintf(info,
"connected_slaves:%lu\r\n",
}
void monitorCommand(redisClient *c) {
- /* ignore MONITOR if aleady slave or in monitor mode */
+ /* ignore MONITOR if already slave or in monitor mode */
if (c->flags & REDIS_SLAVE) return;
c->flags |= (REDIS_SLAVE|REDIS_MONITOR);
de = dictGetRandomKey(dict);
thiskey = dictGetKey(de);
- /* When policy is volatile-lru we need an additonal lookup
+ /* When policy is volatile-lru we need an additional lookup
* to locate the real key, as dict is set to db->expires. */
if (server.maxmemory_policy == REDIS_MAXMEMORY_VOLATILE_LRU)
de = dictFind(db->dict, thiskey);
long long delta;
robj *keyobj = createStringObject(bestkey,sdslen(bestkey));
+ int archived = archive(db, keyobj);
+ redisAssert(archived != 0);
propagateExpire(db,keyobj);
/* We compute the amount of memory freed by dbDelete() alone.
* It is possible that actually the memory needed to propagate
redisAsciiArt();
if (!server.sentinel_mode) {
- /* Things only needed when not runnign in Sentinel mode. */
+ /* Things only needed when not running in Sentinel mode. */
redisLog(REDIS_WARNING,"Server started, Redis version " REDIS_VERSION);
#ifdef __linux__
linuxOvercommitMemoryWarning();