|
24 | 24 | import static org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willCompleteSuccessfully; |
25 | 25 | import static org.apache.ignite.internal.util.GridUnsafe.bufferAddress; |
26 | 26 | import static org.hamcrest.MatcherAssert.assertThat; |
| 27 | +import static org.hamcrest.Matchers.is; |
27 | 28 | import static org.junit.jupiter.api.Assertions.assertFalse; |
28 | 29 | import static org.junit.jupiter.api.Assertions.assertNull; |
29 | 30 | import static org.junit.jupiter.api.Assertions.assertSame; |
|
43 | 44 | import static org.mockito.Mockito.when; |
44 | 45 |
|
45 | 46 | import java.nio.ByteBuffer; |
| 47 | +import java.util.List; |
46 | 48 | import java.util.concurrent.CompletableFuture; |
47 | 49 | import java.util.concurrent.TimeoutException; |
48 | 50 | import java.util.concurrent.atomic.AtomicReference; |
@@ -110,6 +112,106 @@ void testMergeDeltaFileToMainFile() throws Throwable { |
110 | 112 | verify(deltaFilePageStoreIo, times(1)).stop(eq(true)); |
111 | 113 | } |
112 | 114 |
|
| 115 | + @Test |
| 116 | + void testMergeDeltaFileToMainFileWithNewerDeltaFile() throws Throwable { |
| 117 | + Compactor compactor = newCompactor(); |
| 118 | + |
| 119 | + DeltaFilePageStoreIo deltaFilePageStoreIo = createDeltaFilePageStoreIo(new int[]{0, 1}); |
| 120 | + when(deltaFilePageStoreIo.fileIndex()).thenReturn(2); |
| 121 | + FilePageStore filePageStore = createFilePageStore(deltaFilePageStoreIo); |
| 122 | + |
| 123 | + DeltaFilePageStoreIo newerDeltaFile = createDeltaFilePageStoreIo(new int[]{1, 2}); |
| 124 | + when(newerDeltaFile.fileIndex()).thenReturn(3); |
| 125 | + DeltaFilePageStoreIo olderDeltaFile = createDeltaFilePageStoreIo(new int[]{0, 1}); |
| 126 | + when(olderDeltaFile.fileIndex()).thenReturn(1); |
| 127 | + |
| 128 | + when(filePageStore.getCompletedDeltaFiles()).thenReturn(List.of(deltaFilePageStoreIo, olderDeltaFile, newerDeltaFile)); |
| 129 | + |
| 130 | + compactor.mergeDeltaFileToMainFile(filePageStore, deltaFilePageStoreIo, new CompactionMetricsTracker()); |
| 131 | + |
| 132 | + verify(deltaFilePageStoreIo, times(1)).readWithMergedToFilePageStoreCheck(eq(0L), eq(0L), any(ByteBuffer.class), anyBoolean()); |
| 133 | + |
| 134 | + verify(filePageStore, times(1)).getCompletedDeltaFiles(); |
| 135 | + verify(filePageStore, times(1)).write(eq(1L), any(ByteBuffer.class)); |
| 136 | + |
| 137 | + verify(filePageStore, times(1)).sync(); |
| 138 | + verify(filePageStore, times(1)).removeDeltaFile(eq(deltaFilePageStoreIo)); |
| 139 | + |
| 140 | + verify(deltaFilePageStoreIo, times(1)).markMergedToFilePageStore(); |
| 141 | + verify(deltaFilePageStoreIo, times(1)).stop(eq(true)); |
| 142 | + } |
| 143 | + |
| 144 | + @Test |
| 145 | + void testMergeDeltaFileWithMultipleNewerDeltaFiles() throws Throwable { |
| 146 | + Compactor compactor = newCompactor(); |
| 147 | + |
| 148 | + DeltaFilePageStoreIo deltaFilePageStoreIo = createDeltaFilePageStoreIo(new int[]{0, 1, 2, 3, 4, 5}); |
| 149 | + when(deltaFilePageStoreIo.fileIndex()).thenReturn(1); |
| 150 | + |
| 151 | + // Check processing the first page index. |
| 152 | + DeltaFilePageStoreIo newerDeltaFile1 = createDeltaFilePageStoreIo(new int[]{0}); |
| 153 | + when(newerDeltaFile1.fileIndex()).thenReturn(2); |
| 154 | + |
| 155 | + // Check processing the last page index. |
| 156 | + DeltaFilePageStoreIo newerDeltaFile2 = createDeltaFilePageStoreIo(new int[]{5}); |
| 157 | + when(newerDeltaFile2.fileIndex()).thenReturn(3); |
| 158 | + |
| 159 | + // No matches. |
| 160 | + DeltaFilePageStoreIo newerDeltaFileNoMatches = createDeltaFilePageStoreIo(new int[]{30}); |
| 161 | + when(newerDeltaFileNoMatches.fileIndex()).thenReturn(4); |
| 162 | + |
| 163 | + // Multiple page matches. |
| 164 | + DeltaFilePageStoreIo newerDeltaFile3 = createDeltaFilePageStoreIo(new int[]{2, 3}); |
| 165 | + when(newerDeltaFile3.fileIndex()).thenReturn(5); |
| 166 | + |
| 167 | + FilePageStore filePageStore = createFilePageStore(deltaFilePageStoreIo); |
| 168 | + when(filePageStore.getCompletedDeltaFiles()).thenReturn(List.of( |
| 169 | + deltaFilePageStoreIo, newerDeltaFile1, newerDeltaFileNoMatches, newerDeltaFile2, newerDeltaFile3 |
| 170 | + )); |
| 171 | + |
| 172 | + CompactionMetricsTracker tracker = new CompactionMetricsTracker(); |
| 173 | + compactor.mergeDeltaFileToMainFile(filePageStore, deltaFilePageStoreIo, tracker); |
| 174 | + |
| 175 | + // Pages 1, 4 were in no newer delta files, so they should be written. |
| 176 | + verify(filePageStore, times(2)).write(eq(1L), any(ByteBuffer.class)); |
| 177 | + |
| 178 | + verify(deltaFilePageStoreIo, times(1)).readWithMergedToFilePageStoreCheck(eq(1L), anyLong(), any(ByteBuffer.class), anyBoolean()); |
| 179 | + verify(deltaFilePageStoreIo, times(1)).readWithMergedToFilePageStoreCheck(eq(4L), anyLong(), any(ByteBuffer.class), anyBoolean()); |
| 180 | + |
| 181 | + verify(filePageStore, times(1)).sync(); |
| 182 | + verify(filePageStore, times(1)).removeDeltaFile(eq(deltaFilePageStoreIo)); |
| 183 | + |
| 184 | + assertThat(tracker.dataPagesSkipped(), is(4)); |
| 185 | + assertThat(tracker.dataPagesWritten(), is(2)); |
| 186 | + } |
| 187 | + |
| 188 | + @Test |
| 189 | + void testMergeDeltaFileWhenAllPagesSkipped() throws Throwable { |
| 190 | + Compactor compactor = newCompactor(); |
| 191 | + |
| 192 | + // Delta file to compact has pages [0, 1] |
| 193 | + DeltaFilePageStoreIo deltaFilePageStoreIo = createDeltaFilePageStoreIo(new int[]{0, 1}); |
| 194 | + when(deltaFilePageStoreIo.fileIndex()).thenReturn(1); |
| 195 | + |
| 196 | + DeltaFilePageStoreIo newerDeltaFile = createDeltaFilePageStoreIo(new int[]{0, 1}); |
| 197 | + when(newerDeltaFile.fileIndex()).thenReturn(2); |
| 198 | + |
| 199 | + FilePageStore filePageStore = createFilePageStore(deltaFilePageStoreIo); |
| 200 | + when(filePageStore.getCompletedDeltaFiles()).thenReturn(List.of(deltaFilePageStoreIo, newerDeltaFile)); |
| 201 | + |
| 202 | + compactor.mergeDeltaFileToMainFile(filePageStore, deltaFilePageStoreIo, new CompactionMetricsTracker()); |
| 203 | + |
| 204 | + verify(filePageStore, never()).write(anyLong(), any(ByteBuffer.class)); |
| 205 | + |
| 206 | + verify(deltaFilePageStoreIo, never()).readWithMergedToFilePageStoreCheck(anyLong(), anyLong(), any(ByteBuffer.class), anyBoolean()); |
| 207 | + |
| 208 | + verify(filePageStore, never()).sync(); |
| 209 | + |
| 210 | + verify(filePageStore, times(1)).removeDeltaFile(eq(deltaFilePageStoreIo)); |
| 211 | + verify(deltaFilePageStoreIo, times(1)).markMergedToFilePageStore(); |
| 212 | + verify(deltaFilePageStoreIo, times(1)).stop(eq(true)); |
| 213 | + } |
| 214 | + |
113 | 215 | @Test |
114 | 216 | void testDoCompaction() throws Throwable { |
115 | 217 | FilePageStore filePageStore = mock(FilePageStore.class); |
@@ -282,9 +384,13 @@ private Compactor newCompactor(FilePageStoreManager filePageStoreManager) { |
282 | 384 | } |
283 | 385 |
|
284 | 386 | private static DeltaFilePageStoreIo createDeltaFilePageStoreIo() throws Exception { |
| 387 | + return createDeltaFilePageStoreIo(new int[]{0}); |
| 388 | + } |
| 389 | + |
| 390 | + private static DeltaFilePageStoreIo createDeltaFilePageStoreIo(int[] pageIndexes) throws Exception { |
285 | 391 | DeltaFilePageStoreIo deltaFilePageStoreIo = mock(DeltaFilePageStoreIo.class); |
286 | 392 |
|
287 | | - when(deltaFilePageStoreIo.pageIndexes()).thenReturn(new int[]{0}); |
| 393 | + when(deltaFilePageStoreIo.pageIndexes()).thenReturn(pageIndexes); |
288 | 394 |
|
289 | 395 | when(deltaFilePageStoreIo.readWithMergedToFilePageStoreCheck(anyLong(), anyLong(), any(ByteBuffer.class), anyBoolean())) |
290 | 396 | .then(answer -> { |
|
0 commit comments