diff -r a39b99ba552a -r a7c08ee1f1d7 redis-2.0.4/Makefile
--- a/redis-2.0.4/Makefile	Sun Jan 02 13:20:35 2011 -0800
+++ b/redis-2.0.4/Makefile	Sun Jan 02 16:48:37 2011 -0800
@@ -15,11 +15,16 @@
 CCOPT= $(CFLAGS) $(CCLINK) $(ARCH) $(PROF)
 DEBUG?= -g -rdynamic -ggdb 
 
+# Use Berkeley DB as backend instead of RAM
+CFLAGS += -DBERKDB -I /usr/local/include/db42
+LDFLAGS += -L /usr/local/lib/db42 -ldb
+
 INSTALL_TOP= /usr/local
 INSTALL_BIN= $(INSTALL_TOP)/bin
 INSTALL= cp -p
 
-OBJ = adlist.o ae.o anet.o dict.o redis.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o
+OBJ = adlist.o ae.o anet.o redis.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o
+OBJ += berkdb_dict.o
 BENCHOBJ = ae.o anet.o redis-benchmark.o sds.o adlist.o zmalloc.o
 CLIOBJ = anet.o sds.o adlist.o redis-cli.o zmalloc.o linenoise.o
 CHECKDUMPOBJ = redis-check-dump.o lzf_c.o lzf_d.o
@@ -60,7 +65,7 @@
 zmalloc.o: zmalloc.c config.h
 
 redis-server: $(OBJ)
-	$(CC) -o $(PRGNAME) $(CCOPT) $(DEBUG) $(OBJ)
+	$(CC) -o $(PRGNAME) $(CCOPT) $(DEBUG) $(OBJ) $(LDFLAGS)
 	@echo ""
 	@echo "Hint: To run the test-redis.tcl script is a good idea."
 	@echo "Launch the redis server with ./redis-server, then in another"
