From: antirez Date: Wed, 21 Dec 2011 16:13:31 +0000 (+0100) Subject: Merge remote-tracking branch 'origin/unstable' into unstable X-Git-Url: https://git.saurik.com/redis.git/commitdiff_plain/d334281c802bc94e99475557ed341d356af0ab54?hp=7d5209d7d36cf1f3978f3ca09a831f0c1a9f26e2 Merge remote-tracking branch 'origin/unstable' into unstable --- diff --git a/src/aof.c b/src/aof.c index bfa8163d..25d6f454 100644 --- a/src/aof.c +++ b/src/aof.c @@ -19,42 +19,48 @@ void aof_background_fsync(int fd) { /* Called when the user switches from "appendonly yes" to "appendonly no" * at runtime using the CONFIG command. */ void stopAppendOnly(void) { + redisAssert(server.aof_state != REDIS_AOF_OFF); flushAppendOnlyFile(1); - aof_fsync(server.appendfd); - close(server.appendfd); + aof_fsync(server.aof_fd); + close(server.aof_fd); - server.appendfd = -1; - server.appendseldb = -1; - server.appendonly = 0; + server.aof_fd = -1; + server.aof_selected_db = -1; + server.aof_state = REDIS_AOF_OFF; /* rewrite operation in progress? kill it, wait child exit */ - if (server.bgrewritechildpid != -1) { + if (server.aof_child_pid != -1) { int statloc; - if (kill(server.bgrewritechildpid,SIGKILL) != -1) + redisLog(REDIS_NOTICE,"Killing running AOF rewrite child: %ld", + (long) server.aof_child_pid); + if (kill(server.aof_child_pid,SIGKILL) != -1) wait3(&statloc,0,NULL); /* reset the buffer accumulating changes while the child saves */ - sdsfree(server.bgrewritebuf); - server.bgrewritebuf = sdsempty(); - server.bgrewritechildpid = -1; + sdsfree(server.aof_rewrite_buf); + server.aof_rewrite_buf = sdsempty(); + aofRemoveTempFile(server.aof_child_pid); + server.aof_child_pid = -1; } } /* Called when the user switches from "appendonly no" to "appendonly yes" * at runtime using the CONFIG command. */ int startAppendOnly(void) { - server.appendonly = 1; - server.lastfsync = time(NULL); - server.appendfd = open(server.appendfilename,O_WRONLY|O_APPEND|O_CREAT,0644); - if (server.appendfd == -1) { - redisLog(REDIS_WARNING,"Used tried to switch on AOF via CONFIG, but I can't open the AOF file: %s",strerror(errno)); + server.aof_last_fsync = time(NULL); + server.aof_fd = open(server.aof_filename,O_WRONLY|O_APPEND|O_CREAT,0644); + redisAssert(server.aof_state == REDIS_AOF_OFF); + if (server.aof_fd == -1) { + redisLog(REDIS_WARNING,"Redis needs to enable the AOF but can't open the append only file: %s",strerror(errno)); return REDIS_ERR; } if (rewriteAppendOnlyFileBackground() == REDIS_ERR) { - server.appendonly = 0; - close(server.appendfd); - redisLog(REDIS_WARNING,"User tried turning on AOF with CONFIG SET but I can't trigger a background AOF rewrite operation. Check the above logs for more info about the error."); + close(server.aof_fd); + redisLog(REDIS_WARNING,"Redis needs to enable the AOF but can't trigger a background AOF rewrite operation. Check the above logs for more info about the error."); return REDIS_ERR; } + /* We correctly switched on AOF, now wait for the rerwite to be complete + * in order to append data on disk. */ + server.aof_state = REDIS_AOF_WAIT_REWRITE; return REDIS_OK; } @@ -80,12 +86,12 @@ void flushAppendOnlyFile(int force) { ssize_t nwritten; int sync_in_progress = 0; - if (sdslen(server.aofbuf) == 0) return; + if (sdslen(server.aof_buf) == 0) return; - if (server.appendfsync == APPENDFSYNC_EVERYSEC) + if (server.aof_fsync == AOF_FSYNC_EVERYSEC) sync_in_progress = bioPendingJobsOfType(REDIS_BIO_AOF_FSYNC) != 0; - if (server.appendfsync == APPENDFSYNC_EVERYSEC && !force) { + if (server.aof_fsync == AOF_FSYNC_EVERYSEC && !force) { /* With this append fsync policy we do background fsyncing. * If the fsync is still in progress we can try to delay * the write for a couple of seconds. */ @@ -114,45 +120,50 @@ void flushAppendOnlyFile(int force) { * While this will save us against the server being killed I don't think * there is much to do about the whole server stopping for power problems * or alike */ - nwritten = write(server.appendfd,server.aofbuf,sdslen(server.aofbuf)); - if (nwritten != (signed)sdslen(server.aofbuf)) { + nwritten = write(server.aof_fd,server.aof_buf,sdslen(server.aof_buf)); + if (nwritten != (signed)sdslen(server.aof_buf)) { /* Ooops, we are in troubles. The best thing to do for now is * aborting instead of giving the illusion that everything is * working as expected. */ if (nwritten == -1) { redisLog(REDIS_WARNING,"Exiting on error writing to the append-only file: %s",strerror(errno)); } else { - redisLog(REDIS_WARNING,"Exiting on short write while writing to the append-only file: %s",strerror(errno)); + redisLog(REDIS_WARNING,"Exiting on short write while writing to " + "the append-only file: %s (nwritten=%ld, " + "expected=%ld)", + strerror(errno), + (long)nwritten, + (long)sdslen(server.aof_buf)); } exit(1); } - server.appendonly_current_size += nwritten; + server.aof_current_size += nwritten; /* Re-use AOF buffer when it is small enough. The maximum comes from the * arena size of 4k minus some overhead (but is otherwise arbitrary). */ - if ((sdslen(server.aofbuf)+sdsavail(server.aofbuf)) < 4000) { - sdsclear(server.aofbuf); + if ((sdslen(server.aof_buf)+sdsavail(server.aof_buf)) < 4000) { + sdsclear(server.aof_buf); } else { - sdsfree(server.aofbuf); - server.aofbuf = sdsempty(); + sdsfree(server.aof_buf); + server.aof_buf = sdsempty(); } /* Don't fsync if no-appendfsync-on-rewrite is set to yes and there are * children doing I/O in the background. */ - if (server.no_appendfsync_on_rewrite && - (server.bgrewritechildpid != -1 || server.bgsavechildpid != -1)) + if (server.aof_no_fsync_on_rewrite && + (server.aof_child_pid != -1 || server.rdb_child_pid != -1)) return; /* Perform the fsync if needed. */ - if (server.appendfsync == APPENDFSYNC_ALWAYS) { + if (server.aof_fsync == AOF_FSYNC_ALWAYS) { /* aof_fsync is defined as fdatasync() for Linux in order to avoid * flushing metadata. */ - aof_fsync(server.appendfd); /* Let's try to get this data on the disk */ - server.lastfsync = server.unixtime; - } else if ((server.appendfsync == APPENDFSYNC_EVERYSEC && - server.unixtime > server.lastfsync)) { - if (!sync_in_progress) aof_background_fsync(server.appendfd); - server.lastfsync = server.unixtime; + aof_fsync(server.aof_fd); /* Let's try to get this data on the disk */ + server.aof_last_fsync = server.unixtime; + } else if ((server.aof_fsync == AOF_FSYNC_EVERYSEC && + server.unixtime > server.aof_last_fsync)) { + if (!sync_in_progress) aof_background_fsync(server.aof_fd); + server.aof_last_fsync = server.unixtime; } } @@ -224,13 +235,13 @@ void feedAppendOnlyFile(struct redisCommand *cmd, int dictid, robj **argv, int a /* The DB this command was targetting is not the same as the last command * we appendend. To issue a SELECT command is needed. */ - if (dictid != server.appendseldb) { + if (dictid != server.aof_selected_db) { char seldb[64]; snprintf(seldb,sizeof(seldb),"%d",dictid); buf = sdscatprintf(buf,"*2\r\n$6\r\nSELECT\r\n$%lu\r\n%s\r\n", (unsigned long)strlen(seldb),seldb); - server.appendseldb = dictid; + server.aof_selected_db = dictid; } if (cmd->proc == expireCommand || cmd->proc == pexpireCommand || @@ -255,14 +266,15 @@ void feedAppendOnlyFile(struct redisCommand *cmd, int dictid, robj **argv, int a /* Append to the AOF buffer. This will be flushed on disk just before * of re-entering the event loop, so before the client will get a * positive reply about the operation performed. */ - server.aofbuf = sdscatlen(server.aofbuf,buf,sdslen(buf)); + if (server.aof_state == REDIS_AOF_ON) + server.aof_buf = sdscatlen(server.aof_buf,buf,sdslen(buf)); /* If a background append only file rewriting is in progress we want to * accumulate the differences between the child DB and the current one * in a buffer, so that when the child process will do its work we * can append the differences to the new append only file. */ - if (server.bgrewritechildpid != -1) - server.bgrewritebuf = sdscatlen(server.bgrewritebuf,buf,sdslen(buf)); + if (server.aof_child_pid != -1) + server.aof_rewrite_buf = sdscatlen(server.aof_rewrite_buf,buf,sdslen(buf)); sdsfree(buf); } @@ -305,11 +317,11 @@ int loadAppendOnlyFile(char *filename) { struct redisClient *fakeClient; FILE *fp = fopen(filename,"r"); struct redis_stat sb; - int appendonly = server.appendonly; + int old_aof_state = server.aof_state; long loops = 0; if (fp && redis_fstat(fileno(fp),&sb) != -1 && sb.st_size == 0) { - server.appendonly_current_size = 0; + server.aof_current_size = 0; fclose(fp); return REDIS_ERR; } @@ -321,7 +333,7 @@ int loadAppendOnlyFile(char *filename) { /* Temporarily disable AOF, to prevent EXEC from feeding a MULTI * to the same file we're about to read. */ - server.appendonly = 0; + server.aof_state = REDIS_AOF_OFF; fakeClient = createFakeClient(); startLoading(fp); @@ -390,10 +402,10 @@ int loadAppendOnlyFile(char *filename) { fclose(fp); freeFakeClient(fakeClient); - server.appendonly = appendonly; + server.aof_state = old_aof_state; stopLoading(); aofUpdateCurrentSize(); - server.auto_aofrewrite_base_size = server.appendonly_current_size; + server.aof_rewrite_base_size = server.aof_current_size; return REDIS_OK; readerr: @@ -436,8 +448,8 @@ int rewriteListObject(rio *r, robj *key, robj *o) { while(ziplistGet(p,&vstr,&vlen,&vlong)) { if (count == 0) { - int cmd_items = (items > REDIS_AOFREWRITE_ITEMS_PER_CMD) ? - REDIS_AOFREWRITE_ITEMS_PER_CMD : items; + int cmd_items = (items > REDIS_AOF_REWRITE_ITEMS_PER_CMD) ? + REDIS_AOF_REWRITE_ITEMS_PER_CMD : items; if (rioWriteBulkCount(r,'*',2+cmd_items) == 0) return 0; if (rioWriteBulkString(r,"RPUSH",5) == 0) return 0; @@ -449,7 +461,7 @@ int rewriteListObject(rio *r, robj *key, robj *o) { if (rioWriteBulkLongLong(r,vlong) == 0) return 0; } p = ziplistNext(zl,p); - if (++count == REDIS_AOFREWRITE_ITEMS_PER_CMD) count = 0; + if (++count == REDIS_AOF_REWRITE_ITEMS_PER_CMD) count = 0; items--; } } else if (o->encoding == REDIS_ENCODING_LINKEDLIST) { @@ -462,15 +474,15 @@ int rewriteListObject(rio *r, robj *key, robj *o) { robj *eleobj = listNodeValue(ln); if (count == 0) { - int cmd_items = (items > REDIS_AOFREWRITE_ITEMS_PER_CMD) ? - REDIS_AOFREWRITE_ITEMS_PER_CMD : items; + int cmd_items = (items > REDIS_AOF_REWRITE_ITEMS_PER_CMD) ? + REDIS_AOF_REWRITE_ITEMS_PER_CMD : items; if (rioWriteBulkCount(r,'*',2+cmd_items) == 0) return 0; if (rioWriteBulkString(r,"RPUSH",5) == 0) return 0; if (rioWriteBulkObject(r,key) == 0) return 0; } if (rioWriteBulkObject(r,eleobj) == 0) return 0; - if (++count == REDIS_AOFREWRITE_ITEMS_PER_CMD) count = 0; + if (++count == REDIS_AOF_REWRITE_ITEMS_PER_CMD) count = 0; items--; } } else { @@ -490,15 +502,15 @@ int rewriteSetObject(rio *r, robj *key, robj *o) { while(intsetGet(o->ptr,ii++,&llval)) { if (count == 0) { - int cmd_items = (items > REDIS_AOFREWRITE_ITEMS_PER_CMD) ? - REDIS_AOFREWRITE_ITEMS_PER_CMD : items; + int cmd_items = (items > REDIS_AOF_REWRITE_ITEMS_PER_CMD) ? + REDIS_AOF_REWRITE_ITEMS_PER_CMD : items; if (rioWriteBulkCount(r,'*',2+cmd_items) == 0) return 0; if (rioWriteBulkString(r,"SADD",4) == 0) return 0; if (rioWriteBulkObject(r,key) == 0) return 0; } if (rioWriteBulkLongLong(r,llval) == 0) return 0; - if (++count == REDIS_AOFREWRITE_ITEMS_PER_CMD) count = 0; + if (++count == REDIS_AOF_REWRITE_ITEMS_PER_CMD) count = 0; items--; } } else if (o->encoding == REDIS_ENCODING_HT) { @@ -508,15 +520,15 @@ int rewriteSetObject(rio *r, robj *key, robj *o) { while((de = dictNext(di)) != NULL) { robj *eleobj = dictGetKey(de); if (count == 0) { - int cmd_items = (items > REDIS_AOFREWRITE_ITEMS_PER_CMD) ? - REDIS_AOFREWRITE_ITEMS_PER_CMD : items; + int cmd_items = (items > REDIS_AOF_REWRITE_ITEMS_PER_CMD) ? + REDIS_AOF_REWRITE_ITEMS_PER_CMD : items; if (rioWriteBulkCount(r,'*',2+cmd_items) == 0) return 0; if (rioWriteBulkString(r,"SADD",4) == 0) return 0; if (rioWriteBulkObject(r,key) == 0) return 0; } if (rioWriteBulkObject(r,eleobj) == 0) return 0; - if (++count == REDIS_AOFREWRITE_ITEMS_PER_CMD) count = 0; + if (++count == REDIS_AOF_REWRITE_ITEMS_PER_CMD) count = 0; items--; } dictReleaseIterator(di); @@ -549,8 +561,8 @@ int rewriteSortedSetObject(rio *r, robj *key, robj *o) { score = zzlGetScore(sptr); if (count == 0) { - int cmd_items = (items > REDIS_AOFREWRITE_ITEMS_PER_CMD) ? - REDIS_AOFREWRITE_ITEMS_PER_CMD : items; + int cmd_items = (items > REDIS_AOF_REWRITE_ITEMS_PER_CMD) ? + REDIS_AOF_REWRITE_ITEMS_PER_CMD : items; if (rioWriteBulkCount(r,'*',2+cmd_items*2) == 0) return 0; if (rioWriteBulkString(r,"ZADD",4) == 0) return 0; @@ -563,7 +575,7 @@ int rewriteSortedSetObject(rio *r, robj *key, robj *o) { if (rioWriteBulkLongLong(r,vll) == 0) return 0; } zzlNext(zl,&eptr,&sptr); - if (++count == REDIS_AOFREWRITE_ITEMS_PER_CMD) count = 0; + if (++count == REDIS_AOF_REWRITE_ITEMS_PER_CMD) count = 0; items--; } } else if (o->encoding == REDIS_ENCODING_SKIPLIST) { @@ -576,8 +588,8 @@ int rewriteSortedSetObject(rio *r, robj *key, robj *o) { double *score = dictGetVal(de); if (count == 0) { - int cmd_items = (items > REDIS_AOFREWRITE_ITEMS_PER_CMD) ? - REDIS_AOFREWRITE_ITEMS_PER_CMD : items; + int cmd_items = (items > REDIS_AOF_REWRITE_ITEMS_PER_CMD) ? + REDIS_AOF_REWRITE_ITEMS_PER_CMD : items; if (rioWriteBulkCount(r,'*',2+cmd_items*2) == 0) return 0; if (rioWriteBulkString(r,"ZADD",4) == 0) return 0; @@ -585,7 +597,7 @@ int rewriteSortedSetObject(rio *r, robj *key, robj *o) { } if (rioWriteBulkDouble(r,*score) == 0) return 0; if (rioWriteBulkObject(r,eleobj) == 0) return 0; - if (++count == REDIS_AOFREWRITE_ITEMS_PER_CMD) count = 0; + if (++count == REDIS_AOF_REWRITE_ITEMS_PER_CMD) count = 0; items--; } dictReleaseIterator(di); @@ -607,8 +619,8 @@ int rewriteHashObject(rio *r, robj *key, robj *o) { while((p = zipmapNext(p,&field,&flen,&val,&vlen)) != NULL) { if (count == 0) { - int cmd_items = (items > REDIS_AOFREWRITE_ITEMS_PER_CMD) ? - REDIS_AOFREWRITE_ITEMS_PER_CMD : items; + int cmd_items = (items > REDIS_AOF_REWRITE_ITEMS_PER_CMD) ? + REDIS_AOF_REWRITE_ITEMS_PER_CMD : items; if (rioWriteBulkCount(r,'*',2+cmd_items*2) == 0) return 0; if (rioWriteBulkString(r,"HMSET",5) == 0) return 0; @@ -616,7 +628,7 @@ int rewriteHashObject(rio *r, robj *key, robj *o) { } if (rioWriteBulkString(r,(char*)field,flen) == 0) return 0; if (rioWriteBulkString(r,(char*)val,vlen) == 0) return 0; - if (++count == REDIS_AOFREWRITE_ITEMS_PER_CMD) count = 0; + if (++count == REDIS_AOF_REWRITE_ITEMS_PER_CMD) count = 0; items--; } } else { @@ -628,8 +640,8 @@ int rewriteHashObject(rio *r, robj *key, robj *o) { robj *val = dictGetVal(de); if (count == 0) { - int cmd_items = (items > REDIS_AOFREWRITE_ITEMS_PER_CMD) ? - REDIS_AOFREWRITE_ITEMS_PER_CMD : items; + int cmd_items = (items > REDIS_AOF_REWRITE_ITEMS_PER_CMD) ? + REDIS_AOF_REWRITE_ITEMS_PER_CMD : items; if (rioWriteBulkCount(r,'*',2+cmd_items*2) == 0) return 0; if (rioWriteBulkString(r,"HMSET",5) == 0) return 0; @@ -637,7 +649,7 @@ int rewriteHashObject(rio *r, robj *key, robj *o) { } if (rioWriteBulkObject(r,field) == 0) return 0; if (rioWriteBulkObject(r,val) == 0) return 0; - if (++count == REDIS_AOFREWRITE_ITEMS_PER_CMD) count = 0; + if (++count == REDIS_AOF_REWRITE_ITEMS_PER_CMD) count = 0; items--; } dictReleaseIterator(di); @@ -650,7 +662,7 @@ int rewriteHashObject(rio *r, robj *key, robj *o) { * * In order to minimize the number of commands needed in the rewritten * log Redis uses variadic commands when possible, such as RPUSH, SADD - * and ZADD. However at max REDIS_AOFREWRITE_ITEMS_PER_CMD items per time + * and ZADD. However at max REDIS_AOF_REWRITE_ITEMS_PER_CMD items per time * are inserted using a single command. */ int rewriteAppendOnlyFile(char *filename) { dictIterator *di = NULL; @@ -666,7 +678,7 @@ int rewriteAppendOnlyFile(char *filename) { snprintf(tmpfile,256,"temp-rewriteaof-%d.aof", (int) getpid()); fp = fopen(tmpfile,"w"); if (!fp) { - redisLog(REDIS_WARNING, "Failed rewriting the append only file: %s", strerror(errno)); + redisLog(REDIS_WARNING, "Opening the temp file for AOF rewrite in rewriteAppendOnlyFile(): %s", strerror(errno)); return REDIS_ERR; } @@ -758,10 +770,10 @@ werr: * 1) The user calls BGREWRITEAOF * 2) Redis calls this function, that forks(): * 2a) the child rewrite the append only file in a temp file. - * 2b) the parent accumulates differences in server.bgrewritebuf. + * 2b) the parent accumulates differences in server.aof_rewrite_buf. * 3) When the child finished '2a' exists. * 4) The parent will trap the exit code, if it's OK, will append the - * data accumulated into server.bgrewritebuf into the temp file, and + * data accumulated into server.aof_rewrite_buf into the temp file, and * finally will rename(2) the temp file in the actual file name. * The the new file is reopened as the new append only file. Profit! */ @@ -769,7 +781,7 @@ int rewriteAppendOnlyFileBackground(void) { pid_t childpid; long long start; - if (server.bgrewritechildpid != -1) return REDIS_ERR; + if (server.aof_child_pid != -1) return REDIS_ERR; start = ustime(); if ((childpid = fork()) == 0) { char tmpfile[256]; @@ -794,24 +806,24 @@ int rewriteAppendOnlyFileBackground(void) { } redisLog(REDIS_NOTICE, "Background append only file rewriting started by pid %d",childpid); - server.aofrewrite_scheduled = 0; - server.bgrewritechildpid = childpid; + server.aof_rewrite_scheduled = 0; + server.aof_child_pid = childpid; updateDictResizePolicy(); /* We set appendseldb to -1 in order to force the next call to the * feedAppendOnlyFile() to issue a SELECT command, so the differences - * accumulated by the parent into server.bgrewritebuf will start + * accumulated by the parent into server.aof_rewrite_buf will start * with a SELECT statement and it will be safe to merge. */ - server.appendseldb = -1; + server.aof_selected_db = -1; return REDIS_OK; } return REDIS_OK; /* unreached */ } void bgrewriteaofCommand(redisClient *c) { - if (server.bgrewritechildpid != -1) { + if (server.aof_child_pid != -1) { addReplyError(c,"Background append only file rewriting already in progress"); - } else if (server.bgsavechildpid != -1) { - server.aofrewrite_scheduled = 1; + } else if (server.rdb_child_pid != -1) { + server.aof_rewrite_scheduled = 1; addReplyStatus(c,"Background append only file rewriting scheduled"); } else if (rewriteAppendOnlyFileBackground() == REDIS_OK) { addReplyStatus(c,"Background append only file rewriting started"); @@ -827,18 +839,18 @@ void aofRemoveTempFile(pid_t childpid) { unlink(tmpfile); } -/* Update the server.appendonly_current_size filed explicitly using stat(2) +/* Update the server.aof_current_size filed explicitly using stat(2) * to check the size of the file. This is useful after a rewrite or after * a restart, normally the size is updated just adding the write length * to the current lenght, that is much faster. */ void aofUpdateCurrentSize(void) { struct redis_stat sb; - if (redis_fstat(server.appendfd,&sb) == -1) { - redisLog(REDIS_WARNING,"Unable to check the AOF length: %s", + if (redis_fstat(server.aof_fd,&sb) == -1) { + redisLog(REDIS_WARNING,"Unable to obtain the AOF file length. stat: %s", strerror(errno)); } else { - server.appendonly_current_size = sb.st_size; + server.aof_current_size = sb.st_size; } } @@ -857,7 +869,7 @@ void backgroundRewriteDoneHandler(int exitcode, int bysignal) { /* Flush the differences accumulated by the parent to the * rewritten AOF. */ snprintf(tmpfile,256,"temp-rewriteaof-bg-%d.aof", - (int)server.bgrewritechildpid); + (int)server.aof_child_pid); newfd = open(tmpfile,O_WRONLY|O_APPEND); if (newfd == -1) { redisLog(REDIS_WARNING, @@ -865,8 +877,8 @@ void backgroundRewriteDoneHandler(int exitcode, int bysignal) { goto cleanup; } - nwritten = write(newfd,server.bgrewritebuf,sdslen(server.bgrewritebuf)); - if (nwritten != (signed)sdslen(server.bgrewritebuf)) { + nwritten = write(newfd,server.aof_rewrite_buf,sdslen(server.aof_rewrite_buf)); + if (nwritten != (signed)sdslen(server.aof_rewrite_buf)) { if (nwritten == -1) { redisLog(REDIS_WARNING, "Error trying to flush the parent diff to the rewritten AOF: %s", strerror(errno)); @@ -908,13 +920,13 @@ void backgroundRewriteDoneHandler(int exitcode, int bysignal) { * guarantee atomicity for this switch has already happened by then, so * we don't care what the outcome or duration of that close operation * is, as long as the file descriptor is released again. */ - if (server.appendfd == -1) { + if (server.aof_fd == -1) { /* AOF disabled */ /* Don't care if this fails: oldfd will be -1 and we handle that. * One notable case of -1 return is if the old file does * not exist. */ - oldfd = open(server.appendfilename,O_RDONLY|O_NONBLOCK); + oldfd = open(server.aof_filename,O_RDONLY|O_NONBLOCK); } else { /* AOF enabled */ oldfd = -1; /* We'll set this to the current AOF filedes later. */ @@ -922,37 +934,40 @@ void backgroundRewriteDoneHandler(int exitcode, int bysignal) { /* Rename the temporary file. This will not unlink the target file if * it exists, because we reference it with "oldfd". */ - if (rename(tmpfile,server.appendfilename) == -1) { + if (rename(tmpfile,server.aof_filename) == -1) { redisLog(REDIS_WARNING, - "Error trying to rename the temporary AOF: %s", strerror(errno)); + "Error trying to rename the temporary AOF file: %s", strerror(errno)); close(newfd); if (oldfd != -1) close(oldfd); goto cleanup; } - if (server.appendfd == -1) { + if (server.aof_fd == -1) { /* AOF disabled, we don't need to set the AOF file descriptor * to this new file, so we can close it. */ close(newfd); } else { /* AOF enabled, replace the old fd with the new one. */ - oldfd = server.appendfd; - server.appendfd = newfd; - if (server.appendfsync == APPENDFSYNC_ALWAYS) + oldfd = server.aof_fd; + server.aof_fd = newfd; + if (server.aof_fsync == AOF_FSYNC_ALWAYS) aof_fsync(newfd); - else if (server.appendfsync == APPENDFSYNC_EVERYSEC) + else if (server.aof_fsync == AOF_FSYNC_EVERYSEC) aof_background_fsync(newfd); - server.appendseldb = -1; /* Make sure SELECT is re-issued */ + server.aof_selected_db = -1; /* Make sure SELECT is re-issued */ aofUpdateCurrentSize(); - server.auto_aofrewrite_base_size = server.appendonly_current_size; + server.aof_rewrite_base_size = server.aof_current_size; /* Clear regular AOF buffer since its contents was just written to * the new AOF from the background rewrite buffer. */ - sdsfree(server.aofbuf); - server.aofbuf = sdsempty(); + sdsfree(server.aof_buf); + server.aof_buf = sdsempty(); } - redisLog(REDIS_NOTICE, "Background AOF rewrite successful"); + redisLog(REDIS_NOTICE, "Background AOF rewrite finished successfully"); + /* Change state from WAIT_REWRITE to ON if needed */ + if (server.aof_state == REDIS_AOF_WAIT_REWRITE) + server.aof_state = REDIS_AOF_ON; /* Asynchronously close the overwritten AOF. */ if (oldfd != -1) bioCreateBackgroundJob(REDIS_BIO_CLOSE_FILE,(void*)(long)oldfd,NULL,NULL); @@ -968,8 +983,11 @@ void backgroundRewriteDoneHandler(int exitcode, int bysignal) { } cleanup: - sdsfree(server.bgrewritebuf); - server.bgrewritebuf = sdsempty(); - aofRemoveTempFile(server.bgrewritechildpid); - server.bgrewritechildpid = -1; + sdsfree(server.aof_rewrite_buf); + server.aof_rewrite_buf = sdsempty(); + aofRemoveTempFile(server.aof_child_pid); + server.aof_child_pid = -1; + /* Schedule a new rewrite if we are waiting for it to switch the AOF ON. */ + if (server.aof_state == REDIS_AOF_WAIT_REWRITE) + server.aof_rewrite_scheduled = 1; } diff --git a/src/config.c b/src/config.c index acda67bb..4a25489a 100644 --- a/src/config.c +++ b/src/config.c @@ -179,7 +179,7 @@ void loadServerConfigFromString(char *config) { } else if (!strcasecmp(argv[0],"slaveof") && argc == 3) { server.masterhost = sdsnew(argv[1]); server.masterport = atoi(argv[2]); - server.replstate = REDIS_REPL_CONNECT; + server.repl_state = REDIS_REPL_CONNECT; } else if (!strcasecmp(argv[0],"repl-ping-slave-period") && argc == 2) { server.repl_ping_slave_period = atoi(argv[1]); if (server.repl_ping_slave_period <= 0) { @@ -201,7 +201,7 @@ void loadServerConfigFromString(char *config) { } else if (!strcasecmp(argv[0],"glueoutputbuf")) { redisLog(REDIS_WARNING, "Deprecated configuration directive: \"%s\"", argv[0]); } else if (!strcasecmp(argv[0],"rdbcompression") && argc == 2) { - if ((server.rdbcompression = yesnotoi(argv[1])) == -1) { + if ((server.rdb_compression = yesnotoi(argv[1])) == -1) { err = "argument must be 'yes' or 'no'"; goto loaderr; } } else if (!strcasecmp(argv[0],"activerehashing") && argc == 2) { @@ -213,24 +213,27 @@ void loadServerConfigFromString(char *config) { err = "argument must be 'yes' or 'no'"; goto loaderr; } } else if (!strcasecmp(argv[0],"appendonly") && argc == 2) { - if ((server.appendonly = yesnotoi(argv[1])) == -1) { + int yes; + + if ((yes = yesnotoi(argv[1])) == -1) { err = "argument must be 'yes' or 'no'"; goto loaderr; } + server.aof_state = yes ? REDIS_AOF_ON : REDIS_AOF_OFF; } else if (!strcasecmp(argv[0],"appendfilename") && argc == 2) { - zfree(server.appendfilename); - server.appendfilename = zstrdup(argv[1]); + zfree(server.aof_filename); + server.aof_filename = zstrdup(argv[1]); } else if (!strcasecmp(argv[0],"no-appendfsync-on-rewrite") && argc == 2) { - if ((server.no_appendfsync_on_rewrite= yesnotoi(argv[1])) == -1) { + if ((server.aof_no_fsync_on_rewrite= yesnotoi(argv[1])) == -1) { err = "argument must be 'yes' or 'no'"; goto loaderr; } } else if (!strcasecmp(argv[0],"appendfsync") && argc == 2) { if (!strcasecmp(argv[1],"no")) { - server.appendfsync = APPENDFSYNC_NO; + server.aof_fsync = AOF_FSYNC_NO; } else if (!strcasecmp(argv[1],"always")) { - server.appendfsync = APPENDFSYNC_ALWAYS; + server.aof_fsync = AOF_FSYNC_ALWAYS; } else if (!strcasecmp(argv[1],"everysec")) { - server.appendfsync = APPENDFSYNC_EVERYSEC; + server.aof_fsync = AOF_FSYNC_EVERYSEC; } else { err = "argument must be 'no', 'always' or 'everysec'"; goto loaderr; @@ -238,23 +241,23 @@ void loadServerConfigFromString(char *config) { } else if (!strcasecmp(argv[0],"auto-aof-rewrite-percentage") && argc == 2) { - server.auto_aofrewrite_perc = atoi(argv[1]); - if (server.auto_aofrewrite_perc < 0) { + server.aof_rewrite_perc = atoi(argv[1]); + if (server.aof_rewrite_perc < 0) { err = "Invalid negative percentage for AOF auto rewrite"; goto loaderr; } } else if (!strcasecmp(argv[0],"auto-aof-rewrite-min-size") && argc == 2) { - server.auto_aofrewrite_min_size = memtoll(argv[1],NULL); + server.aof_rewrite_min_size = memtoll(argv[1],NULL); } else if (!strcasecmp(argv[0],"requirepass") && argc == 2) { server.requirepass = zstrdup(argv[1]); } else if (!strcasecmp(argv[0],"pidfile") && argc == 2) { zfree(server.pidfile); server.pidfile = zstrdup(argv[1]); } else if (!strcasecmp(argv[0],"dbfilename") && argc == 2) { - zfree(server.dbfilename); - server.dbfilename = zstrdup(argv[1]); + zfree(server.rdb_filename); + server.rdb_filename = zstrdup(argv[1]); } else if (!strcasecmp(argv[0],"hash-max-zipmap-entries") && argc == 2) { server.hash_max_zipmap_entries = memtoll(argv[1], NULL); } else if (!strcasecmp(argv[0],"hash-max-zipmap-value") && argc == 2) { @@ -373,8 +376,8 @@ void configSetCommand(redisClient *c) { o = c->argv[3]; if (!strcasecmp(c->argv[2]->ptr,"dbfilename")) { - zfree(server.dbfilename); - server.dbfilename = zstrdup(o->ptr); + zfree(server.rdb_filename); + server.rdb_filename = zstrdup(o->ptr); } else if (!strcasecmp(c->argv[2]->ptr,"requirepass")) { zfree(server.requirepass); server.requirepass = ((char*)o->ptr)[0] ? zstrdup(o->ptr) : NULL; @@ -412,11 +415,11 @@ void configSetCommand(redisClient *c) { server.maxidletime = ll; } else if (!strcasecmp(c->argv[2]->ptr,"appendfsync")) { if (!strcasecmp(o->ptr,"no")) { - server.appendfsync = APPENDFSYNC_NO; + server.aof_fsync = AOF_FSYNC_NO; } else if (!strcasecmp(o->ptr,"everysec")) { - server.appendfsync = APPENDFSYNC_EVERYSEC; + server.aof_fsync = AOF_FSYNC_EVERYSEC; } else if (!strcasecmp(o->ptr,"always")) { - server.appendfsync = APPENDFSYNC_ALWAYS; + server.aof_fsync = AOF_FSYNC_ALWAYS; } else { goto badfmt; } @@ -424,29 +427,26 @@ void configSetCommand(redisClient *c) { int yn = yesnotoi(o->ptr); if (yn == -1) goto badfmt; - server.no_appendfsync_on_rewrite = yn; + server.aof_no_fsync_on_rewrite = yn; } else if (!strcasecmp(c->argv[2]->ptr,"appendonly")) { - int old = server.appendonly; - int new = yesnotoi(o->ptr); - - if (new == -1) goto badfmt; - if (old != new) { - if (new == 0) { - stopAppendOnly(); - } else { - if (startAppendOnly() == REDIS_ERR) { - addReplyError(c, - "Unable to turn on AOF. Check server logs."); - return; - } + int enable = yesnotoi(o->ptr); + + if (enable == -1) goto badfmt; + if (enable == 0 && server.aof_state != REDIS_AOF_OFF) { + stopAppendOnly(); + } else if (enable && server.aof_state == REDIS_AOF_OFF) { + if (startAppendOnly() == REDIS_ERR) { + addReplyError(c, + "Unable to turn on AOF. Check server logs."); + return; } } } else if (!strcasecmp(c->argv[2]->ptr,"auto-aof-rewrite-percentage")) { if (getLongLongFromObject(o,&ll) == REDIS_ERR || ll < 0) goto badfmt; - server.auto_aofrewrite_perc = ll; + server.aof_rewrite_perc = ll; } else if (!strcasecmp(c->argv[2]->ptr,"auto-aof-rewrite-min-size")) { if (getLongLongFromObject(o,&ll) == REDIS_ERR || ll < 0) goto badfmt; - server.auto_aofrewrite_min_size = ll; + server.aof_rewrite_min_size = ll; } else if (!strcasecmp(c->argv[2]->ptr,"save")) { int vlen, j; sds *v = sdssplitlen(o->ptr,sdslen(o->ptr)," ",1,&vlen); @@ -567,7 +567,7 @@ void configGetCommand(redisClient *c) { } if (stringmatch(pattern,"dbfilename",0)) { addReplyBulkCString(c,"dbfilename"); - addReplyBulkCString(c,server.dbfilename); + addReplyBulkCString(c,server.rdb_filename); matches++; } if (stringmatch(pattern,"requirepass",0)) { @@ -616,21 +616,21 @@ void configGetCommand(redisClient *c) { } if (stringmatch(pattern,"appendonly",0)) { addReplyBulkCString(c,"appendonly"); - addReplyBulkCString(c,server.appendonly ? "yes" : "no"); + addReplyBulkCString(c,server.aof_state == REDIS_AOF_OFF ? "no" : "yes"); matches++; } if (stringmatch(pattern,"no-appendfsync-on-rewrite",0)) { addReplyBulkCString(c,"no-appendfsync-on-rewrite"); - addReplyBulkCString(c,server.no_appendfsync_on_rewrite ? "yes" : "no"); + addReplyBulkCString(c,server.aof_no_fsync_on_rewrite ? "yes" : "no"); matches++; } if (stringmatch(pattern,"appendfsync",0)) { char *policy; - switch(server.appendfsync) { - case APPENDFSYNC_NO: policy = "no"; break; - case APPENDFSYNC_EVERYSEC: policy = "everysec"; break; - case APPENDFSYNC_ALWAYS: policy = "always"; break; + switch(server.aof_fsync) { + case AOF_FSYNC_NO: policy = "no"; break; + case AOF_FSYNC_EVERYSEC: policy = "everysec"; break; + case AOF_FSYNC_ALWAYS: policy = "always"; break; default: policy = "unknown"; break; /* too harmless to panic */ } addReplyBulkCString(c,"appendfsync"); @@ -655,12 +655,12 @@ void configGetCommand(redisClient *c) { } if (stringmatch(pattern,"auto-aof-rewrite-percentage",0)) { addReplyBulkCString(c,"auto-aof-rewrite-percentage"); - addReplyBulkLongLong(c,server.auto_aofrewrite_perc); + addReplyBulkLongLong(c,server.aof_rewrite_perc); matches++; } if (stringmatch(pattern,"auto-aof-rewrite-min-size",0)) { addReplyBulkCString(c,"auto-aof-rewrite-min-size"); - addReplyBulkLongLong(c,server.auto_aofrewrite_min_size); + addReplyBulkLongLong(c,server.aof_rewrite_min_size); matches++; } if (stringmatch(pattern,"slave-serve-stale-data",0)) { diff --git a/src/db.c b/src/db.c index 3135795d..f7d93e08 100644 --- a/src/db.c +++ b/src/db.c @@ -40,7 +40,7 @@ robj *lookupKey(redisDb *db, robj *key) { /* Update the access time for the aging algorithm. * Don't do it if we have a saving child, as this will trigger * a copy on write madness. */ - if (server.bgsavechildpid == -1 && server.bgrewritechildpid == -1) + if (server.rdb_child_pid == -1 && server.aof_child_pid == -1) val->lru = server.lruclock; server.stat_keyspace_hits++; return val; @@ -210,15 +210,15 @@ void flushallCommand(redisClient *c) { signalFlushedDb(-1); server.dirty += emptyDb(); addReply(c,shared.ok); - if (server.bgsavechildpid != -1) { - kill(server.bgsavechildpid,SIGKILL); - rdbRemoveTempFile(server.bgsavechildpid); + if (server.rdb_child_pid != -1) { + kill(server.rdb_child_pid,SIGKILL); + rdbRemoveTempFile(server.rdb_child_pid); } if (server.saveparamslen > 0) { /* Normally rdbSave() will reset dirty, but we don't want this here * as otherwise FLUSHALL will not be replicated nor put into the AOF. */ int saved_dirty = server.dirty; - rdbSave(server.dbfilename); + rdbSave(server.rdb_filename); server.dirty = saved_dirty; } server.dirty++; @@ -487,7 +487,7 @@ void propagateExpire(redisDb *db, robj *key) { argv[1] = key; incrRefCount(key); - if (server.appendonly) + if (server.aof_state != REDIS_AOF_OFF) feedAppendOnlyFile(server.delCommand,db->id,argv,2); if (listLength(server.slaves)) replicationFeedSlaves(server.slaves,db->id,argv,2); diff --git a/src/debug.c b/src/debug.c index d610d2a9..d218f0f9 100644 --- a/src/debug.c +++ b/src/debug.c @@ -216,12 +216,12 @@ void debugCommand(redisClient *c) { if (c->argc >= 3) c->argv[2] = tryObjectEncoding(c->argv[2]); redisAssertWithInfo(c,c->argv[0],1 == 2); } else if (!strcasecmp(c->argv[1]->ptr,"reload")) { - if (rdbSave(server.dbfilename) != REDIS_OK) { + if (rdbSave(server.rdb_filename) != REDIS_OK) { addReply(c,shared.err); return; } emptyDb(); - if (rdbLoad(server.dbfilename) != REDIS_OK) { + if (rdbLoad(server.rdb_filename) != REDIS_OK) { addReplyError(c,"Error trying to load the RDB dump"); return; } @@ -229,10 +229,11 @@ void debugCommand(redisClient *c) { addReply(c,shared.ok); } else if (!strcasecmp(c->argv[1]->ptr,"loadaof")) { emptyDb(); - if (loadAppendOnlyFile(server.appendfilename) != REDIS_OK) { + if (loadAppendOnlyFile(server.aof_filename) != REDIS_OK) { addReply(c,shared.err); return; } + server.dirty = 0; /* Prevent AOF / replication */ redisLog(REDIS_WARNING,"Append Only File loaded by DEBUG LOADAOF"); addReply(c,shared.ok); } else if (!strcasecmp(c->argv[1]->ptr,"object") && c->argc == 3) { diff --git a/src/multi.c b/src/multi.c index 5c883400..1504bb09 100644 --- a/src/multi.c +++ b/src/multi.c @@ -67,7 +67,7 @@ void discardCommand(redisClient *c) { void execCommandReplicateMulti(redisClient *c) { robj *multistring = createStringObject("MULTI",5); - if (server.appendonly) + if (server.aof_state != REDIS_AOF_OFF) feedAppendOnlyFile(server.multiCommand,c->db->id,&multistring,1); if (listLength(server.slaves)) replicationFeedSlaves(server.slaves,c->db->id,&multistring,1); diff --git a/src/networking.c b/src/networking.c index bc807c4b..59512f0f 100644 --- a/src/networking.c +++ b/src/networking.c @@ -519,7 +519,7 @@ void freeClient(redisClient *c) { /* Case 2: we lost the connection with the master. */ if (c->flags & REDIS_MASTER) { server.master = NULL; - server.replstate = REDIS_REPL_CONNECT; + server.repl_state = REDIS_REPL_CONNECT; server.repl_down_since = time(NULL); /* Since we lost the connection with the master, we should also * close the connection with all our slaves if we have any, so diff --git a/src/rdb.c b/src/rdb.c index 2c0feb6d..77e2a048 100644 --- a/src/rdb.c +++ b/src/rdb.c @@ -253,7 +253,7 @@ int rdbSaveRawString(rio *rdb, unsigned char *s, size_t len) { /* Try LZF compression - under 20 bytes it's unable to compress even * aaaaaaaaaaaaaaaaaa so skip it */ - if (server.rdbcompression && len > 20) { + if (server.rdb_compression && len > 20) { n = rdbSaveLzfStringObject(rdb,s,len); if (n == -1) return -1; if (n > 0) return n; @@ -670,7 +670,7 @@ int rdbSaveBackground(char *filename) { pid_t childpid; long long start; - if (server.bgsavechildpid != -1) return REDIS_ERR; + if (server.rdb_child_pid != -1) return REDIS_ERR; server.dirty_before_bgsave = server.dirty; @@ -692,7 +692,7 @@ int rdbSaveBackground(char *filename) { return REDIS_ERR; } redisLog(REDIS_NOTICE,"Background saving started by pid %d",childpid); - server.bgsavechildpid = childpid; + server.rdb_child_pid = childpid; updateDictResizePolicy(); return REDIS_OK; } @@ -1062,20 +1062,20 @@ void backgroundSaveDoneHandler(int exitcode, int bysignal) { } else { redisLog(REDIS_WARNING, "Background saving terminated by signal %d", bysignal); - rdbRemoveTempFile(server.bgsavechildpid); + rdbRemoveTempFile(server.rdb_child_pid); } - server.bgsavechildpid = -1; + server.rdb_child_pid = -1; /* 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) { + if (server.rdb_child_pid != -1) { addReplyError(c,"Background save already in progress"); return; } - if (rdbSave(server.dbfilename) == REDIS_OK) { + if (rdbSave(server.rdb_filename) == REDIS_OK) { addReply(c,shared.ok); } else { addReply(c,shared.err); @@ -1083,11 +1083,11 @@ void saveCommand(redisClient *c) { } void bgsaveCommand(redisClient *c) { - if (server.bgsavechildpid != -1) { + if (server.rdb_child_pid != -1) { addReplyError(c,"Background save already in progress"); - } else if (server.bgrewritechildpid != -1) { + } else if (server.aof_child_pid != -1) { addReplyError(c,"Can't BGSAVE while AOF log rewriting is in progress"); - } else if (rdbSaveBackground(server.dbfilename) == REDIS_OK) { + } else if (rdbSaveBackground(server.rdb_filename) == REDIS_OK) { addReplyStatus(c,"Background saving started"); } else { addReply(c,shared.err); diff --git a/src/redis.c b/src/redis.c index 28240b03..09146115 100644 --- a/src/redis.c +++ b/src/redis.c @@ -563,7 +563,7 @@ void incrementallyRehash(void) { * for dict.c to resize the hash tables accordingly to the fact we have o not * running childs. */ void updateDictResizePolicy(void) { - if (server.bgsavechildpid == -1 && server.bgrewritechildpid == -1) + if (server.rdb_child_pid == -1 && server.aof_child_pid == -1) dictEnableResize(); else dictDisableResize(); @@ -673,7 +673,7 @@ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) { * if we resize the HT while there is the saving child at work actually * a lot of memory movements in the parent will cause a lot of pages * copied. */ - if (server.bgsavechildpid == -1 && server.bgrewritechildpid == -1) { + if (server.rdb_child_pid == -1 && server.aof_child_pid == -1) { if (!(loops % 10)) tryResizeHashTables(); if (server.activerehashing) incrementallyRehash(); } @@ -692,14 +692,14 @@ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) { /* Start a scheduled AOF rewrite if this was requested by the user while * a BGSAVE was in progress. */ - if (server.bgsavechildpid == -1 && server.bgrewritechildpid == -1 && - server.aofrewrite_scheduled) + if (server.rdb_child_pid == -1 && server.aof_child_pid == -1 && + server.aof_rewrite_scheduled) { rewriteAppendOnlyFileBackground(); } /* Check if a background saving or AOF rewrite in progress terminated. */ - if (server.bgsavechildpid != -1 || server.bgrewritechildpid != -1) { + if (server.rdb_child_pid != -1 || server.aof_child_pid != -1) { int statloc; pid_t pid; @@ -709,7 +709,7 @@ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) { if (WIFSIGNALED(statloc)) bysignal = WTERMSIG(statloc); - if (pid == server.bgsavechildpid) { + if (pid == server.rdb_child_pid) { backgroundSaveDoneHandler(exitcode,bysignal); } else { backgroundRewriteDoneHandler(exitcode,bysignal); @@ -728,21 +728,21 @@ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) { now-server.lastsave > sp->seconds) { redisLog(REDIS_NOTICE,"%d changes in %d seconds. Saving...", sp->changes, sp->seconds); - rdbSaveBackground(server.dbfilename); + rdbSaveBackground(server.rdb_filename); break; } } /* Trigger an AOF rewrite if needed */ - if (server.bgsavechildpid == -1 && - server.bgrewritechildpid == -1 && - server.auto_aofrewrite_perc && - server.appendonly_current_size > server.auto_aofrewrite_min_size) + if (server.rdb_child_pid == -1 && + server.aof_child_pid == -1 && + server.aof_rewrite_perc && + server.aof_current_size > server.aof_rewrite_min_size) { - long long base = server.auto_aofrewrite_base_size ? - server.auto_aofrewrite_base_size : 1; - long long growth = (server.appendonly_current_size*100/base) - 100; - if (growth >= server.auto_aofrewrite_perc) { + long long base = server.aof_rewrite_base_size ? + server.aof_rewrite_base_size : 1; + long long growth = (server.aof_current_size*100/base) - 100; + if (growth >= server.aof_rewrite_perc) { redisLog(REDIS_NOTICE,"Starting automatic rewriting of AOF on %lld%% growth",growth); rewriteAppendOnlyFileBackground(); } @@ -873,22 +873,22 @@ void initServerConfig() { server.syslog_ident = zstrdup("redis"); server.syslog_facility = LOG_LOCAL0; server.daemonize = 0; - server.appendonly = 0; - server.appendfsync = APPENDFSYNC_EVERYSEC; - server.no_appendfsync_on_rewrite = 0; - server.auto_aofrewrite_perc = REDIS_AUTO_AOFREWRITE_PERC; - server.auto_aofrewrite_min_size = REDIS_AUTO_AOFREWRITE_MIN_SIZE; - server.auto_aofrewrite_base_size = 0; - server.aofrewrite_scheduled = 0; - server.lastfsync = time(NULL); - server.appendfd = -1; - server.appendseldb = -1; /* Make sure the first time will not match */ + server.aof_state = REDIS_AOF_OFF; + server.aof_fsync = AOF_FSYNC_EVERYSEC; + server.aof_no_fsync_on_rewrite = 0; + server.aof_rewrite_perc = REDIS_AOF_REWRITE_PERC; + server.aof_rewrite_min_size = REDIS_AOF_REWRITE_MIN_SIZE; + server.aof_rewrite_base_size = 0; + server.aof_rewrite_scheduled = 0; + server.aof_last_fsync = time(NULL); + server.aof_fd = -1; + server.aof_selected_db = -1; /* Make sure the first time will not match */ server.aof_flush_postponed_start = 0; server.pidfile = zstrdup("/var/run/redis.pid"); - server.dbfilename = zstrdup("dump.rdb"); - server.appendfilename = zstrdup("appendonly.aof"); + server.rdb_filename = zstrdup("dump.rdb"); + server.aof_filename = zstrdup("appendonly.aof"); server.requirepass = NULL; - server.rdbcompression = 1; + server.rdb_compression = 1; server.activerehashing = 1; server.maxclients = REDIS_MAX_CLIENTS; server.bpop_blocked_clients = 0; @@ -919,12 +919,11 @@ void initServerConfig() { appendServerSaveParams(300,100); /* save after 5 minutes and 100 changes */ appendServerSaveParams(60,10000); /* save after 1 minute and 10000 changes */ /* Replication related */ - server.isslave = 0; server.masterauth = NULL; server.masterhost = NULL; server.masterport = 6379; server.master = NULL; - server.replstate = REDIS_REPL_NONE; + server.repl_state = REDIS_REPL_NONE; server.repl_syncio_timeout = REDIS_REPL_SYNCIO_TIMEOUT; server.repl_serve_stale_data = 1; server.repl_down_since = -1; @@ -1045,10 +1044,10 @@ void initServer() { listSetFreeMethod(server.pubsub_patterns,freePubsubPattern); listSetMatchMethod(server.pubsub_patterns,listMatchPubsubPattern); server.cronloops = 0; - server.bgsavechildpid = -1; - server.bgrewritechildpid = -1; - server.bgrewritebuf = sdsempty(); - server.aofbuf = sdsempty(); + server.rdb_child_pid = -1; + server.aof_child_pid = -1; + server.aof_rewrite_buf = sdsempty(); + server.aof_buf = sdsempty(); server.lastsave = time(NULL); server.dirty = 0; server.stat_numcommands = 0; @@ -1068,9 +1067,10 @@ void initServer() { if (server.sofd > 0 && aeCreateFileEvent(server.el,server.sofd,AE_READABLE, acceptUnixHandler,NULL) == AE_ERR) oom("creating file event"); - if (server.appendonly) { - server.appendfd = open(server.appendfilename,O_WRONLY|O_APPEND|O_CREAT,0644); - if (server.appendfd == -1) { + if (server.aof_state == REDIS_AOF_ON) { + server.aof_fd = open(server.aof_filename, + O_WRONLY|O_APPEND|O_CREAT,0644); + if (server.aof_fd == -1) { redisLog(REDIS_WARNING, "Can't open the append-only file: %s", strerror(errno)); exit(1); @@ -1155,7 +1155,7 @@ void call(redisClient *c) { slowlogPushEntryIfNeeded(c->argv,c->argc,duration); c->cmd->calls++; - if (server.appendonly && dirty > 0) + if (server.aof_state != REDIS_AOF_OFF && dirty > 0) feedAppendOnlyFile(c->cmd,c->db->id,c->argv,c->argc); if ((dirty > 0 || c->cmd->flags & REDIS_CMD_FORCE_REPLICATION) && listLength(server.slaves)) @@ -1254,7 +1254,7 @@ int processCommand(redisClient *c) { /* Only allow INFO and SLAVEOF when slave-serve-stale-data is no and * we are a slave with a broken link with master. */ - if (server.masterhost && server.replstate != REDIS_REPL_CONNECTED && + if (server.masterhost && server.repl_state != REDIS_REPL_CONNECTED && server.repl_serve_stale_data == 0 && c->cmd->proc != infoCommand && c->cmd->proc != slaveofCommand) { @@ -1305,27 +1305,27 @@ int prepareForShutdown(int flags) { /* Kill the saving child if there is a background saving in progress. We want to avoid race conditions, for instance our saving child may overwrite the synchronous saving did by SHUTDOWN. */ - if (server.bgsavechildpid != -1) { + if (server.rdb_child_pid != -1) { redisLog(REDIS_WARNING,"There is a child saving an .rdb. Killing it!"); - kill(server.bgsavechildpid,SIGKILL); - rdbRemoveTempFile(server.bgsavechildpid); + kill(server.rdb_child_pid,SIGKILL); + rdbRemoveTempFile(server.rdb_child_pid); } - if (server.appendonly) { + if (server.aof_state != REDIS_AOF_OFF) { /* Kill the AOF saving child as the AOF we already have may be longer * but contains the full dataset anyway. */ - if (server.bgrewritechildpid != -1) { + if (server.aof_child_pid != -1) { redisLog(REDIS_WARNING, "There is a child rewriting the AOF. Killing it!"); - kill(server.bgrewritechildpid,SIGKILL); + kill(server.aof_child_pid,SIGKILL); } /* Append only file: fsync() the AOF and exit */ redisLog(REDIS_NOTICE,"Calling fsync() on the AOF file."); - aof_fsync(server.appendfd); + aof_fsync(server.aof_fd); } if ((server.saveparamslen > 0 && !nosave) || save) { redisLog(REDIS_NOTICE,"Saving the final RDB snapshot before exiting."); /* Snapshotting. Perform a SYNC SAVE and exit */ - if (rdbSave(server.dbfilename) != REDIS_OK) { + if (rdbSave(server.rdb_filename) != REDIS_OK) { /* Ooops.. error saving! The best we can do is to continue * operating. Note that if there was a background saving process, * in the next cron() Redis will be notified that the background @@ -1497,23 +1497,23 @@ sds genRedisInfoString(char *section) { "last_save_time:%ld\r\n" "bgrewriteaof_in_progress:%d\r\n", server.loading, - server.appendonly, + server.aof_state != REDIS_AOF_OFF, server.dirty, - server.bgsavechildpid != -1, + server.rdb_child_pid != -1, server.lastsave, - server.bgrewritechildpid != -1); + server.aof_child_pid != -1); - if (server.appendonly) { + if (server.aof_state != REDIS_AOF_OFF) { info = sdscatprintf(info, "aof_current_size:%lld\r\n" "aof_base_size:%lld\r\n" "aof_pending_rewrite:%d\r\n" "aof_buffer_length:%zu\r\n" "aof_pending_bio_fsync:%llu\r\n", - (long long) server.appendonly_current_size, - (long long) server.auto_aofrewrite_base_size, - server.aofrewrite_scheduled, - sdslen(server.aofbuf), + (long long) server.aof_current_size, + (long long) server.aof_rewrite_base_size, + server.aof_rewrite_scheduled, + sdslen(server.aof_buf), bioPendingJobsOfType(REDIS_BIO_AOF_FSYNC)); } @@ -1592,14 +1592,14 @@ sds genRedisInfoString(char *section) { "master_sync_in_progress:%d\r\n" ,server.masterhost, server.masterport, - (server.replstate == REDIS_REPL_CONNECTED) ? + (server.repl_state == REDIS_REPL_CONNECTED) ? "up" : "down", server.master ? ((int)(time(NULL)-server.master->lastinteraction)) : -1, - server.replstate == REDIS_REPL_TRANSFER + server.repl_state == REDIS_REPL_TRANSFER ); - if (server.replstate == REDIS_REPL_TRANSFER) { + if (server.repl_state == REDIS_REPL_TRANSFER) { info = sdscatprintf(info, "master_sync_left_bytes:%ld\r\n" "master_sync_last_io_seconds_ago:%d\r\n" @@ -1608,7 +1608,7 @@ sds genRedisInfoString(char *section) { ); } - if (server.replstate != REDIS_REPL_CONNECTED) { + if (server.repl_state != REDIS_REPL_CONNECTED) { info = sdscatprintf(info, "master_link_down_since_seconds:%ld\r\n", (long)time(NULL)-server.repl_down_since); @@ -2098,11 +2098,11 @@ int main(int argc, char **argv) { linuxOvercommitMemoryWarning(); #endif start = ustime(); - if (server.appendonly) { - if (loadAppendOnlyFile(server.appendfilename) == REDIS_OK) + if (server.aof_state == REDIS_AOF_ON) { + if (loadAppendOnlyFile(server.aof_filename) == REDIS_OK) redisLog(REDIS_NOTICE,"DB loaded from append only file: %.3f seconds",(float)(ustime()-start)/1000000); } else { - if (rdbLoad(server.dbfilename) == REDIS_OK) { + if (rdbLoad(server.rdb_filename) == REDIS_OK) { redisLog(REDIS_NOTICE,"DB loaded from disk: %.3f seconds", (float)(ustime()-start)/1000000); } else if (errno != ENOENT) { diff --git a/src/redis.h b/src/redis.h index 6b9bad08..aa79b4ad 100644 --- a/src/redis.h +++ b/src/redis.h @@ -52,9 +52,9 @@ #define REDIS_SHARED_INTEGERS 10000 #define REDIS_REPLY_CHUNK_BYTES (16*1024) /* 16k output buffer */ #define REDIS_MAX_LOGMSG_LEN 1024 /* Default maximum length of syslog messages */ -#define REDIS_AUTO_AOFREWRITE_PERC 100 -#define REDIS_AUTO_AOFREWRITE_MIN_SIZE (1024*1024) -#define REDIS_AOFREWRITE_ITEMS_PER_CMD 64 +#define REDIS_AOF_REWRITE_PERC 100 +#define REDIS_AOF_REWRITE_MIN_SIZE (1024*1024) +#define REDIS_AOF_REWRITE_ITEMS_PER_CMD 64 #define REDIS_SLOWLOG_LOG_SLOWER_THAN 10000 #define REDIS_SLOWLOG_MAX_LEN 64 #define REDIS_MAX_CLIENTS 10000 @@ -124,6 +124,11 @@ #define REDIS_RDB_ENC_INT32 2 /* 32 bit signed integer */ #define REDIS_RDB_ENC_LZF 3 /* string compressed with FASTLZ */ +/* AOF states */ +#define REDIS_AOF_OFF 0 /* AOF is off */ +#define REDIS_AOF_ON 1 /* AOF is on */ +#define REDIS_AOF_WAIT_REWRITE 2 /* AOF waits rewrite to start appending */ + /* Client flags */ #define REDIS_SLAVE 1 /* This client is a slave server */ #define REDIS_MASTER 2 /* This client is a master server */ @@ -184,9 +189,9 @@ #define ZSKIPLIST_P 0.25 /* Skiplist P = 1/4 */ /* Append only defines */ -#define APPENDFSYNC_NO 0 -#define APPENDFSYNC_ALWAYS 1 -#define APPENDFSYNC_EVERYSEC 2 +#define AOF_FSYNC_NO 0 +#define AOF_FSYNC_ALWAYS 1 +#define AOF_FSYNC_EVERYSEC 2 /* Zip structure related defaults */ #define REDIS_HASH_MAX_ZIPMAP_ENTRIES 512 @@ -498,112 +503,113 @@ struct redisServer { redisDb *db; dict *commands; /* Command table hahs table */ aeEventLoop *el; + unsigned lruclock:22; /* Clock incrementing every minute, for LRU */ + unsigned lruclock_padding:10; + int shutdown_asap; /* SHUTDOWN needed ASAP */ + int activerehashing; /* Incremental rehash in serverCron() */ + char *requirepass; /* Pass for AUTH command, or NULL */ + char *pidfile; /* PID file path */ /* Networking */ - int port; - char *bindaddr; - char *unixsocket; - mode_t unixsocketperm; - int ipfd; - int sofd; - int cfd; - list *clients; - list *slaves, *monitors; - char neterr[ANET_ERR_LEN]; + int port; /* TCP listening port */ + char *bindaddr; /* Bind address or NULL */ + char *unixsocket; /* UNIX socket path */ + mode_t unixsocketperm; /* UNIX socket permission */ + int ipfd; /* TCP socket file descriptor */ + int sofd; /* Unix socket file descriptor */ + int cfd; /* Cluster bus lisetning socket */ + list *clients; /* List of active clients */ + list *slaves, *monitors; /* List of slaves and MONITORs */ + char neterr[ANET_ERR_LEN]; /* Error buffer for anet.c */ /* RDB / AOF loading information */ - int loading; + int loading; /* We are loading data from disk if true */ off_t loading_total_bytes; off_t loading_loaded_bytes; time_t loading_start_time; /* Fast pointers to often looked up command */ struct redisCommand *delCommand, *multiCommand; - int cronloops; /* number of times the cron function run */ + int cronloops; /* Number of times the cron function run */ time_t lastsave; /* Unix time of last save succeeede */ /* Fields used only for stats */ - time_t stat_starttime; /* server start time */ - long long stat_numcommands; /* number of processed commands */ - long long stat_numconnections; /* number of connections received */ - long long stat_expiredkeys; /* number of expired keys */ - long long stat_evictedkeys; /* number of evicted keys (maxmemory) */ - long long stat_keyspace_hits; /* number of successful lookups of keys */ - long long stat_keyspace_misses; /* number of failed lookups of keys */ - size_t stat_peak_memory; /* max used memory record */ - long long stat_fork_time; /* time needed to perform latets fork() */ - long long stat_rejected_conn; /* clients rejected because of maxclients */ - list *slowlog; - long long slowlog_entry_id; - long long slowlog_log_slower_than; - unsigned long slowlog_max_len; + time_t stat_starttime; /* Server start time */ + long long stat_numcommands; /* Number of processed commands */ + long long stat_numconnections; /* Number of connections received */ + long long stat_expiredkeys; /* Number of expired keys */ + long long stat_evictedkeys; /* Number of evicted keys (maxmemory) */ + long long stat_keyspace_hits; /* Number of successful lookups of keys */ + long long stat_keyspace_misses; /* Number of failed lookups of keys */ + size_t stat_peak_memory; /* Max used memory record */ + long long stat_fork_time; /* Time needed to perform latets fork() */ + long long stat_rejected_conn; /* Clients rejected because of maxclients */ + list *slowlog; /* SLOWLOG list of commands */ + long long slowlog_entry_id; /* SLOWLOG current entry ID */ + long long slowlog_log_slower_than; /* SLOWLOG time limit (to get logged) */ + unsigned long slowlog_max_len; /* SLOWLOG max number of items logged */ /* Configuration */ - int verbosity; - int maxidletime; - size_t client_max_querybuf_len; - int dbnum; - int daemonize; - int appendonly; - int appendfsync; - int no_appendfsync_on_rewrite; - int auto_aofrewrite_perc; /* Rewrite AOF if % growth is > M and... */ - off_t auto_aofrewrite_min_size; /* the AOF file is at least N bytes. */ - off_t auto_aofrewrite_base_size;/* AOF size on latest startup or rewrite. */ - off_t appendonly_current_size; /* AOF current size. */ - int aofrewrite_scheduled; /* Rewrite once BGSAVE terminates. */ - int shutdown_asap; /* SHUTDOWN needed */ - int activerehashing; - char *requirepass; - /* Persistence */ - long long dirty; /* changes to DB from the last save */ - long long dirty_before_bgsave; /* used to restore dirty on failed BGSAVE */ - time_t lastfsync; - int appendfd; - int appendseldb; - time_t aof_flush_postponed_start; - char *pidfile; - pid_t bgsavechildpid; - pid_t bgrewritechildpid; - 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; + int verbosity; /* Loglevel in redis.conf */ + int maxidletime; /* Client timeout in seconds */ + size_t client_max_querybuf_len; /* Limit for client query buffer length */ + int dbnum; /* Total number of configured DBs */ + int daemonize; /* True if running as a daemon */ + /* AOF persistence */ + int aof_state; /* REDIS_AOF_(ON|OFF|WAIT_REWRITE) */ + int aof_fsync; /* Kind of fsync() policy */ + char *aof_filename; /* Name of the AOF file */ + int aof_no_fsync_on_rewrite; /* Don't fsync if a rewrite is in prog. */ + int aof_rewrite_perc; /* Rewrite AOF if % growth is > M and... */ + off_t aof_rewrite_min_size; /* the AOF file is at least N bytes. */ + off_t aof_rewrite_base_size; /* AOF size on latest startup or rewrite. */ + off_t aof_current_size; /* AOF current size. */ + int aof_rewrite_scheduled; /* Rewrite once BGSAVE terminates. */ + pid_t aof_child_pid; /* PID if rewriting process */ + sds aof_rewrite_buf; /* buffer taken by parent during oppend only rewrite */ + sds aof_buf; /* AOF buffer, written before entering the event loop */ + int aof_fd; /* File descriptor of currently selected AOF file */ + int aof_selected_db; /* Currently selected DB in AOF */ + time_t aof_flush_postponed_start; /* UNIX time of postponed AOF flush */ + time_t aof_last_fsync; /* UNIX time of last fsync() */ + /* RDB persistence */ + long long dirty; /* Changes to DB from the last save */ + long long dirty_before_bgsave; /* Used to restore dirty on failed BGSAVE */ + pid_t rdb_child_pid; /* PID of RDB saving child */ + struct saveparam *saveparams; /* Save points array for RDB */ + int saveparamslen; /* Number of saving points */ + char *rdb_filename; /* Name of RDB file */ + int rdb_compression; /* Use compression in RDB? */ /* Logging */ - char *logfile; - int syslog_enabled; - char *syslog_ident; - int syslog_facility; - /* Replication related */ - int isslave; + char *logfile; /* Path of log file */ + int syslog_enabled; /* Is syslog enabled? */ + char *syslog_ident; /* Syslog ident */ + int syslog_facility; /* Syslog facility */ /* Slave specific fields */ - char *masterauth; - char *masterhost; - int masterport; - int repl_ping_slave_period; - int repl_timeout; - redisClient *master; /* client that is master for this slave */ - int repl_syncio_timeout; /* timeout for synchronous I/O calls */ - int replstate; /* replication status if the instance is a slave */ - off_t repl_transfer_left; /* bytes left reading .rdb */ - int repl_transfer_s; /* slave -> master SYNC socket */ - int repl_transfer_fd; /* slave -> master SYNC temp file descriptor */ - char *repl_transfer_tmpfile; /* slave-> master SYNC temp file name */ - time_t repl_transfer_lastio; /* unix time of the latest read, for timeout */ + char *masterauth; /* AUTH with this password with master */ + char *masterhost; /* Hostname of master */ + int masterport; /* Port of master */ + int repl_ping_slave_period; /* Master pings the salve every N seconds */ + int repl_timeout; /* Timeout after N seconds of master idle */ + redisClient *master; /* Client that is master for this slave */ + int repl_syncio_timeout; /* Timeout for synchronous I/O calls */ + int repl_state; /* Replication status if the instance is a slave */ + off_t repl_transfer_left; /* Bytes left reading .rdb */ + int repl_transfer_s; /* Slave -> Master SYNC socket */ + int repl_transfer_fd; /* Slave -> Master SYNC temp file descriptor */ + char *repl_transfer_tmpfile; /* Slave-> master SYNC temp file name */ + time_t repl_transfer_lastio; /* Unix time of the latest read, for timeout */ int repl_serve_stale_data; /* Serve stale data when link is down? */ - time_t repl_down_since; /* unix time at which link with master went down */ + time_t repl_down_since; /* Unix time at which link with master went down */ /* Limits */ - unsigned int maxclients; - unsigned long long maxmemory; - int maxmemory_policy; - int maxmemory_samples; + unsigned int maxclients; /* Max number of simultaneous clients */ + unsigned long long maxmemory; /* Max number of memory bytes to use */ + int maxmemory_policy; /* Policy for key evition */ + int maxmemory_samples; /* Pricision of random sampling */ /* Blocked clients */ - unsigned int bpop_blocked_clients; + unsigned int bpop_blocked_clients; /* Number of clients blocked by lists */ list *unblocked_clients; /* list of clients to unblock before next loop */ /* Sort parameters - qsort_r() is only available under BSD so we * have to take this state global, in order to pass it to sortCompare() */ int sort_desc; int sort_alpha; int sort_bypattern; - /* Zip structure config */ + /* Zip structure config, see redis.conf for more information */ size_t hash_max_zipmap_entries; size_t hash_max_zipmap_value; size_t list_max_ziplist_entries; @@ -611,23 +617,20 @@ struct redisServer { size_t set_max_intset_entries; size_t zset_max_ziplist_entries; size_t zset_max_ziplist_value; - time_t unixtime; /* Unix time sampled every second. */ + time_t unixtime; /* Unix time sampled every second. */ /* Pubsub */ - dict *pubsub_channels; /* Map channels to list of subscribed clients */ - list *pubsub_patterns; /* A list of pubsub_patterns */ - /* Misc */ - unsigned lruclock:22; /* clock incrementing every minute, for LRU */ - unsigned lruclock_padding:10; + dict *pubsub_channels; /* Map channels to list of subscribed clients */ + list *pubsub_patterns; /* A list of pubsub_patterns */ /* Cluster */ - int cluster_enabled; - clusterState cluster; + int cluster_enabled; /* Is cluster enabled? */ + clusterState cluster; /* State of the cluster */ /* Scripting */ lua_State *lua; /* The Lua interpreter. We use just one for all clients */ - redisClient *lua_client; /* The "fake client" to query Redis from Lua */ - redisClient *lua_caller; /* The client running EVAL right now, or NULL */ - dict *lua_scripts; /* A dictionary of SHA1 -> Lua scripts */ - long long lua_time_limit; - long long lua_time_start; + redisClient *lua_client; /* The "fake client" to query Redis from Lua */ + redisClient *lua_caller; /* The client running EVAL right now, or NULL */ + dict *lua_scripts; /* A dictionary of SHA1 -> Lua scripts */ + long long lua_time_limit; /* Script timeout in seconds */ + long long lua_time_start; /* Start time of script */ int lua_write_dirty; /* True if a write command was called during the execution of the current script. */ int lua_random_dirty; /* True if a random command was called during the @@ -639,7 +642,7 @@ struct redisServer { char *assert_failed; char *assert_file; int assert_line; - int bug_report_start; /* True if bug report header already logged. */ + int bug_report_start; /* True if bug report header was already logged. */ }; typedef struct pubsubPattern { diff --git a/src/replication.c b/src/replication.c index 30df9bc8..e08517e8 100644 --- a/src/replication.c +++ b/src/replication.c @@ -89,7 +89,7 @@ void syncCommand(redisClient *c) { /* Refuse SYNC requests if we are a slave but the link with our master * is not ok... */ - if (server.masterhost && server.replstate != REDIS_REPL_CONNECTED) { + if (server.masterhost && server.repl_state != REDIS_REPL_CONNECTED) { addReplyError(c,"Can't SYNC while not connected with my master"); return; } @@ -106,7 +106,7 @@ void syncCommand(redisClient *c) { redisLog(REDIS_NOTICE,"Slave ask for synchronization"); /* Here we need to check if there is a background saving operation * in progress, or if it is required to start one */ - if (server.bgsavechildpid != -1) { + if (server.rdb_child_pid != -1) { /* Ok a background save is in progress. Let's check if it is a good * one for replication, i.e. if there is another slave that is * registering differences since the server forked to save */ @@ -135,7 +135,7 @@ void syncCommand(redisClient *c) { } else { /* Ok we don't have a BGSAVE in progress, let's start one */ redisLog(REDIS_NOTICE,"Starting BGSAVE for SYNC"); - if (rdbSaveBackground(server.dbfilename) != REDIS_OK) { + if (rdbSaveBackground(server.rdb_filename) != REDIS_OK) { redisLog(REDIS_NOTICE,"Replication failed, can't BGSAVE"); addReplyError(c,"Unable to perform background save"); return; @@ -229,7 +229,7 @@ void updateSlavesWaitingBgsave(int bgsaveerr) { redisLog(REDIS_WARNING,"SYNC failed. BGSAVE child returned an error"); continue; } - if ((slave->repldbfd = open(server.dbfilename,O_RDONLY)) == -1 || + if ((slave->repldbfd = open(server.rdb_filename,O_RDONLY)) == -1 || redis_fstat(slave->repldbfd,&buf) == -1) { freeClient(slave); redisLog(REDIS_WARNING,"SYNC failed. Can't open/stat DB after BGSAVE: %s", strerror(errno)); @@ -246,7 +246,7 @@ void updateSlavesWaitingBgsave(int bgsaveerr) { } } if (startbgsave) { - if (rdbSaveBackground(server.dbfilename) != REDIS_OK) { + if (rdbSaveBackground(server.rdb_filename) != REDIS_OK) { listIter li; listRewind(server.slaves,&li); @@ -265,14 +265,14 @@ void updateSlavesWaitingBgsave(int bgsaveerr) { /* Abort the async download of the bulk dataset while SYNC-ing with master */ void replicationAbortSyncTransfer(void) { - redisAssert(server.replstate == REDIS_REPL_TRANSFER); + redisAssert(server.repl_state == REDIS_REPL_TRANSFER); aeDeleteFileEvent(server.el,server.repl_transfer_s,AE_READABLE); close(server.repl_transfer_s); close(server.repl_transfer_fd); unlink(server.repl_transfer_tmpfile); zfree(server.repl_transfer_tmpfile); - server.replstate = REDIS_REPL_CONNECT; + server.repl_state = REDIS_REPL_CONNECT; } /* Asynchronously read the SYNC payload we receive from a master */ @@ -333,7 +333,7 @@ void readSyncBulkPayload(aeEventLoop *el, int fd, void *privdata, int mask) { server.repl_transfer_left -= nread; /* Check if the transfer is now complete */ if (server.repl_transfer_left == 0) { - if (rename(server.repl_transfer_tmpfile,server.dbfilename) == -1) { + if (rename(server.repl_transfer_tmpfile,server.rdb_filename) == -1) { redisLog(REDIS_WARNING,"Failed trying to rename the temp DB into dump.rdb in MASTER <-> SLAVE synchronization: %s", strerror(errno)); replicationAbortSyncTransfer(); return; @@ -345,7 +345,7 @@ void readSyncBulkPayload(aeEventLoop *el, int fd, void *privdata, int mask) { * rdbLoad() will call the event loop to process events from time to * time for non blocking loading. */ aeDeleteFileEvent(server.el,server.repl_transfer_s,AE_READABLE); - if (rdbLoad(server.dbfilename) != REDIS_OK) { + if (rdbLoad(server.rdb_filename) != REDIS_OK) { redisLog(REDIS_WARNING,"Failed trying to load the MASTER synchronization DB from disk"); replicationAbortSyncTransfer(); return; @@ -356,10 +356,24 @@ void readSyncBulkPayload(aeEventLoop *el, int fd, void *privdata, int mask) { server.master = createClient(server.repl_transfer_s); server.master->flags |= REDIS_MASTER; server.master->authenticated = 1; - server.replstate = REDIS_REPL_CONNECTED; + server.repl_state = REDIS_REPL_CONNECTED; redisLog(REDIS_NOTICE, "MASTER <-> SLAVE sync: Finished with success"); - /* Rewrite the AOF file now that the dataset changed. */ - if (server.appendonly) rewriteAppendOnlyFileBackground(); + /* Restart the AOF subsystem now that we finished the sync. This + * will trigger an AOF rewrite, and when done will start appending + * to the new file. */ + if (server.aof_state != REDIS_AOF_OFF) { + int retry = 10; + + stopAppendOnly(); + while (retry-- && startAppendOnly() == REDIS_ERR) { + redisLog(REDIS_WARNING,"Failed enabling the AOF after successful master synchrnization! Trying it again in one second."); + sleep(1); + } + if (!retry) { + redisLog(REDIS_WARNING,"FATAL: this slave instance finished the synchronization with its master, but the AOF can't be turned on. Exiting now."); + exit(1); + } + } } return; @@ -378,7 +392,7 @@ void syncWithMaster(aeEventLoop *el, int fd, void *privdata, int mask) { /* If this event fired after the user turned the instance into a master * with SLAVEOF NO ONE we must just return ASAP. */ - if (server.replstate == REDIS_REPL_NONE) { + if (server.repl_state == REDIS_REPL_NONE) { close(fd); return; } @@ -440,7 +454,7 @@ void syncWithMaster(aeEventLoop *el, int fd, void *privdata, int mask) { goto error; } - server.replstate = REDIS_REPL_TRANSFER; + server.repl_state = REDIS_REPL_TRANSFER; server.repl_transfer_left = -1; server.repl_transfer_fd = dfd; server.repl_transfer_lastio = time(NULL); @@ -448,7 +462,7 @@ void syncWithMaster(aeEventLoop *el, int fd, void *privdata, int mask) { return; error: - server.replstate = REDIS_REPL_CONNECT; + server.repl_state = REDIS_REPL_CONNECT; close(fd); return; } @@ -473,7 +487,7 @@ int connectWithMaster(void) { server.repl_transfer_lastio = time(NULL); server.repl_transfer_s = fd; - server.replstate = REDIS_REPL_CONNECTING; + server.repl_state = REDIS_REPL_CONNECTING; return REDIS_OK; } @@ -482,11 +496,11 @@ int connectWithMaster(void) { void undoConnectWithMaster(void) { int fd = server.repl_transfer_s; - redisAssert(server.replstate == REDIS_REPL_CONNECTING); + redisAssert(server.repl_state == REDIS_REPL_CONNECTING); aeDeleteFileEvent(server.el,fd,AE_READABLE|AE_WRITABLE); close(fd); server.repl_transfer_s = -1; - server.replstate = REDIS_REPL_CONNECT; + server.repl_state = REDIS_REPL_CONNECT; } void slaveofCommand(redisClient *c) { @@ -496,11 +510,11 @@ void slaveofCommand(redisClient *c) { sdsfree(server.masterhost); server.masterhost = NULL; if (server.master) freeClient(server.master); - if (server.replstate == REDIS_REPL_TRANSFER) + if (server.repl_state == REDIS_REPL_TRANSFER) replicationAbortSyncTransfer(); - else if (server.replstate == REDIS_REPL_CONNECTING) + else if (server.repl_state == REDIS_REPL_CONNECTING) undoConnectWithMaster(); - server.replstate = REDIS_REPL_NONE; + server.repl_state = REDIS_REPL_NONE; redisLog(REDIS_NOTICE,"MASTER MODE enabled (user request)"); } } else { @@ -508,9 +522,9 @@ void slaveofCommand(redisClient *c) { server.masterhost = sdsdup(c->argv[1]->ptr); server.masterport = atoi(c->argv[2]->ptr); if (server.master) freeClient(server.master); - if (server.replstate == REDIS_REPL_TRANSFER) + if (server.repl_state == REDIS_REPL_TRANSFER) replicationAbortSyncTransfer(); - server.replstate = REDIS_REPL_CONNECT; + server.repl_state = REDIS_REPL_CONNECT; redisLog(REDIS_NOTICE,"SLAVE OF %s:%d enabled (user request)", server.masterhost, server.masterport); } @@ -521,7 +535,7 @@ void slaveofCommand(redisClient *c) { void replicationCron(void) { /* Non blocking connection timeout? */ - if (server.masterhost && server.replstate == REDIS_REPL_CONNECTING && + if (server.masterhost && server.repl_state == REDIS_REPL_CONNECTING && (time(NULL)-server.repl_transfer_lastio) > server.repl_timeout) { redisLog(REDIS_WARNING,"Timeout connecting to the MASTER..."); @@ -529,7 +543,7 @@ void replicationCron(void) { } /* Bulk transfer I/O timeout? */ - if (server.masterhost && server.replstate == REDIS_REPL_TRANSFER && + if (server.masterhost && server.repl_state == REDIS_REPL_TRANSFER && (time(NULL)-server.repl_transfer_lastio) > server.repl_timeout) { redisLog(REDIS_WARNING,"Timeout receiving bulk data from MASTER..."); @@ -537,7 +551,7 @@ void replicationCron(void) { } /* Timed out master when we are an already connected slave? */ - if (server.masterhost && server.replstate == REDIS_REPL_CONNECTED && + if (server.masterhost && server.repl_state == REDIS_REPL_CONNECTED && (time(NULL)-server.master->lastinteraction) > server.repl_timeout) { redisLog(REDIS_WARNING,"MASTER time out: no data nor PING received..."); @@ -545,7 +559,7 @@ void replicationCron(void) { } /* Check if we should connect to a MASTER */ - if (server.replstate == REDIS_REPL_CONNECT) { + if (server.repl_state == REDIS_REPL_CONNECT) { redisLog(REDIS_NOTICE,"Connecting to MASTER..."); if (connectWithMaster() == REDIS_OK) { redisLog(REDIS_NOTICE,"MASTER <-> SLAVE sync started"); diff --git a/tests/support/test.tcl b/tests/support/test.tcl index c875cfd8..e53d497b 100644 --- a/tests/support/test.tcl +++ b/tests/support/test.tcl @@ -5,7 +5,7 @@ set ::tests_failed {} proc assert {condition} { if {![uplevel 1 expr $condition]} { - error "assertion:Expected condition '$condition' to be true" + error "assertion:Expected condition '$condition' to be true ([uplevel 1 [list subst -nocommands $condition]])" } } diff --git a/tests/unit/other.tcl b/tests/unit/other.tcl index bb65570a..6bdb0b3f 100644 --- a/tests/unit/other.tcl +++ b/tests/unit/other.tcl @@ -140,6 +140,7 @@ start_server {tags {"other"}} { r pexpireat pz [expr {([clock seconds]+3000)*1000}] # Reload and check + waitForBgrewriteaof r r debug loadaof set ttl [r ttl x] assert {$ttl > 900 && $ttl <= 1000}