Replay the append log file. On success C_OK is returned. On non fatal * error (the append only file is zero-length) C_ERR is returned. On * fatal error an error message is logged and the program exists. */
| 838 | * error (the append only file is zero-length) C_ERR is returned. On |
| 839 | * fatal error an error message is logged and the program exists. */ |
| 840 | int loadAppendOnlyFile(char *filename) { |
| 841 | struct client *fakeClient; |
| 842 | FILE *fp = fopen(filename,"r"); |
| 843 | struct redis_stat sb; |
| 844 | int old_aof_state = g_pserver->aof_state; |
| 845 | long loops = 0; |
| 846 | off_t valid_up_to = 0; /* Offset of latest well-formed command loaded. */ |
| 847 | off_t valid_before_multi = 0; /* Offset before MULTI command loaded. */ |
| 848 | serverAssert(serverTL != NULL); // This happens early in boot, ensure serverTL was setup |
| 849 | |
| 850 | if (fp == NULL) { |
| 851 | serverLog(LL_WARNING,"Fatal error: can't open the append log file for reading: %s",strerror(errno)); |
| 852 | exit(1); |
| 853 | } |
| 854 | |
| 855 | /* Handle a zero-length AOF file as a special case. An empty AOF file |
| 856 | * is a valid AOF because an empty server with AOF enabled will create |
| 857 | * a zero length file at startup, that will remain like that if no write |
| 858 | * operation is received. */ |
| 859 | if (fp && redis_fstat(fileno(fp),&sb) != -1 && sb.st_size == 0) { |
| 860 | g_pserver->aof_current_size = 0; |
| 861 | g_pserver->aof_fsync_offset = g_pserver->aof_current_size; |
| 862 | fclose(fp); |
| 863 | return C_ERR; |
| 864 | } |
| 865 | |
| 866 | /* Temporarily disable AOF, to prevent EXEC from feeding a MULTI |
| 867 | * to the same file we're about to read. */ |
| 868 | g_pserver->aof_state = AOF_OFF; |
| 869 | |
| 870 | fakeClient = createAOFClient(); |
| 871 | startLoadingFile(fp, filename, RDBFLAGS_AOF_PREAMBLE); |
| 872 | |
| 873 | for (int idb = 0; idb < cserver.dbnum; ++idb) |
| 874 | { |
| 875 | g_pserver->db[idb]->trackChanges(true); |
| 876 | } |
| 877 | |
| 878 | /* Check if this AOF file has an RDB preamble. In that case we need to |
| 879 | * load the RDB file and later continue loading the AOF tail. */ |
| 880 | char sig[5]; /* "REDIS" */ |
| 881 | if (fread(sig,1,5,fp) != 5 || memcmp(sig,"REDIS",5) != 0) { |
| 882 | /* No RDB preamble, seek back at 0 offset. */ |
| 883 | if (fseek(fp,0,SEEK_SET) == -1) goto readerr; |
| 884 | } else { |
| 885 | /* RDB preamble. Pass loading the RDB functions. */ |
| 886 | rio rdb; |
| 887 | rdbSaveInfo rsi; |
| 888 | |
| 889 | serverLog(LL_NOTICE,"Reading RDB preamble from AOF file..."); |
| 890 | if (fseek(fp,0,SEEK_SET) == -1) goto readerr; |
| 891 | rioInitWithFile(&rdb,fp); |
| 892 | if (rdbLoadRio(&rdb,RDBFLAGS_AOF_PREAMBLE,&rsi) != C_OK) { |
| 893 | serverLog(LL_WARNING,"Error reading the RDB preamble of the AOF file, AOF loading aborted"); |
| 894 | goto readerr; |
| 895 | } else { |
| 896 | serverLog(LL_NOTICE,"Reading the remaining AOF tail..."); |
| 897 | } |
no test coverage detected