diff -r a39b99ba552a -r a7c08ee1f1d7 redis-2.0.4/berkdb_dict.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/redis-2.0.4/berkdb_dict.c	Sun Jan 02 16:48:37 2011 -0800
@@ -0,0 +1,259 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <db.h>
+#include "zmalloc.h"
+#include "dict.h"
+
+
+// XXX we have to grovel around in here for strings
+struct redisObjectVM {
+    off_t page;         /* the page at witch the object is stored on disk */
+    off_t usedpages;    /* number of pages used on disk */
+    time_t atime;       /* Last access time */
+} vm;
+
+typedef struct redisObject {
+    void *ptr;
+    unsigned char type;
+    unsigned char encoding;
+    unsigned char storage;  /* If this object is a key, where is the value?
+                             * REDIS_VM_MEMORY, REDIS_VM_SWAPPED, ... */
+    unsigned char vtype; /* If this object is a key, and value is swapped out,
+                          * this is the type of the swapped out object. */
+    int refcount;
+    /* VM fields, this are only allocated if VM is active, otherwise the
+     * object allocation function will just allocate
+     * sizeof(redisObjct) minus sizeof(redisObjectVM), so using
+     * Redis without VM active will not have any overhead. */
+    struct redisObjectVM vm;
+} robj;
+
+robj *createStringObject(char *ptr, size_t len);
+
+#define REDIS_STRING 0
+
+
+static void
+ _dictReset(dictht *ht)
+{
+    ht->table = NULL;
+    ht->size = 0;
+    ht->sizemask = 0;
+    ht->used = 0;
+}
+
+static int dbId;
+
+dict *
+dictCreate(dictType *type, void *privDataPtr)
+{
+    dict *d;
+    DB *dbp;
+    int ret;
+    char filename[512];
+
+printf("db create %d\n", dbId);
+    d = zmalloc(sizeof(*d));
+    if (d == NULL) {
+        fprintf(stderr, "panic: dict oom\n");
+        exit(1);
+    }
+
+    // Create the database handle and open the underlying database.
+    if ((ret = db_create(&dbp, NULL, 0)) != 0) {
+        fprintf(stderr, "db_create: %s\n", db_strerror(ret));
+            exit(1);
+    }
+    snprintf(filename, sizeof(filename), "test-redis-%02d.db", dbId);
+    if ((ret = dbp->open(dbp, NULL, filename, NULL, 
+        DB_HASH, DB_CREATE, 0644)) != 0) {
+        dbp->err(dbp, ret, "%s", "create berkdb");
+        exit(1);
+    }
+    dbId++;
+
+    // Initialize db structure
+    _dictReset(&d->ht[0]);
+    _dictReset(&d->ht[1]);
+    d->type = type;
+    d->rehashidx = -1;
+    d->iterators = 0;
+    d->privdata = dbp;
+
+    return d;
+}
+
+int
+dictAdd(dict *d, void *key, void *val)
+{
+    int ret;
+    DBT db_key, db_val;
+    DB *dbp = (DB *)d->privdata;
+    robj *k = (robj *)key;
+    robj *v = (robj *)val;
+
+    if (k->type != REDIS_STRING || v->type != REDIS_STRING) {
+        return DICT_ERR;
+    }
+
+    memset(&db_key, 0, sizeof(db_key));
+    memset(&db_val, 0, sizeof(db_val));
+    db_key.data = k->ptr;
+    db_key.size = strlen(k->ptr);
+    db_val.data = v->ptr;
+    db_val.size = strlen(v->ptr);
+
+printf("set %s %s\n", k->ptr, v->ptr);
+    if ((ret = dbp->put(dbp, NULL, &db_key, &db_val, DB_NOOVERWRITE)) != 0) {
+printf("exists\n");
+        return DICT_ERR;
+    }
+
+    return DICT_OK;
+}
+
+int
+dictReplace(dict *d, void *key, void *val)
+{
+    DB *dbp = (DB *)d->privdata;
+    DBT db_key, db_val;
+    robj *k = (robj *)key;
+    robj *v = (robj *)val;
+    int existed;
+
+    // Find out if it exists or if we're adding it new
+    memset(&db_key, 0, sizeof(db_key));
+    memset(&db_val, 0, sizeof(db_val));
+    db_key.data = k->ptr;
+    db_key.size = strlen(k->ptr);
+    existed = dbp->get(dbp, NULL, &db_key, &db_val, 0) == 0 ? 1 : 0;
+
+    // Overwrite it with new value
+    db_val.data = v->ptr;
+    db_val.size = strlen(v->ptr);
+    if (dbp->put(dbp, NULL, &db_key, &db_val, 0) != 0) {
+printf("fail overwrite\n");
+    }
+    return !existed;
+}
+
+int
+dictDelete(dict *d, const void *key)
+{
+    DB *dbp = (DB *)d->privdata;
+    int ret;
+    DBT db_key;
+    robj *k = (robj *)key;
+
+printf("del called\n");
+    if (k->type != REDIS_STRING) {
+        return DICT_ERR;
+    }
+    memset(&db_key, 0, sizeof(db_key));
+    db_key.data = k->ptr;
+    db_key.size = strlen(k->ptr);
+printf("del %s\n", k->ptr);
+    if ((ret = dbp->del(dbp, NULL, &db_key, 0)) != 0) {
+printf("key not found\n");
+        return DICT_ERR;
+    }
+    return DICT_OK;
+}
+
+int
+dictDeleteNoFree(dict *d, const void *key)
+{
+    return dictDelete(d, key);
+}
+
+void
+dictRelease(dict *d)
+{
+    DB *dbp = (DB *)d->privdata;
+}
+
+dictEntry *
+dictFind(dict *d, const void *key)
+{
+    dictEntry *de;
+    int ret;
+    DBT db_key, db_val;
+    DB *dbp = (DB *)d->privdata;
+    robj *k = (robj *)key;
+
+    memset(&db_key, 0, sizeof(db_key));
+    memset(&db_val, 0, sizeof(db_val));
+    db_key.data = k->ptr;
+    db_key.size = strlen(k->ptr);
+printf("get %s\n", k->ptr);
+    if ((ret = dbp->get(dbp, NULL, &db_key, &db_val, 0)) != 0) {
+printf("key not found\n");
+        return NULL;
+    }
+
+    de = zmalloc(sizeof(*de));
+    de->key = createStringObject(db_key.data, strlen(db_key.data));
+    de->val = createStringObject(db_val.data, strlen(db_val.data));
+    de->next = NULL;
+    return de;
+}
+
+dictIterator *
+dictGetIterator(dict *d)
+{
+    DB *dbp = (DB *)d->privdata;
+}
+
+dictEntry *
+dictNext(dictIterator *iter)
+{
+}
+
+void
+dictReleaseIterator(dictIterator *iter)
+{
+}
+
+dictEntry *
+dictGetRandomKey(dict *d)
+{
+    DB *dbp = (DB *)d->privdata;
+    // TODO: implement
+    printf("getrandom not implemented yet\n");
+    return NULL;
+}
+
+void
+dictPrintStats(dict *d)
+{
+    DB *dbp = (DB *)d->privdata;
+}
+
+// Delete all keys
+void
+dictEmpty(dict *d)
+{
+    DB *dbp = (DB *)d->privdata;
+}
+
+// Unused stubs below
+unsigned int
+dictGenHashFunction(const unsigned char *buf, int len)
+{
+    return 0;
+}
+
+void
+dictEnableResize(void)
+{ }
+
+void
+dictDisableResize(void)
+{ }
+
+int
+dictRehashMilliseconds(dict *d, int ms)
+{
+    return 0;
+}
diff -r a39b99ba552a -r a7c08ee1f1d7 redis-2.0.4/redis.c
--- a/redis-2.0.4/redis.c	Sun Jan 02 13:20:35 2011 -0800
+++ b/redis-2.0.4/redis.c	Sun Jan 02 16:48:37 2011 -0800
@@ -27,7 +27,11 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
+#ifndef BERKDB
 #define REDIS_VERSION "2.0.4"
