X-Git-Url: https://git.saurik.com/redis.git/blobdiff_plain/a3e60027e7d4419971406c6da7d6e8accbcaf9b0..11fd0c422b627d73d563916c6f559d3c0a021f26:/src/rdb.c diff --git a/src/rdb.c b/src/rdb.c index b8e24ab6..ce4b3566 100644 --- a/src/rdb.c +++ b/src/rdb.c @@ -7,6 +7,7 @@ #include #include #include +#include int rdbSaveType(FILE *fp, unsigned char type) { if (fwrite(&type,1,1,fp) == 0) return -1; @@ -461,7 +462,8 @@ int rdbSaveBackground(char *filename) { if ((childpid = fork()) == 0) { /* Child */ if (server.vm_enabled) vmReopenSwapFile(); - close(server.fd); + if (server.ipfd > 0) close(server.ipfd); + if (server.sofd > 0) close(server.sofd); if (rdbSave(filename) == REDIS_OK) { _exit(0); } else { @@ -792,6 +794,31 @@ robj *rdbLoadObject(int type, FILE *fp) { return o; } +/* Mark that we are loading in the global state and setup the fields + * needed to provide loading stats. */ +void startLoading(FILE *fp) { + struct stat sb; + + /* Load the DB */ + server.loading = 1; + server.loading_start_time = time(NULL); + if (fstat(fileno(fp), &sb) == -1) { + server.loading_total_bytes = 1; /* just to avoid division by zero */ + } else { + server.loading_total_bytes = sb.st_size; + } +} + +/* Refresh the loading progress info */ +void loadingProgress(off_t pos) { + server.loading_loaded_bytes = pos; +} + +/* Loading finished */ +void stopLoading(void) { + server.loading = 0; +} + int rdbLoad(char *filename) { FILE *fp; uint32_t dbid; @@ -800,6 +827,7 @@ int rdbLoad(char *filename) { redisDb *db = server.db+0; char buf[1024]; time_t expiretime, now = time(NULL); + long loops = 0; fp = fopen(filename,"r"); if (!fp) return REDIS_ERR; @@ -816,11 +844,20 @@ int rdbLoad(char *filename) { redisLog(REDIS_WARNING,"Can't handle RDB format version %d",rdbver); return REDIS_ERR; } + + startLoading(fp); while(1) { robj *key, *val; int force_swapout; expiretime = -1; + + /* Serve the clients from time to time */ + if (!(loops++ % 1000)) { + loadingProgress(ftello(fp)); + aeProcessEvents(server.el, AE_FILE_EVENTS|AE_DONT_WAIT); + } + /* Read type. */ if ((type = rdbLoadType(fp)) == -1) goto eoferr; if (type == REDIS_EXPIRETIME) { @@ -885,20 +922,21 @@ int rdbLoad(char *filename) { /* Flush data on disk once 32 MB of additional RAM are used... */ force_swapout = 0; - if ((redisEstimateRSS() - server.vm_max_memory) > 1024*1024*32) + if ((zmalloc_used_memory() - server.vm_max_memory) > 1024*1024*32) force_swapout = 1; /* If we have still some hope of having some value fitting memory * then we try random sampling. */ if (!swap_all_values && server.vm_enabled && force_swapout) { - while (redisEstimateRSS() > server.vm_max_memory) { + while (zmalloc_used_memory() > server.vm_max_memory) { if (vmSwapOneObjectBlocking() == REDIS_ERR) break; } - if (redisEstimateRSS() > server.vm_max_memory) + if (zmalloc_used_memory() > server.vm_max_memory) swap_all_values = 1; /* We are already using too much mem */ } } fclose(fp); + stopLoading(); return REDIS_OK; eoferr: /* unexpected end of file is handled here with a fatal exit */