Commit ccfabfa
authored
fix Bookkeeper can't startup cause by 'IOException: Recovery log xxx is missing' (apache#4740)
* fix apache#4105
When journal and dbledgerstorage on the same disk, concurrent checkpointComplete calls from SyncThread and SingleDirectoryDbLedgerStorage.flush() can overwrite lastMark backwards,causing journal files to be deleted while still referenced by the older mark.
* fix apache#4105
When singleLedgerDirs=true, bookie can crash on restart with "Recovery log is missing" due to lastMark file being overwritten backwards.
Root cause
SyncThread.flush() has a nested call pattern that causes lastMark regression:
SyncThread.flush():
1. outerCheckpoint = newCheckpoint() → mark = (file 5, offset 100)
2. ledgerStorage.flush()
→ SingleDirectoryDbLedgerStorage.flush():
a. innerCheckpoint = newCheckpoint() → mark = (file 7, offset 200), journal has advanced
b. flushes data to disk
c. checkpointComplete(mark=7, compact=true)
→ persists lastMark=7, deletes journal files with id < 7 (including file 5)
3. checkpointComplete(mark=5, compact=false)
→ persists lastMark=5, overwriting the 7 written in step 2c
4. Bookie restarts → reads lastMark=5 → file 5 no longer exists → crash
Step 1 captures the checkpoint before step 2 runs, so it is always older. Step 2c advances lastMark and garbage-collects old journals. Step 3 then overwrites lastMark backwards to a
position whose journal file was already deleted.
Conditions
- singleLedgerDirs=true (journal and ledger on the same disk, so SingleDirectoryDbLedgerStorage.flush() calls checkpointComplete internally)
- Journal file rotates between the two newCheckpoint() calls (requires sufficient write throughput)
- maxBackupJournals small enough for old files to actually be deleted
Fix
Add a monotonic guard in checkpointComplete(): track the highest mark persisted so far, skip any call with an older mark. This prevents rollLog from overwriting lastMark backwards.
* fix apache#4105
When singleLedgerDirs=true, bookie can crash on restart with "Recovery log is missing" due to lastMark file being overwritten backwards.
Root cause
SyncThread.flush() has a nested call pattern that causes lastMark regression:
SyncThread.flush():
1. outerCheckpoint = newCheckpoint() → mark = (file 5, offset 100)
2. ledgerStorage.flush()
→ SingleDirectoryDbLedgerStorage.flush():
a. innerCheckpoint = newCheckpoint() → mark = (file 7, offset 200), journal has advanced
b. flushes data to disk
c. checkpointComplete(mark=7, compact=true)
→ persists lastMark=7, deletes journal files with id < 7 (including file 5)
3. checkpointComplete(mark=5, compact=false)
→ persists lastMark=5, overwriting the 7 written in step 2c
4. Bookie restarts → reads lastMark=5 → file 5 no longer exists → crash
Step 1 captures the checkpoint before step 2 runs, so it is always older. Step 2c advances lastMark and garbage-collects old journals. Step 3 then overwrites lastMark backwards to a
position whose journal file was already deleted.
Conditions
- singleLedgerDirs=true (journal and ledger on the same disk, so SingleDirectoryDbLedgerStorage.flush() calls checkpointComplete internally)
- Journal file rotates between the two newCheckpoint() calls (requires sufficient write throughput)
- maxBackupJournals small enough for old files to actually be deleted
Fix
Add a monotonic guard in checkpointComplete(): track the highest mark persisted so far, skip any call with an older mark. This prevents rollLog from overwriting lastMark backwards.
* fix apache#4105
When singleLedgerDirs=true, bookie can crash on restart with "Recovery log is missing" due to lastMark file being overwritten backwards.
Root cause
SyncThread.flush() has a nested call pattern that causes lastMark regression:
SyncThread.flush():
1. outerCheckpoint = newCheckpoint() → mark = (file 5, offset 100)
2. ledgerStorage.flush()
→ SingleDirectoryDbLedgerStorage.flush():
a. innerCheckpoint = newCheckpoint() → mark = (file 7, offset 200), journal has advanced
b. flushes data to disk
c. checkpointComplete(mark=7, compact=true)
→ persists lastMark=7, deletes journal files with id < 7 (including file 5)
3. checkpointComplete(mark=5, compact=false)
→ persists lastMark=5, overwriting the 7 written in step 2c
4. Bookie restarts → reads lastMark=5 → file 5 no longer exists → crash
Step 1 captures the checkpoint before step 2 runs, so it is always older. Step 2c advances lastMark and garbage-collects old journals. Step 3 then overwrites lastMark backwards to a
position whose journal file was already deleted.
Conditions
- singleLedgerDirs=true (journal and ledger on the same disk, so SingleDirectoryDbLedgerStorage.flush() calls checkpointComplete internally)
- Journal file rotates between the two newCheckpoint() calls (requires sufficient write throughput)
- maxBackupJournals small enough for old files to actually be deleted
Fix
Add a monotonic guard in checkpointComplete(): track the highest mark persisted so far, skip any call with an older mark. This prevents rollLog from overwriting lastMark backwards.
* Fix lastMark regression in checkpoint completion1 parent 8e88b03 commit ccfabfa
2 files changed
Lines changed: 269 additions & 1 deletion
File tree
- bookkeeper-server/src
- main/java/org/apache/bookkeeper/bookie
- test/java/org/apache/bookkeeper/bookie/storage/ldb
Lines changed: 29 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
628 | 628 | | |
629 | 629 | | |
630 | 630 | | |
| 631 | + | |
| 632 | + | |
| 633 | + | |
| 634 | + | |
631 | 635 | | |
632 | 636 | | |
633 | 637 | | |
| |||
705 | 709 | | |
706 | 710 | | |
707 | 711 | | |
| 712 | + | |
| 713 | + | |
708 | 714 | | |
709 | 715 | | |
710 | 716 | | |
| |||
771 | 777 | | |
772 | 778 | | |
773 | 779 | | |
| 780 | + | |
| 781 | + | |
| 782 | + | |
774 | 783 | | |
775 | 784 | | |
776 | 785 | | |
| |||
781 | 790 | | |
782 | 791 | | |
783 | 792 | | |
784 | | - | |
| 793 | + | |
| 794 | + | |
| 795 | + | |
| 796 | + | |
| 797 | + | |
| 798 | + | |
| 799 | + | |
| 800 | + | |
| 801 | + | |
| 802 | + | |
785 | 803 | | |
786 | 804 | | |
787 | 805 | | |
| |||
803 | 821 | | |
804 | 822 | | |
805 | 823 | | |
| 824 | + | |
| 825 | + | |
| 826 | + | |
| 827 | + | |
| 828 | + | |
| 829 | + | |
| 830 | + | |
| 831 | + | |
| 832 | + | |
| 833 | + | |
806 | 834 | | |
807 | 835 | | |
808 | 836 | | |
| |||
Lines changed: 240 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
32 | 32 | | |
33 | 33 | | |
34 | 34 | | |
| 35 | + | |
35 | 36 | | |
36 | 37 | | |
37 | 38 | | |
38 | 39 | | |
39 | 40 | | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
40 | 46 | | |
41 | 47 | | |
42 | 48 | | |
| |||
45 | 51 | | |
46 | 52 | | |
47 | 53 | | |
| 54 | + | |
48 | 55 | | |
| 56 | + | |
49 | 57 | | |
50 | 58 | | |
51 | 59 | | |
52 | 60 | | |
53 | 61 | | |
54 | 62 | | |
55 | 63 | | |
| 64 | + | |
56 | 65 | | |
57 | 66 | | |
58 | 67 | | |
| |||
881 | 890 | | |
882 | 891 | | |
883 | 892 | | |
| 893 | + | |
| 894 | + | |
| 895 | + | |
| 896 | + | |
| 897 | + | |
| 898 | + | |
| 899 | + | |
| 900 | + | |
| 901 | + | |
| 902 | + | |
| 903 | + | |
| 904 | + | |
| 905 | + | |
| 906 | + | |
| 907 | + | |
| 908 | + | |
| 909 | + | |
| 910 | + | |
| 911 | + | |
| 912 | + | |
| 913 | + | |
| 914 | + | |
| 915 | + | |
| 916 | + | |
| 917 | + | |
| 918 | + | |
| 919 | + | |
| 920 | + | |
| 921 | + | |
| 922 | + | |
| 923 | + | |
| 924 | + | |
| 925 | + | |
| 926 | + | |
| 927 | + | |
| 928 | + | |
| 929 | + | |
| 930 | + | |
| 931 | + | |
| 932 | + | |
| 933 | + | |
| 934 | + | |
| 935 | + | |
| 936 | + | |
| 937 | + | |
| 938 | + | |
| 939 | + | |
| 940 | + | |
| 941 | + | |
| 942 | + | |
| 943 | + | |
| 944 | + | |
| 945 | + | |
| 946 | + | |
| 947 | + | |
| 948 | + | |
| 949 | + | |
| 950 | + | |
| 951 | + | |
| 952 | + | |
| 953 | + | |
| 954 | + | |
| 955 | + | |
| 956 | + | |
| 957 | + | |
| 958 | + | |
| 959 | + | |
| 960 | + | |
| 961 | + | |
| 962 | + | |
| 963 | + | |
| 964 | + | |
| 965 | + | |
| 966 | + | |
| 967 | + | |
| 968 | + | |
| 969 | + | |
| 970 | + | |
| 971 | + | |
| 972 | + | |
| 973 | + | |
| 974 | + | |
| 975 | + | |
| 976 | + | |
| 977 | + | |
| 978 | + | |
| 979 | + | |
| 980 | + | |
| 981 | + | |
| 982 | + | |
| 983 | + | |
| 984 | + | |
| 985 | + | |
| 986 | + | |
| 987 | + | |
| 988 | + | |
| 989 | + | |
| 990 | + | |
| 991 | + | |
| 992 | + | |
| 993 | + | |
| 994 | + | |
| 995 | + | |
| 996 | + | |
| 997 | + | |
| 998 | + | |
| 999 | + | |
| 1000 | + | |
| 1001 | + | |
| 1002 | + | |
| 1003 | + | |
| 1004 | + | |
| 1005 | + | |
| 1006 | + | |
| 1007 | + | |
| 1008 | + | |
| 1009 | + | |
| 1010 | + | |
| 1011 | + | |
| 1012 | + | |
| 1013 | + | |
| 1014 | + | |
| 1015 | + | |
| 1016 | + | |
| 1017 | + | |
| 1018 | + | |
| 1019 | + | |
| 1020 | + | |
| 1021 | + | |
| 1022 | + | |
| 1023 | + | |
| 1024 | + | |
| 1025 | + | |
| 1026 | + | |
| 1027 | + | |
| 1028 | + | |
| 1029 | + | |
| 1030 | + | |
| 1031 | + | |
| 1032 | + | |
| 1033 | + | |
| 1034 | + | |
| 1035 | + | |
| 1036 | + | |
| 1037 | + | |
| 1038 | + | |
| 1039 | + | |
| 1040 | + | |
| 1041 | + | |
| 1042 | + | |
| 1043 | + | |
| 1044 | + | |
| 1045 | + | |
| 1046 | + | |
| 1047 | + | |
| 1048 | + | |
| 1049 | + | |
| 1050 | + | |
| 1051 | + | |
| 1052 | + | |
| 1053 | + | |
| 1054 | + | |
| 1055 | + | |
| 1056 | + | |
| 1057 | + | |
| 1058 | + | |
| 1059 | + | |
| 1060 | + | |
| 1061 | + | |
| 1062 | + | |
| 1063 | + | |
| 1064 | + | |
| 1065 | + | |
| 1066 | + | |
| 1067 | + | |
| 1068 | + | |
| 1069 | + | |
| 1070 | + | |
| 1071 | + | |
| 1072 | + | |
| 1073 | + | |
| 1074 | + | |
| 1075 | + | |
| 1076 | + | |
| 1077 | + | |
| 1078 | + | |
| 1079 | + | |
| 1080 | + | |
| 1081 | + | |
| 1082 | + | |
| 1083 | + | |
| 1084 | + | |
| 1085 | + | |
| 1086 | + | |
| 1087 | + | |
| 1088 | + | |
| 1089 | + | |
| 1090 | + | |
| 1091 | + | |
| 1092 | + | |
| 1093 | + | |
| 1094 | + | |
| 1095 | + | |
| 1096 | + | |
| 1097 | + | |
| 1098 | + | |
| 1099 | + | |
| 1100 | + | |
| 1101 | + | |
| 1102 | + | |
| 1103 | + | |
| 1104 | + | |
| 1105 | + | |
| 1106 | + | |
| 1107 | + | |
| 1108 | + | |
| 1109 | + | |
| 1110 | + | |
| 1111 | + | |
| 1112 | + | |
| 1113 | + | |
| 1114 | + | |
| 1115 | + | |
| 1116 | + | |
| 1117 | + | |
| 1118 | + | |
| 1119 | + | |
| 1120 | + | |
| 1121 | + | |
| 1122 | + | |
| 1123 | + | |
884 | 1124 | | |
0 commit comments