+#else
+#define REDIS_VERSION "2.0.4-berkdb"
+#endif
 
 #include "fmacros.h"
 #include "config.h"
@@ -284,9 +288,11 @@
 
 typedef struct redisDb {
     dict *dict;                 /* The keyspace for this DB */
+#ifndef BERKDB
     dict *expires;              /* Timeout of keys with a timeout set */
     dict *blockingkeys;         /* Keys with clients waiting for data (BLPOP) */
     dict *io_keys;              /* Keys with clients waiting for VM I/O */
+#endif
     int id;
 } redisDb;
 
@@ -331,8 +337,10 @@
                              * is >= blockingto then the operation timed out. */
     list *io_keys;          /* Keys this client is waiting to be loaded from the
                              * swap file in order to continue. */
+#ifndef BERKDB
     dict *pubsub_channels;  /* channels a client is interested in (SUBSCRIBE) */
     list *pubsub_patterns;  /* patterns a client is interested in (SUBSCRIBE) */
+#endif
 } redisClient;
 
 struct saveparam {
@@ -561,7 +569,10 @@
 static void addReplySds(redisClient *c, sds s);
 static void incrRefCount(robj *o);
 static int rdbSaveBackground(char *filename);
-static robj *createStringObject(char *ptr, size_t len);
+#ifndef BERKDB
+static
+#endif
+robj *createStringObject(char *ptr, size_t len);
 static robj *dupStringObject(robj *o);
 static void replicationFeedSlaves(list *slaves, int dictid, robj **argv, int argc);
 static void replicationFeedMonitors(list *monitors, int dictid, robj **argv, int argc);
@@ -758,6 +769,29 @@
     {"incr",incrCommand,2,REDIS_CMD_INLINE|REDIS_CMD_DENYOOM,NULL,1,1,1},
     {"decr",decrCommand,2,REDIS_CMD_INLINE|REDIS_CMD_DENYOOM,NULL,1,1,1},
     {"mget",mgetCommand,-2,REDIS_CMD_INLINE,NULL,1,-1,1},
+    {"incrby",incrbyCommand,3,REDIS_CMD_INLINE|REDIS_CMD_DENYOOM,NULL,1,1,1},
+    {"decrby",decrbyCommand,3,REDIS_CMD_INLINE|REDIS_CMD_DENYOOM,NULL,1,1,1},
+    {"getset",getsetCommand,3,REDIS_CMD_BULK|REDIS_CMD_DENYOOM,NULL,1,1,1},
+    {"mset",msetCommand,-3,REDIS_CMD_BULK|REDIS_CMD_DENYOOM,NULL,1,-1,2},
+    {"msetnx",msetnxCommand,-3,REDIS_CMD_BULK|REDIS_CMD_DENYOOM,NULL,1,-1,2},
+    {"randomkey",randomkeyCommand,1,REDIS_CMD_INLINE,NULL,0,0,0},
+    {"select",selectCommand,2,REDIS_CMD_INLINE,NULL,0,0,0},
+    {"move",moveCommand,3,REDIS_CMD_INLINE,NULL,1,1,1},
+    {"rename",renameCommand,3,REDIS_CMD_INLINE,NULL,1,1,1},
+    {"renamenx",renamenxCommand,3,REDIS_CMD_INLINE,NULL,1,1,1},
+    {"keys",keysCommand,2,REDIS_CMD_INLINE,NULL,0,0,0},
+    {"dbsize",dbsizeCommand,1,REDIS_CMD_INLINE,NULL,0,0,0},
+    {"auth",authCommand,2,REDIS_CMD_INLINE,NULL,0,0,0},
+    {"ping",pingCommand,1,REDIS_CMD_INLINE,NULL,0,0,0},
+    {"echo",echoCommand,2,REDIS_CMD_BULK,NULL,0,0,0},
+    {"flushdb",flushdbCommand,1,REDIS_CMD_INLINE,NULL,0,0,0},
+    {"flushall",flushallCommand,1,REDIS_CMD_INLINE,NULL,0,0,0},
+    {"info",infoCommand,1,REDIS_CMD_INLINE,NULL,0,0,0},
+    {"monitor",monitorCommand,1,REDIS_CMD_INLINE,NULL,0,0,0},
+    {"slaveof",slaveofCommand,3,REDIS_CMD_INLINE,NULL,0,0,0},
+    {"debug",debugCommand,-2,REDIS_CMD_INLINE,NULL,0,0,0},
+    {"config",configCommand,-2,REDIS_CMD_BULK,NULL,0,0,0},
+#ifndef BERKDB
     {"rpush",rpushCommand,3,REDIS_CMD_BULK|REDIS_CMD_DENYOOM,NULL,1,1,1},
     {"lpush",lpushCommand,3,REDIS_CMD_BULK|REDIS_CMD_DENYOOM,NULL,1,1,1},
     {"rpop",rpopCommand,2,REDIS_CMD_INLINE,NULL,1,1,1},
@@ -812,23 +846,8 @@
     {"hvals",hvalsCommand,2,REDIS_CMD_INLINE,NULL,1,1,1},
     {"hgetall",hgetallCommand,2,REDIS_CMD_INLINE,NULL,1,1,1},
     {"hexists",hexistsCommand,3,REDIS_CMD_BULK,NULL,1,1,1},
-    {"incrby",incrbyCommand,3,REDIS_CMD_INLINE|REDIS_CMD_DENYOOM,NULL,1,1,1},
-    {"decrby",decrbyCommand,3,REDIS_CMD_INLINE|REDIS_CMD_DENYOOM,NULL,1,1,1},
-    {"getset",getsetCommand,3,REDIS_CMD_BULK|REDIS_CMD_DENYOOM,NULL,1,1,1},
-    {"mset",msetCommand,-3,REDIS_CMD_BULK|REDIS_CMD_DENYOOM,NULL,1,-1,2},
-    {"msetnx",msetnxCommand,-3,REDIS_CMD_BULK|REDIS_CMD_DENYOOM,NULL,1,-1,2},
-    {"randomkey",randomkeyCommand,1,REDIS_CMD_INLINE,NULL,0,0,0},
-    {"select",selectCommand,2,REDIS_CMD_INLINE,NULL,0,0,0},
-    {"move",moveCommand,3,REDIS_CMD_INLINE,NULL,1,1,1},
-    {"rename",renameCommand,3,REDIS_CMD_INLINE,NULL,1,1,1},
-    {"renamenx",renamenxCommand,3,REDIS_CMD_INLINE,NULL,1,1,1},
     {"expire",expireCommand,3,REDIS_CMD_INLINE,NULL,0,0,0},
     {"expireat",expireatCommand,3,REDIS_CMD_INLINE,NULL,0,0,0},
-    {"keys",keysCommand,2,REDIS_CMD_INLINE,NULL,0,0,0},
-    {"dbsize",dbsizeCommand,1,REDIS_CMD_INLINE,NULL,0,0,0},
-    {"auth",authCommand,2,REDIS_CMD_INLINE,NULL,0,0,0},
-    {"ping",pingCommand,1,REDIS_CMD_INLINE,NULL,0,0,0},
-    {"echo",echoCommand,2,REDIS_CMD_BULK,NULL,0,0,0},
     {"save",saveCommand,1,REDIS_CMD_INLINE,NULL,0,0,0},
     {"bgsave",bgsaveCommand,1,REDIS_CMD_INLINE,NULL,0,0,0},
     {"bgrewriteaof",bgrewriteaofCommand,1,REDIS_CMD_INLINE,NULL,0,0,0},
@@ -839,20 +858,14 @@
     {"exec",execCommand,1,REDIS_CMD_INLINE|REDIS_CMD_DENYOOM,execBlockClientOnSwappedKeys,0,0,0},
     {"discard",discardCommand,1,REDIS_CMD_INLINE,NULL,0,0,0},
     {"sync",syncCommand,1,REDIS_CMD_INLINE,NULL,0,0,0},
-    {"flushdb",flushdbCommand,1,REDIS_CMD_INLINE,NULL,0,0,0},
-    {"flushall",flushallCommand,1,REDIS_CMD_INLINE,NULL,0,0,0},
-    {"sort",sortCommand,-2,REDIS_CMD_INLINE|REDIS_CMD_DENYOOM,NULL,1,1,1},
-    {"info",infoCommand,1,REDIS_CMD_INLINE,NULL,0,0,0},
-    {"monitor",monitorCommand,1,REDIS_CMD_INLINE,NULL,0,0,0},
-    {"ttl",ttlCommand,2,REDIS_CMD_INLINE,NULL,1,1,1},
-    {"slaveof",slaveofCommand,3,REDIS_CMD_INLINE,NULL,0,0,0},
-    {"debug",debugCommand,-2,REDIS_CMD_INLINE,NULL,0,0,0},
-    {"config",configCommand,-2,REDIS_CMD_BULK,NULL,0,0,0},
     {"subscribe",subscribeCommand,-2,REDIS_CMD_INLINE,NULL,0,0,0},
     {"unsubscribe",unsubscribeCommand,-1,REDIS_CMD_INLINE,NULL,0,0,0},
     {"psubscribe",psubscribeCommand,-2,REDIS_CMD_INLINE,NULL,0,0,0},
     {"punsubscribe",punsubscribeCommand,-1,REDIS_CMD_INLINE,NULL,0,0,0},
     {"publish",publishCommand,3,REDIS_CMD_BULK|REDIS_CMD_FORCE_REPLICATION,NULL,0,0,0},
+    {"sort",sortCommand,-2,REDIS_CMD_INLINE|REDIS_CMD_DENYOOM,NULL,1,1,1},
+    {"ttl",ttlCommand,2,REDIS_CMD_INLINE,NULL,1,1,1},
+#endif // BERKDB
     {NULL,NULL,0,0,NULL,0,0,0}
 };
 
