Produces a dump of the database in RDB format sending it to the specified * Redis I/O channel. On success C_OK is returned, otherwise C_ERR * is returned and part of the output, or all the output, can be * missing because of I/O errors. * * When the function returns C_ERR and if 'error' is not NULL, the * integer pointed by 'error' is set to the value of errno just after the I/O * error. */
| 1219 | * integer pointed by 'error' is set to the value of errno just after the I/O |
| 1220 | * error. */ |
| 1221 | int rdbSaveRio(rio *rdb, int *error, int rdbflags, rdbSaveInfo *rsi) { |
| 1222 | dictIterator *di = NULL; |
| 1223 | dictEntry *de; |
| 1224 | char magic[10]; |
| 1225 | uint64_t cksum; |
| 1226 | size_t processed = 0; |
| 1227 | int j; |
| 1228 | long key_count = 0; |
| 1229 | long long info_updated_time = 0; |
| 1230 | char *pname = (rdbflags & RDBFLAGS_AOF_PREAMBLE) ? "AOF rewrite" : "RDB"; |
| 1231 | |
| 1232 | if (server.rdb_checksum) |
| 1233 | rdb->update_cksum = rioGenericUpdateChecksum; |
| 1234 | snprintf(magic,sizeof(magic),"REDIS%04d",RDB_VERSION); |
| 1235 | if (rdbWriteRaw(rdb,magic,9) == -1) goto werr; |
| 1236 | if (rdbSaveInfoAuxFields(rdb,rdbflags,rsi) == -1) goto werr; |
| 1237 | if (rdbSaveModulesAux(rdb, REDISMODULE_AUX_BEFORE_RDB) == -1) goto werr; |
| 1238 | |
| 1239 | for (j = 0; j < server.dbnum; j++) { |
| 1240 | redisDb *db = server.db+j; |
| 1241 | dict *d = db->dict; |
| 1242 | if (dictSize(d) == 0) continue; |
| 1243 | di = dictGetSafeIterator(d); |
| 1244 | |
| 1245 | /* Write the SELECT DB opcode */ |
| 1246 | if (rdbSaveType(rdb,RDB_OPCODE_SELECTDB) == -1) goto werr; |
| 1247 | if (rdbSaveLen(rdb,j) == -1) goto werr; |
| 1248 | |
| 1249 | /* Write the RESIZE DB opcode. */ |
| 1250 | uint64_t db_size, expires_size; |
| 1251 | db_size = dictSize(db->dict); |
| 1252 | expires_size = dictSize(db->expires); |
| 1253 | if (rdbSaveType(rdb,RDB_OPCODE_RESIZEDB) == -1) goto werr; |
| 1254 | if (rdbSaveLen(rdb,db_size) == -1) goto werr; |
| 1255 | if (rdbSaveLen(rdb,expires_size) == -1) goto werr; |
| 1256 | |
| 1257 | /* Iterate this DB writing every entry */ |
| 1258 | while((de = dictNext(di)) != NULL) { |
| 1259 | sds keystr = dictGetKey(de); |
| 1260 | robj key, *o = dictGetVal(de); |
| 1261 | long long expire; |
| 1262 | |
| 1263 | initStaticStringObject(key,keystr); |
| 1264 | expire = getExpire(db,&key); |
| 1265 | if (rdbSaveKeyValuePair(rdb,&key,o,expire) == -1) goto werr; |
| 1266 | |
| 1267 | /* When this RDB is produced as part of an AOF rewrite, move |
| 1268 | * accumulated diff from parent to child while rewriting in |
| 1269 | * order to have a smaller final write. */ |
| 1270 | if (rdbflags & RDBFLAGS_AOF_PREAMBLE && |
| 1271 | rdb->processed_bytes > processed+AOF_READ_DIFF_INTERVAL_BYTES) |
| 1272 | { |
| 1273 | processed = rdb->processed_bytes; |
| 1274 | aofReadDiffFromParent(); |
| 1275 | } |
| 1276 | |
| 1277 | /* Update child info every 1 second (approximately). |
| 1278 | * in order to avoid calling mstime() on each iteration, we will |
no test coverage detected