-
Notifications
You must be signed in to change notification settings - Fork 143
IGNITE-27926 Implement Raft group destruction in Segstore #7958
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -114,6 +114,11 @@ class SegmentFileManager implements ManuallyCloseable { | |||||||||||
| */ | ||||||||||||
| static final byte[] SWITCH_SEGMENT_RECORD = new byte[8]; // 8 zero bytes. | ||||||||||||
|
|
||||||||||||
| /** | ||||||||||||
| * Special "destroy group" sentinel value for the log reset index. | ||||||||||||
| */ | ||||||||||||
| static final long GROUP_DESTROY_LOG_INDEX = 0L; | ||||||||||||
|
Comment on lines
+119
to
+120
|
||||||||||||
| */ | |
| static final long GROUP_DESTROY_LOG_INDEX = 0L; | |
| * Must not overlap with a valid stored log index. | |
| */ | |
| static final long GROUP_DESTROY_LOG_INDEX = -1L; |
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -646,6 +646,90 @@ void testCompactionOfFileAdjacentToStaleEntryInDequeCausesCorruption() throws Ex | |||||||||||
| }); | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| /** | ||||||||||||
| * Verifies that after {@link SegmentFileManager#destroyGroup} is called, the GC can remove segment files belonging | ||||||||||||
| * to the destroyed group. | ||||||||||||
| */ | ||||||||||||
| @Test | ||||||||||||
| void testSegmentFilesRemovedByGcAfterGroupDestroy() throws Exception { | ||||||||||||
| List<byte[]> batches = createRandomData(FILE_SIZE / 4, 10); | ||||||||||||
|
|
||||||||||||
| for (int i = 0; i < batches.size(); i++) { | ||||||||||||
| appendBytes(GROUP_ID_1, batches.get(i), i); | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| await().until(this::indexFiles, hasSize(equalTo(segmentFiles().size() - 1))); | ||||||||||||
|
|
||||||||||||
| List<Path> oldSegmentFiles = segmentFiles().subList(0, segmentFiles().size() - 1); | ||||||||||||
| List<Path> oldIndexFiles = indexFiles(); | ||||||||||||
|
|
||||||||||||
| fileManager.destroyGroup(GROUP_ID_1); | ||||||||||||
|
|
||||||||||||
| // The destroy tombstone is in the current segment file's memtable. Trigger a rollover using a different group so the | ||||||||||||
| // checkpoint thread processes the tombstone and removes GROUP_ID_1 from the in-memory index. | ||||||||||||
| triggerAndAwaitCheckpoint(GROUP_ID_2, 0); | ||||||||||||
|
|
||||||||||||
|
||||||||||||
| for (int i = 0; i < batches.size(); i++) { | |
| assertThat(getEntry(GROUP_ID_1, i), is((LogEntry) null)); | |
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This removal is keyed off
firstIndexKept == GROUP_DESTROY_LOG_INDEX, butfirstIndexKeptis also used for regular prefix/reset tombstones and can legitimately be0if a group ever uses log index 0 (the segstore tests do). In that case, this would incorrectly drop all in-memory index metadata for an active group, making entries unreachable and potentially causing the GC to delete/compact files incorrectly. Please make the “group destroyed” signal unambiguous (e.g., a separate persisted flag/record marker) or add a strict invariant (validated at write/reset boundaries) that log indices are always >= 1 so0can never occur except as a destroy marker.