@@ -1261,8 +1274,10 @@
         if (server.maxidletime &&
             !(c->flags & REDIS_SLAVE) &&    /* no timeout for slaves */
             !(c->flags & REDIS_MASTER) &&   /* no timeout for masters */
+#ifndef BERKDB
             dictSize(c->pubsub_channels) == 0 && /* no timeout for pubsub */
             listLength(c->pubsub_patterns) == 0 &&
+#endif
             (now - c->lastinteraction > server.maxidletime))
         {
             redisLog(REDIS_VERBOSE,"Closing idle client");
@@ -1270,7 +1285,9 @@
         } else if (c->flags & REDIS_BLOCKED) {
             if (c->blockingto != 0 && c->blockingto < now) {
                 addReply(c,shared.nullmultibulk);
+#ifndef BERKDB
                 unblockClientWaitingData(c);
+#endif
             }
         }
     }
@@ -1290,12 +1307,14 @@
 static void tryResizeHashTables(void) {
     int j;
 
+#ifndef BERKDB
     for (j = 0; j < server.dbnum; j++) {
         if (htNeedsResize(server.db[j].dict))
             dictResize(server.db[j].dict);
         if (htNeedsResize(server.db[j].expires))
             dictResize(server.db[j].expires);
     }
+#endif
 }
 
 /* Our hash table implementation performs rehashing incrementally while
@@ -1436,7 +1455,11 @@
 
         size = dictSlots(server.db[j].dict);
         used = dictSize(server.db[j].dict);
+#ifndef BERKDB
         vkeys = dictSize(server.db[j].expires);
+#else
+        vkeys = 0;
+#endif
         if (!(loops % 50) && (used || vkeys)) {
             redisLog(REDIS_VERBOSE,"DB %d: %lld keys (%lld volatile) in %lld slots HT.",j,used,vkeys,size);
             /* dictPrintStats(server.dict); */
