if (getLongLongFromObject(o,&ll) == REDIS_ERR ||
ll < 0 || ll > LONG_MAX) goto badfmt;
server.maxidletime = ll;
+ } else if (!strcasecmp(c->argv[2]->ptr,"keyarchive")) {
+ int enable = yesnotoi(o->ptr);
+
+ if (enable == -1) goto badfmt;
+ if (enable == 0 && server.mdb_state != REDIS_MDB_OFF) {
+ stopKeyArchive();
+ } else if (enable && server.mdb_state == REDIS_MDB_OFF) {
+ if (startKeyArchive() != 0) {
+ addReplyError(c,
+ "Unable to turn on MDB. Check server logs.");
+ return;
+ }
+ }
} else if (!strcasecmp(c->argv[2]->ptr,"appendfsync")) {
if (!strcasecmp(o->ptr,"no")) {
server.aof_fsync = AOF_FSYNC_NO;
return;
}
-void mdb(void) {
- int ret;
+void stopKeyArchive(void) {
+ redisAssert(server.mdb_state == REDIS_MDB_ON);
+ redisAssert(env != NULL);
- if (env != NULL)
- return;
+ mdb_dbi_close(env, dbi);
+ mdb_env_close(env);
+ env = NULL;
+
+ server.mdb_state = REDIS_MDB_OFF;
+}
+
+int startKeyArchive(void) {
+ redisAssert(server.mdb_state == REDIS_MDB_OFF);
+ redisAssert(env == NULL);
+
+ int ret;
ret = mdb_env_create(&env);
- redisAssert(ret == 0);
+ if (ret != 0) return ret;
ret = mdb_env_set_mapsize(env, server.mdb_mapsize);
- redisAssert(ret == 0);
+ if (ret != 0) return ret;
ret = mdb_env_set_maxdbs(env, 1);
- redisAssert(ret == 0);
+ if (ret != 0) return ret;
mkdir(server.mdb_environment, 0644);
ret = mdb_env_open(env, server.mdb_environment, MDB_FIXEDMAP | MDB_NOSYNC, 0664);
- redisAssert(ret == 0);
+ if (ret != 0) return ret;
MDB_txn *txn;
ret = mdb_txn_begin(env, NULL, 0, &txn);
- redisAssert(ret == 0);
+ if (ret != 0) return ret;
ret = mdb_open(txn, NULL, 0, &dbi);
- redisAssert(ret == 0);
+ if (ret != 0) return ret;
mdb_txn_commit(txn);
+
+ server.mdb_state = REDIS_MDB_ON;
+ return 0;
}
int archive(redisDb *db, robj *key) {
if (server.mdb_state == REDIS_MDB_OFF)
return 1;
-
- mdb();
+ redisAssert(env != NULL);
MDB_val kval;
kval.mv_data = key->ptr;
int ret;
- mdb();
-
MDB_val kval;
kval.mv_data = key->ptr;
kval.mv_size = sdslen((sds)key->ptr);
#include <math.h>
#include <sys/resource.h>
#include <sys/utsname.h>
+#include <lmdb.h>
/* Our shared "common" objects */
}
}
+ 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
unsigned int GetKeysInSlot(unsigned int hashslot, robj **keys, unsigned int count);
/* external database archival */
+void stopKeyArchive(void);
+int startKeyArchive(void);
robj *recover(redisDb *db, robj *key);
int archive(redisDb *db, robj *key);