Skip to content

Commit

Permalink
source reshaped a bit to play well with a bgsaving thread, still work…
Browse files Browse the repository at this point in the history
… to do, does not compile.
  • Loading branch information
antirez committed Jan 7, 2011
1 parent cb9b35c commit 36c17a5
Show file tree
Hide file tree
Showing 8 changed files with 103 additions and 54 deletions.
2 changes: 2 additions & 0 deletions TODO
Expand Up @@ -15,6 +15,8 @@ DISKSTORE TODO
* Check that 00/00 and ff/ff exist at startup, otherwise exit with error.
* Implement sync flush option, where data is written synchronously on disk when a command is executed.
* Implement MULTI/EXEC as transaction abstract API to diskstore.c, with transaction_start, transaction_end, and a journal to recover.
* Stop BGSAVE thread on shutdown and any other condition where the child is killed during normal bgsave.
* Use a mutex to log on the file, so that we don't get overlapping messages, or even better make sure to use a single write against it.

REPLICATION
===========
Expand Down
7 changes: 2 additions & 5 deletions src/aof.c
Expand Up @@ -585,10 +585,7 @@ void aofRemoveTempFile(pid_t childpid) {

/* A background append only file rewriting (BGREWRITEAOF) terminated its work.
* Handle this. */
void backgroundRewriteDoneHandler(int statloc) {
int exitcode = WEXITSTATUS(statloc);
int bysignal = WIFSIGNALED(statloc);

void backgroundRewriteDoneHandler(int exitcode, int bysignal) {
if (!bysignal && exitcode == 0) {
int fd;
char tmpfile[256];
Expand Down Expand Up @@ -636,7 +633,7 @@ void backgroundRewriteDoneHandler(int statloc) {
} else {
redisLog(REDIS_WARNING,
"Background append only file rewriting terminated by signal %d",
WTERMSIG(statloc));
bysitnal);
}
cleanup:
sdsfree(server.bgrewritebuf);
Expand Down
24 changes: 0 additions & 24 deletions src/db.c
Expand Up @@ -379,30 +379,6 @@ void typeCommand(redisClient *c) {
addReplyStatus(c,type);
}

void saveCommand(redisClient *c) {
if (server.bgsavechildpid != -1) {
addReplyError(c,"Background save already in progress");
return;
}
if (rdbSave(server.dbfilename) == REDIS_OK) {
addReply(c,shared.ok);
} else {
addReply(c,shared.err);
}
}

void bgsaveCommand(redisClient *c) {
if (server.bgsavechildpid != -1) {
addReplyError(c,"Background save already in progress");
return;
}
if (rdbSaveBackground(server.dbfilename) == REDIS_OK) {
addReplyStatus(c,"Background saving started");
} else {
addReply(c,shared.err);
}
}

void shutdownCommand(redisClient *c) {
if (prepareForShutdown() == REDIS_OK)
exit(0);
Expand Down
26 changes: 22 additions & 4 deletions src/diskstore.c
Expand Up @@ -349,11 +349,16 @@ void dsFlushDb(int dbid) {
}
}

int dsRdbSave(char *filename) {
char tmpfile[256];
void *dsRdbSave_thread(void *arg) {
char tmpfile[256], *filename = (char*)arg;
int j, i;
time_t now = time(NULL);

/* Change state to ACTIVE, to signal there is a saving thead working. */
pthread_mutex_lock(&server.bgsavethread_mutex);
server.bgsavethread_state = REDIS_BGSAVE_THREAD_ACTIVE;
pthread_mutex_unlock(&server.bgsavethread_mutex);

snprintf(tmpfile,256,"temp-%d.rdb", (int) getpid());
fp = fopen(tmpfile,"w");
if (!fp) {
Expand All @@ -377,6 +382,7 @@ int dsRdbSave(char *filename) {
fflush(fp);
fsync(fileno(fp));
fclose(fp);
zfree(filename);

/* Use RENAME to make sure the DB file is changed atomically only
* if the generate DB file is ok. */
Expand All @@ -386,12 +392,24 @@ int dsRdbSave(char *filename) {
return REDIS_ERR;
}
redisLog(REDIS_NOTICE,"DB saved on disk");
server.dirty = 0;
server.lastsave = time(NULL);
return REDIS_OK;

werr:
zfree(filename);
fclose(fp);
unlink(tmpfile);
redisLog(REDIS_WARNING,"Write error saving DB on disk: %s", strerror(errno));
}

int dsRdbSave(char *filename) {
pthread_t thread;

if (pthread_create(&thread,NULL,dsRdbSave_thread,zstrdup(filename)) != 0) {
redisLog(REDIS_WARNING,"Can't create diskstore BGSAVE thread: %s",
strerror(errno));
return REDIS_ERR;
} else {
server.bgsavethread = thread;
return REDIS_OK;
}
}
1 change: 1 addition & 0 deletions src/dscache.c
Expand Up @@ -132,6 +132,7 @@ void dsInit(void) {
server.io_ready_clients = listCreate();
pthread_mutex_init(&server.io_mutex,NULL);
pthread_cond_init(&server.io_condvar,NULL);
pthread_mutex_init(&server.bgsavethread_mutex,NULL);
server.io_active_threads = 0;
if (pipe(pipefds) == -1) {
redisLog(REDIS_WARNING,"Unable to intialized DS: pipe(2): %s. Exiting."
Expand Down
48 changes: 36 additions & 12 deletions src/rdb.c
Expand Up @@ -496,22 +496,23 @@ int rdbSave(char *filename) {
int rdbSaveBackground(char *filename) {
pid_t childpid;

if (server.bgsavechildpid != -1) return REDIS_ERR;
if (server.bgsavechildpid != -1 ||
server.bgsavethread != (pthread_t) -1) return REDIS_ERR;

server.dirty_before_bgsave = server.dirty;

if (server.ds_enabled) {
cacheForcePointInTime();
return dsRdbSave(filename);
}

if ((childpid = fork()) == 0) {
int retval;

/* Child */
if (server.ipfd > 0) close(server.ipfd);
if (server.sofd > 0) close(server.sofd);
if (server.ds_enabled) {
cacheForcePointInTime();
dsRdbSave(filename);
} else {
rdbSave(filename);
}
retval = rdbSave(filename);
_exit((retval == REDIS_OK) ? 0 : 1);
} else {
/* Parent */
Expand Down Expand Up @@ -950,10 +951,7 @@ int rdbLoad(char *filename) {
}

/* A background saving child (BGSAVE) terminated its work. Handle this. */
void backgroundSaveDoneHandler(int statloc) {
int exitcode = WEXITSTATUS(statloc);
int bysignal = WIFSIGNALED(statloc);

void backgroundSaveDoneHandler(int exitcode, int bysignal) {
if (!bysignal && exitcode == 0) {
redisLog(REDIS_NOTICE,
"Background saving terminated with success");
Expand All @@ -963,11 +961,37 @@ void backgroundSaveDoneHandler(int statloc) {
redisLog(REDIS_WARNING, "Background saving error");
} else {
redisLog(REDIS_WARNING,
"Background saving terminated by signal %d", WTERMSIG(statloc));
"Background saving terminated by signal %d", bysignal);
rdbRemoveTempFile(server.bgsavechildpid);
}
server.bgsavechildpid = -1;
server.bgsavethread = (pthread_t) -1;
server.bgsavethread_state = REDIS_BGSAVE_THREAD_UNACTIVE;
/* Possibly there are slaves waiting for a BGSAVE in order to be served
* (the first stage of SYNC is a bulk transfer of dump.rdb) */
updateSlavesWaitingBgsave(exitcode == 0 ? REDIS_OK : REDIS_ERR);
}

void saveCommand(redisClient *c) {
if (server.bgsavechildpid != -1 || server.bgsavethread != (pthread-t)-1) {
addReplyError(c,"Background save already in progress");
return;
}
if (rdbSave(server.dbfilename) == REDIS_OK) {
addReply(c,shared.ok);
} else {
addReply(c,shared.err);
}
}

void bgsaveCommand(redisClient *c) {
if (server.bgsavechildpid != -1 || server.bgsavethread != (pthread-t)-1) {
addReplyError(c,"Background save already in progress");
return;
}
if (rdbSaveBackground(server.dbfilename) == REDIS_OK) {
addReplyStatus(c,"Background saving started");
} else {
addReply(c,shared.err);
}
}
24 changes: 22 additions & 2 deletions src/redis.c
Expand Up @@ -589,13 +589,31 @@ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {
pid_t pid;

if ((pid = wait3(&statloc,WNOHANG,NULL)) != 0) {
int exitcode = WEXITSTATUS(statloc);
int bysignal = 0;

if (WIFSIGNALED(statloc)) bysignal = WTERMSIG(statloc);

if (pid == server.bgsavechildpid) {
backgroundSaveDoneHandler(statloc);
backgroundSaveDoneHandler(exitcode,bysignal);
} else {
backgroundRewriteDoneHandler(statloc);
backgroundRewriteDoneHandler(exitcode,bysignal);
}
updateDictResizePolicy();
}
if (server.bgsavethread != (pthread_t) -1) {
int state;

pthread_mutex_lock(&server.bgsavethread_mutex);
state = server.bgsavethread_state;
pthread_mutex_unlock(&server.bgsavethread_mutex);

if (state == REDIS_BGSAVE_DONE_OK || state == REDIS_BGSAVE_DONE_ERR)
{
backgroundSaveDoneHandler(
(state == REDIS_BGSAVE_DONE_OK) ? 0 : 1, 0);
}
}
} else if (!server.ds_enabled) {
/* If there is not a background saving in progress check if
* we have to save now */
Expand Down Expand Up @@ -867,6 +885,8 @@ void initServer() {
server.cronloops = 0;
server.bgsavechildpid = -1;
server.bgrewritechildpid = -1;
server.bgsavethread_state = REDIS_BGSAVE_THREAD_UNACTIVE;
server.bgsavethread = (pthread_t) -1;
server.bgrewritebuf = sdsempty();
server.aofbuf = sdsempty();
server.lastsave = time(NULL);
Expand Down
25 changes: 18 additions & 7 deletions src/redis.h
Expand Up @@ -203,6 +203,12 @@
#define REDIS_MAXMEMORY_ALLKEYS_RANDOM 4
#define REDIS_MAXMEMORY_NO_EVICTION 5

/* Diskstore background saving thread states */
#define REDIS_BGSAVE_THREAD_UNACTIVE 0
#define REDIS_BGSAVE_THREAD_ACTIVE 1
#define REDIS_BGSAVE_THREAD_DONE_OK 2
#define REDIS_BGSAVE_THREAD_DONE_ERR 3

/* We can print the stacktrace, so our assert is defined this way: */
#define redisAssert(_e) ((_e)?(void)0 : (_redisAssert(#_e,__FILE__,__LINE__),_exit(1)))
#define redisPanic(_e) _redisPanic(#_e,__FILE__,__LINE__),_exit(1)
Expand Down Expand Up @@ -390,25 +396,30 @@ struct redisServer {
int appendfsync;
int no_appendfsync_on_rewrite;
int shutdown_asap;
int activerehashing;
char *requirepass;
/* Persistence */
time_t lastfsync;
int appendfd;
int appendseldb;
char *pidfile;
pid_t bgsavechildpid;
pid_t bgrewritechildpid;
int bgsavethread_state;
pthread_mutex_t bgsavethread_mutex;
pthread_t bgsavethread;
sds bgrewritebuf; /* buffer taken by parent during oppend only rewrite */
sds aofbuf; /* AOF buffer, written before entering the event loop */
struct saveparam *saveparams;
int saveparamslen;
char *dbfilename;
int rdbcompression;
char *appendfilename;
/* Logging */
char *logfile;
int syslog_enabled;
char *syslog_ident;
int syslog_facility;
char *dbfilename;
char *appendfilename;
char *requirepass;
int rdbcompression;
int activerehashing;
/* Replication related */
int isslave;
/* Slave specific fields */
Expand Down Expand Up @@ -745,7 +756,7 @@ int rdbSaveObject(FILE *fp, robj *o);
off_t rdbSavedObjectLen(robj *o);
off_t rdbSavedObjectPages(robj *o);
robj *rdbLoadObject(int type, FILE *fp);
void backgroundSaveDoneHandler(int statloc);
void backgroundSaveDoneHandler(int exitcode, int bysignal) {
int rdbSaveKeyValuePair(FILE *fp, redisDb *db, robj *key, robj *val, time_t now);
int rdbLoadType(FILE *fp);
time_t rdbLoadTime(FILE *fp);
Expand All @@ -759,7 +770,7 @@ int rewriteAppendOnlyFileBackground(void);
int loadAppendOnlyFile(char *filename);
void stopAppendOnly(void);
int startAppendOnly(void);
void backgroundRewriteDoneHandler(int statloc);
void backgroundRewriteDoneHandler(int exitcode, int bysignal);

/* Sorted sets data type */
zskiplist *zslCreate(void);
Expand Down

0 comments on commit 36c17a5

Please sign in to comment.