@@ -1466,6 +1489,7 @@
     if ((server.maxidletime && !(loops % 100)) || server.blpop_blocked_clients)
         closeTimedoutClients();
 
+#ifndef BERKDB
     /* Check if a background saving or AOF rewrite in progress terminated */
     if (server.bgsavechildpid != -1 || server.bgrewritechildpid != -1) {
         int statloc;
@@ -1564,6 +1588,7 @@
             if (retval == REDIS_ERR || server.vm_max_threads > 0) break;
         }
     }
+#endif // BERKDB
 
     /* Check if we should connect to a MASTER */
     if (server.replstate == REDIS_REPL_CONNECT && !(loops % 10)) {
@@ -1757,16 +1782,20 @@
     }
     for (j = 0; j < server.dbnum; j++) {
         server.db[j].dict = dictCreate(&dbDictType,NULL);
+#ifndef BERKDB
         server.db[j].expires = dictCreate(&keyptrDictType,NULL);
         server.db[j].blockingkeys = dictCreate(&keylistDictType,NULL);
         if (server.vm_enabled)
             server.db[j].io_keys = dictCreate(&keylistDictType,NULL);
+#endif
         server.db[j].id = j;
     }
+#ifndef BERKDB
     server.pubsub_channels = dictCreate(&keylistDictType,NULL);
     server.pubsub_patterns = listCreate();
     listSetFreeMethod(server.pubsub_patterns,freePubsubPattern);
     listSetMatchMethod(server.pubsub_patterns,listMatchPubsubPattern);
