vm swap file creation, and some basic configuration

This commit is contained in:
antirez 2010-01-04 16:01:40 -05:00
parent 5dc70bff2e
commit 75680a3c37

74
redis.c
View File

@ -152,6 +152,12 @@
#define REDIS_RDB_ENC_INT32 2 /* 32 bit signed integer */ #define REDIS_RDB_ENC_INT32 2 /* 32 bit signed integer */
#define REDIS_RDB_ENC_LZF 3 /* string compressed with FASTLZ */ #define REDIS_RDB_ENC_LZF 3 /* string compressed with FASTLZ */
/* Virtual memory object->where field. */
#define REDIS_VM_MEMORY 0 /* The object is on memory */
#define REDIS_VM_SWAPPED 1 /* The object is on disk */
#define REDIS_VM_SWAPPING 2 /* Redis is swapping this object on disk */
#define REDIS_VM_LOADING 3 /* Redis is loading this object from disk */
/* Client flags */ /* Client flags */
#define REDIS_CLOSE 1 /* This client connection should be closed ASAP */ #define REDIS_CLOSE 1 /* This client connection should be closed ASAP */
#define REDIS_SLAVE 2 /* This client is a slave server */ #define REDIS_SLAVE 2 /* This client is a slave server */
@ -207,12 +213,26 @@ static void _redisAssert(char *estr);
/*================================= Data types ============================== */ /*================================= Data types ============================== */
/* A redis object, that is a type able to hold a string / list / set */ /* A redis object, that is a type able to hold a string / list / set */
/* The VM object structure */
struct redisObjectVM {
off_t offset; /* the page at witch the object is stored on disk */
int pages; /* number of pages used on disk */
} vm;
/* The actual Redis Object */
typedef struct redisObject { typedef struct redisObject {
void *ptr; void *ptr;
unsigned char type; unsigned char type;
unsigned char encoding; unsigned char encoding;
unsigned char notused[2]; unsigned char storage; /* where? REDIS_VM_MEMORY, REDIS_VM_SWAPPED, ... */
unsigned char notused;
int refcount; 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;
/* Macro used to initalize a Redis object allocated on the stack. /* Macro used to initalize a Redis object allocated on the stack.
@ -339,6 +359,16 @@ struct redisServer {
int sort_desc; int sort_desc;
int sort_alpha; int sort_alpha;
int sort_bypattern; int sort_bypattern;
/* Virtual memory configuration */
int vm_enabled;
off_t vm_page_size;
off_t vm_pages;
long vm_max_memory;
/* Virtual memory state */
FILE *vm_fp;
int vm_fd;
off_t vm_next_page; /* Next probably empty page */
off_t vm_near_pages; /* Number of pages allocated sequentially */
}; };
typedef void redisCommandProc(redisClient *c); typedef void redisCommandProc(redisClient *c);
@ -447,6 +477,7 @@ static void freeClientMultiState(redisClient *c);
static void queueMultiCommand(redisClient *c, struct redisCommand *cmd); static void queueMultiCommand(redisClient *c, struct redisCommand *cmd);
static void unblockClient(redisClient *c); static void unblockClient(redisClient *c);
static int handleClientsWaitingListPush(redisClient *c, robj *key, robj *ele); static int handleClientsWaitingListPush(redisClient *c, robj *key, robj *ele);
static void vmInit(void);
static void authCommand(redisClient *c); static void authCommand(redisClient *c);
static void pingCommand(redisClient *c); static void pingCommand(redisClient *c);
@ -1207,6 +1238,11 @@ static void initServerConfig() {
server.maxclients = 0; server.maxclients = 0;
server.blockedclients = 0; server.blockedclients = 0;
server.maxmemory = 0; server.maxmemory = 0;
server.vm_enabled = 0;
server.vm_page_size = 256; /* 256 bytes per page */
server.vm_pages = 1024*1024*100; /* 104 millions of pages */
server.vm_max_memory = 1024LL*1024*1024*1; /* 1 GB of RAM */
resetServerSaveParams(); resetServerSaveParams();
appendServerSaveParams(60*60,1); /* save after 1 hour and 1 change */ appendServerSaveParams(60*60,1); /* save after 1 hour and 1 change */
@ -1273,6 +1309,8 @@ static void initServer() {
exit(1); exit(1);
} }
} }
if (server.vm_enabled) vmInit();
} }
/* Empty the whole database */ /* Empty the whole database */
@ -1439,6 +1477,10 @@ static void loadServerConfig(char *filename) {
server.pidfile = zstrdup(argv[1]); server.pidfile = zstrdup(argv[1]);
} else if (!strcasecmp(argv[0],"dbfilename") && argc == 2) { } else if (!strcasecmp(argv[0],"dbfilename") && argc == 2) {
server.dbfilename = zstrdup(argv[1]); server.dbfilename = zstrdup(argv[1]);
} else if (!strcasecmp(argv[0],"vm-enabled") && argc == 2) {
if ((server.vm_enabled = yesnotoi(argv[1])) == -1) {
err = "argument must be 'yes' or 'no'"; goto loaderr;
}
} else { } else {
err = "Bad directive or wrong number of arguments"; goto loaderr; err = "Bad directive or wrong number of arguments"; goto loaderr;
} }
@ -2194,7 +2236,11 @@ static robj *createObject(int type, void *ptr) {
o = listNodeValue(head); o = listNodeValue(head);
listDelNode(server.objfreelist,head); listDelNode(server.objfreelist,head);
} else { } else {
if (server.vm_enabled) {
o = zmalloc(sizeof(*o)); o = zmalloc(sizeof(*o));
} else {
o = zmalloc(sizeof(*o)-sizeof(struct redisObjectVM));
}
} }
o->type = type; o->type = type;
o->encoding = REDIS_ENCODING_RAW; o->encoding = REDIS_ENCODING_RAW;
@ -6532,6 +6578,32 @@ static void aofRemoveTempFile(pid_t childpid) {
unlink(tmpfile); unlink(tmpfile);
} }
/* =============================== Virtual Memory =========================== */
static void vmInit(void) {
off_t totsize;
server.vm_fp = fopen("/tmp/redisvm","w+b");
if (server.vm_fp == NULL) {
redisLog(REDIS_WARNING,"Impossible to open the swap file. Exiting.");
exit(1);
}
server.vm_fd = fileno(server.vm_fp);
server.vm_next_page = 0;
server.vm_near_pages = 0;
totsize = server.vm_pages*server.vm_page_size;
redisLog(REDIS_NOTICE,"Allocating %lld bytes of swap file",totsize);
if (ftruncate(server.vm_fd,totsize) == -1) {
redisLog(REDIS_WARNING,"Can't ftruncate swap file: %s. Exiting.",
strerror(errno));
exit(1);
} else {
redisLog(REDIS_NOTICE,"Swap file allocated with success");
}
/* Try to remove the swap file, so the OS will really delete it from the
* file system when Redis exists. */
unlink("/tmp/redisvm");
}
/* ================================= Debugging ============================== */ /* ================================= Debugging ============================== */
static void debugCommand(redisClient *c) { static void debugCommand(redisClient *c) {