Write a sequence of commands able to fully rebuild the dataset into * "filename". Used both by REWRITEAOF and BGREWRITEAOF. * * 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 AOF_REWRITE_ITEMS_PER_CMD items per time * are inserted using a single command. */
| 1647 | * and ZADD. However at max AOF_REWRITE_ITEMS_PER_CMD items per time |
| 1648 | * are inserted using a single command. */ |
| 1649 | int rewriteAppendOnlyFile(char *filename) { |
| 1650 | rio aof; |
| 1651 | FILE *fp = NULL; |
| 1652 | char tmpfile[256]; |
| 1653 | char byte; |
| 1654 | int nodata = 0; |
| 1655 | mstime_t start = 0; |
| 1656 | |
| 1657 | { // BEGIN GOTO SCOPED VARIABLES |
| 1658 | /* Note that we have to use a different temp name here compared to the |
| 1659 | * one used by rewriteAppendOnlyFileBackground() function. */ |
| 1660 | snprintf(tmpfile,sizeof(tmpfile),"temp-rewriteaof-%d.aof", (int) getpid()); |
| 1661 | fp = fopen(tmpfile,"w"); |
| 1662 | if (!fp) { |
| 1663 | serverLog(LL_WARNING, "Opening the temp file for AOF rewrite in rewriteAppendOnlyFile(): %s", strerror(errno)); |
| 1664 | return C_ERR; |
| 1665 | } |
| 1666 | |
| 1667 | g_pserver->aof_child_diff = sdsempty(); |
| 1668 | rioInitWithFile(&aof,fp); |
| 1669 | |
| 1670 | if (g_pserver->aof_rewrite_incremental_fsync) |
| 1671 | rioSetAutoSync(&aof,REDIS_AUTOSYNC_BYTES); |
| 1672 | |
| 1673 | startSaving(RDBFLAGS_AOF_PREAMBLE); |
| 1674 | |
| 1675 | if (g_pserver->aof_use_rdb_preamble) { |
| 1676 | int error; |
| 1677 | std::vector<const redisDbPersistentDataSnapshot*> vecpdb; |
| 1678 | for (int idb = 0; idb < cserver.dbnum; ++idb) |
| 1679 | { |
| 1680 | vecpdb.push_back(g_pserver->db[idb]); |
| 1681 | } |
| 1682 | if (rdbSaveRio(&aof,vecpdb.data(),&error,RDBFLAGS_AOF_PREAMBLE,NULL) == C_ERR) { |
| 1683 | errno = error; |
| 1684 | goto werr; |
| 1685 | } |
| 1686 | } else { |
| 1687 | if (rewriteAppendOnlyFileRio(&aof) == C_ERR) goto werr; |
| 1688 | } |
| 1689 | |
| 1690 | /* Do an initial slow fsync here while the parent is still sending |
| 1691 | * data, in order to make the next final fsync faster. */ |
| 1692 | if (fflush(fp) == EOF) goto werr; |
| 1693 | if (fsync(fileno(fp)) == -1) goto werr; |
| 1694 | |
| 1695 | /* Read again a few times to get more data from the parent. |
| 1696 | * We can't read forever (the server may receive data from clients |
| 1697 | * faster than it is able to send data to the child), so we try to read |
| 1698 | * some more data in a loop as soon as there is a good chance more data |
| 1699 | * will come. If it looks like we are wasting time, we abort (this |
| 1700 | * happens after 20 ms without new data). */ |
| 1701 | start = mstime(); |
| 1702 | while(mstime()-start < 1000 && nodata < 20) { |
| 1703 | if (aeWait(g_pserver->aof_pipe_read_data_from_parent, AE_READABLE, 1) <= 0) |
| 1704 | { |
| 1705 | nodata++; |
| 1706 | continue; |
no test coverage detected