opendj-server-legacy/src/main/java/org/opends/server/replication/server/changelog/file/BlockLogReader.java
@@ -29,6 +29,7 @@ import org.forgerock.opendj.ldap.ByteStringBuilder; import org.forgerock.util.Pair; import org.forgerock.util.Reject; import org.forgerock.util.annotations.VisibleForTesting; import org.opends.server.replication.server.changelog.api.ChangelogException; import org.opends.server.replication.server.changelog.api.DBCursor.KeyMatchingStrategy; import org.opends.server.replication.server.changelog.api.DBCursor.PositionStrategy; @@ -530,12 +531,22 @@ * The position of reader on file. * @return the file position of the block start. */ @VisibleForTesting long getClosestBlockStartBeforeOrAtPosition(final long filePosition) { final int dist = getDistanceToNextBlockStart(filePosition, blockSize); return dist == 0 ? filePosition : filePosition + dist - blockSize; } @VisibleForTesting long getClosestBlockStartToEndOfFile() throws ChangelogException { final long fileLength = getFileLength(); long lastBlockStart = getClosestBlockStartBeforeOrAtPosition(fileLength); // block start is invalid if equal to file length return lastBlockStart < fileLength ? lastBlockStart : getClosestBlockStartBeforeOrAtPosition(fileLength-1); } /** * Returns the closest start of block which has a position strictly * higher than the provided file position. @@ -589,8 +600,7 @@ { try { final long fileSize = getFileLength(); final long lastBlockStart = getClosestBlockStartBeforeOrAtPosition(fileSize); final long lastBlockStart = getClosestBlockStartToEndOfFile(); positionToRecordFromBlockStart(lastBlockStart); long lastValidPosition = lastBlockStart; @@ -599,7 +609,7 @@ lastValidPosition = reader.getFilePointer(); } final boolean isFileValid = lastValidPosition == fileSize; final boolean isFileValid = lastValidPosition == getFileLength(); return isFileValid ? -1 : lastValidPosition; } catch (Exception e) @@ -613,13 +623,7 @@ Record<K, V> getNewestRecord() throws ChangelogException { try { final long fileLength = getFileLength(); long lastBlockStart = getClosestBlockStartBeforeOrAtPosition(fileLength); if (lastBlockStart == fileLength) { // this is not a valid block start, find the previous block start lastBlockStart = getClosestBlockStartBeforeOrAtPosition(fileLength-1); } long lastBlockStart = getClosestBlockStartToEndOfFile(); positionToRecordFromBlockStart(lastBlockStart); ByteString candidate = readNextRecord(); ByteString record = candidate; opendj-server-legacy/src/test/java/org/opends/server/replication/server/changelog/file/BlockLogReaderWriterTest.java
@@ -15,7 +15,8 @@ */ package org.opends.server.replication.server.changelog.file; import static org.assertj.core.api.Assertions.*; import static org.assertj.core.api.Assertions.assertThat; import static org.opends.server.replication.server.changelog.api.DBCursor.KeyMatchingStrategy.*; import static org.opends.server.replication.server.changelog.api.DBCursor.PositionStrategy.*; import static org.opends.server.replication.server.changelog.file.BlockLogReader.*; @@ -251,7 +252,7 @@ } @Test public void testGetClosestMarkerBeforeOrAtPosition() throws Exception public void testGetClosestBlockStartBeforeOrAtPosition() throws Exception { final int blockSize = 10; BlockLogReader<Integer, Integer> reader = newReaderWithNullFile(blockSize); @@ -295,6 +296,36 @@ } } @DataProvider Object[][] recordsForEndOfFile() { return new Object[][] { // raw size taken by each record is: 4 (record size) + 4 (key) + 4 (value) = 12 bytes // size of block, records to write, expected closest block start to end of file { 12, records(1), 0 }, // zero block marker { 10, records(1), 10 }, // one block marker { 8, records(1), 8 }, // one block marker { 7, records(1), 14 }, // two block markers { 6, records(1), 18 }, // three block markers { 5, records(1), 35 }, // seven block markers { 16, records(1,2), 16 }, // one block marker { 12, records(1,2), 24 }, // two block markers { 10, records(1,2), 30 }, // three block markers }; } @Test(dataProvider="recordsForEndOfFile") public void testGetClosestBlockStartToEndOfFile(int blockSize, List<Record<Integer, Integer>> records, int expectedBlockStart) throws Exception { writeRecords(blockSize, records); try(BlockLogReader<Integer, Integer> reader = newReader(blockSize)) { assertThat(reader.getClosestBlockStartToEndOfFile()).isEqualTo(expectedBlockStart); } } @Test public void testGetClosestMarkerStrictlyAfterPosition() throws Exception {