+#endif
     server.cronloops = 0;
     server.bgsavechildpid = -1;
     server.bgrewritechildpid = -1;
@@ -1803,7 +1832,9 @@
     for (j = 0; j < server.dbnum; j++) {
         removed += dictSize(server.db[j].dict);
         dictEmpty(server.db[j].dict);
+#ifndef BERKDB
         dictEmpty(server.db[j].expires);
+#endif
     }
     return removed;
 }
@@ -2021,6 +2052,7 @@
      * this, because this call adds the READABLE event. */
     sdsfree(c->querybuf);
     c->querybuf = NULL;
+#ifndef BERKDB
     if (c->flags & REDIS_BLOCKED)
         unblockClientWaitingData(c);
 
@@ -2029,6 +2061,7 @@
     pubsubUnsubscribeAllPatterns(c,0);
     dictRelease(c->pubsub_channels);
     listRelease(c->pubsub_patterns);
+#endif
     /* Obvious cleanup */
     aeDeleteFileEvent(server.el,c->fd,AE_READABLE);
     aeDeleteFileEvent(server.el,c->fd,AE_WRITABLE);
@@ -2053,7 +2086,9 @@
         } else {
             while (listLength(c->io_keys)) {
                 ln = listFirst(c->io_keys);
+#ifndef BERKDB
                 dontWaitForSwappedKey(c,ln->value);
+#endif
             }
         }
         server.vm_blocked_clients--;
@@ -2432,6 +2467,7 @@
      * First we try to free some memory if possible (if there are volatile
      * keys in the dataset). If there are not the only thing we can do
      * is returning an error. */
+#ifndef BERKDB
     if (server.maxmemory) freeMemoryIfNeeded();
     if (server.maxmemory && (cmd->flags & REDIS_CMD_DENYOOM) &&
         zmalloc_used_memory() > server.maxmemory)
@@ -2450,14 +2486,17 @@
         resetClient(c);
         return 1;
     }
+#endif // BERKDB
 
     /* Exec the command */
     if (c->flags & REDIS_MULTI && cmd->proc != execCommand && cmd->proc != discardCommand) {
         queueMultiCommand(c,cmd);
         addReply(c,shared.queued);
     } else {
+#ifndef BERKDB
         if (server.vm_enabled && server.vm_max_threads > 0 &&
             blockClientOnSwappedKeys(c,cmd)) return 1;
+#endif
         call(c,cmd);
     }
 
@@ -2759,10 +2798,12 @@
     c->blockingkeysnum = 0;
     c->io_keys = listCreate();
     listSetFreeMethod(c->io_keys,decrRefCount);
+#ifndef BERKDB
     c->pubsub_channels = dictCreate(&setDictType,NULL);
     c->pubsub_patterns = listCreate();
     listSetFreeMethod(c->pubsub_patterns,decrRefCount);
     listSetMatchMethod(c->pubsub_patterns,listMatchObjects);
+#endif
     listAddNodeTail(server.clients,c);
     initClientMultiState(c);
     return c;
@@ -2942,7 +2983,10 @@
     return o;
 }
 
-static robj *createStringObject(char *ptr, size_t len) {
+#ifndef BERKDB
+static
+#endif
+robj *createStringObject(char *ptr, size_t len) {
     return createObject(REDIS_STRING,sdsnewlen(ptr,len));
 }
 
@@ -3086,6 +3130,7 @@
         robj *key = dictGetEntryKey(de);
         robj *val = dictGetEntryVal(de);
 
+#ifndef BERKDB
         if (server.vm_enabled) {
             if (key->storage == REDIS_VM_MEMORY ||
                 key->storage == REDIS_VM_SWAPPING)
@@ -3109,6 +3154,7 @@
                 if (notify) handleClientsBlockedOnSwappedKey(db,key);
             }
         }
+#endif // BERKDB
         return val;
     } else {
         return NULL;
@@ -3153,8 +3199,10 @@
      * it's count. This may happen when we get the object reference directly
      * from the hash table with dictRandomKey() or dict iterators */
     incrRefCount(key);
+#ifndef BERKDB
     if (server.vm_enabled) handleClientsBlockedOnSwappedKey(db,key);
     if (dictSize(db->expires)) dictDelete(db->expires,key);
+#endif
     retval = dictDelete(db->dict,key);
     decrRefCount(key);
 
@@ -4005,8 +4053,10 @@
         o = (type == REDIS_LIST) ? createListObject() : createSetObject();
         /* It's faster to expand the dict to the right size asap in order
          * to avoid rehashing */
+#ifndef BERKDB
         if (type == REDIS_SET && listlen > DICT_HT_INITIAL_SIZE)
             dictExpand(o->ptr,listlen);
+#endif
         /* Load every single element of the list/set */
         while(listlen--) {
             robj *ele;
@@ -6826,7 +6876,9 @@
 static void flushdbCommand(redisClient *c) {
     server.dirty += dictSize(c->db->dict);
     dictEmpty(c->db->dict);
+#ifndef BERKDB
     dictEmpty(c->db->expires);
+#endif
     addReply(c,shared.ok);
 }
 
@@ -7356,7 +7408,11 @@
         long long keys, vkeys;
 
         keys = dictSize(server.db[j].dict);
+#ifndef BERKDB
         vkeys = dictSize(server.db[j].expires);
+#else
+        vkeys = 0;
+#endif
         if (keys || vkeys) {
             info = sdscatprintf(info, "db%d:keys=%lld,expires=%lld\r\n",
                 j, keys, vkeys);
@@ -7384,6 +7440,7 @@
 }
 
 /* ================================= Expire ================================= */
+#ifndef BERKDB
 static int removeExpire(redisDb *db, robj *key) {
     if (dictDelete(db->expires,key) == DICT_OK) {
         return 1;
@@ -7445,6 +7502,29 @@
     return dictDelete(db->dict,key) == DICT_OK;
 }
 
+#else // BERKDB
+static int removeExpire(redisDb *db, robj *key)
+{
+    return 0;
+}
+static int setExpire(redisDb *db, robj *key, time_t when)
+{
+    return 0;
+}
+static time_t getExpire(redisDb *db, robj *key)
+{
+    return -1;
+}
+static int expireIfNeeded(redisDb *db, robj *key)
+{
+    return 0;
+}
+static int deleteIfVolatile(redisDb *db, robj *key)
+{
+    return 0;
+}
+#endif // BERKDB
+
 static void expireGenericCommand(redisClient *c, robj *key, robj *param, long offset) {
     dictEntry *de;
     time_t seconds;
@@ -7601,6 +7681,7 @@
     server.dirty++;
 }
 
+#ifndef BERKDB
 /* =========================== Blocking Operations  ========================= */
 
 /* Currently Redis blocking operations support is limited to list POP ops,
@@ -7744,6 +7825,7 @@
     unblockClientWaitingData(receiver);
     return 1;
 }
+#endif // BERKDB
 
 /* Blocking RPOP/LPOP */
 static void blockingPopGenericCommand(redisClient *c, int where) {
@@ -7812,7 +7894,9 @@
     /* If the list is empty or the key does not exists we must block */
     timeout = lltimeout;
     if (timeout > 0) timeout += time(NULL);
+#ifndef BERKDB
     blockForKeys(c,c->argv+1,c->argc-2,timeout);
+#endif
 }
 
 static void blpopCommand(redisClient *c) {
@@ -8223,6 +8307,7 @@
  * the server will start refusing commands that will enlarge even more the
  * memory usage.
  */
+#ifndef BERKDB
 static void freeMemoryIfNeeded(void) {
     while (server.maxmemory && zmalloc_used_memory() > server.maxmemory) {
         int j, k, freed = 0;
@@ -8254,6 +8339,7 @@
         if (!freed) return; /* nothing to free... */
     }
 }
+#endif // BERKDB
 
 /* ============================== Append Only file ========================== */
 
@@ -9481,7 +9567,9 @@
             db = j->db;
             freeIOJob(j);
             /* Handle clients waiting for this key to be loaded. */
+#ifndef BERKDB
             handleClientsBlockedOnSwappedKey(db,key);
+#endif
         } else if (j->type == REDIS_IOJOB_PREPARE_SWAP) {
             /* Now we know the amount of pages required to swap this object.
              * Let's find some space for it, and queue this task again
@@ -9794,6 +9882,7 @@
     return REDIS_OK;
 }
 
+#ifndef BERKDB
 /* ============ Virtual Memory - Blocking clients on missing keys =========== */
 
 /* This function makes the clinet 'c' waiting for the key 'key' to be loaded.
@@ -10006,6 +10095,7 @@
         }
     }
 }
+#endif // BERKDB
 
 /* =========================== Remote Configuration ========================= */
 
@@ -10214,8 +10304,8 @@
         (char*) c->argv[1]->ptr));
 }
 
+#ifndef BERKDB
 /* =========================== Pubsub implementation ======================== */
-
 static void freePubsubPattern(void *p) {
     pubsubPattern *pat = p;
 
@@ -10473,6 +10563,7 @@
     int receivers = pubsubPublishMessage(c->argv[1],c->argv[2]);
     addReplyLongLong(c,receivers);
 }
+#endif // BERKDB
 
 /* ================================= Debugging ============================== */
 
