This is an automated email from the ASF dual-hosted git repository.
shauryachats pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pinot.git
The following commit(s) were added to refs/heads/master by this push:
new 56438382353 Avoid mmap during predownload local segment check to
reduce page faults (#18467)
56438382353 is described below
commit 56438382353a13875e3fd47cfb0f56e14967a654
Author: rohit <[email protected]>
AuthorDate: Wed May 27 21:41:39 2026 +0530
Avoid mmap during predownload local segment check to reduce page faults
(#18467)
* Avoid mmap during predownload local segment check to reduce page faults
PredownloadScheduler.loadSegmentsFromLocal() previously opened a full
SegmentLocalFSDirectory(ReadMode.mmap) for each segment to read its CRC,
causing ~C×5 major page faults per segment (one per index chunk boundary
validated by SingleFileIndexDirectory.mapBufferEntries). On hosts with
thousands of segments this creates a page fault storm at startup.
The CRC is pre-written to creation.meta (8 bytes) during segment build
and does not require mmapping index files. Replace the SegmentDirectory
open with a direct read of creation.meta via DataInputStream, and replace
getDiskSizeBytes() with FileUtils.sizeOfDirectory() for the post-download
size metric. Both Phase 1 (local check) and Phase 2 (post-download size
reporting) now use this optimised path through loadSegmentFromLocal.
If a segment CRC matches but the local directory is corrupted, the server
startup path handles recovery: BaseTableDataManager.tryLoadExistingSegment
performs a full segment load, falling back to downloadAndLoadSegment to
re-fetch from deep store or peers.
* Address PR review comments
- Add warn log when creation.meta is not found (shauryachats)
- Add comment documenting creation.meta layout: [8 bytes CRC] [8 bytes
creation time] (chenboat)
- Wrap FileUtils.sizeOfDirectory in try-catch for TOCTOU race where
directory could be deleted between isDirectory check and size
computation (shauryachats)
- Fix temp dir name typo in PredownloadSchedulerTest (shauryachats)
- Move FileUtils.deleteQuietly to finally block in test (shauryachats)
- Convert Javadoc to markdown-style /// comments (tarun11Mavani)
Co-Authored-By: Claude Sonnet 4.6 (1M context) <[email protected]>
---------
Co-authored-by: Claude Sonnet 4.6 (1M context) <[email protected]>
---
.../server/predownload/PredownloadSegmentInfo.java | 36 +++++++--
.../server/predownload/PredownloadTableInfo.java | 77 +++++++-----------
.../predownload/PredownloadSchedulerTest.java | 37 +++++----
.../predownload/PredownloadSegmentInfoTest.java | 58 ++++++++++++++
.../predownload/PredownloadTableInfoTest.java | 90 +++++++++-------------
5 files changed, 178 insertions(+), 120 deletions(-)
diff --git
a/pinot-server/src/main/java/org/apache/pinot/server/predownload/PredownloadSegmentInfo.java
b/pinot-server/src/main/java/org/apache/pinot/server/predownload/PredownloadSegmentInfo.java
index 4f31d52b554..d876192ef5f 100644
---
a/pinot-server/src/main/java/org/apache/pinot/server/predownload/PredownloadSegmentInfo.java
+++
b/pinot-server/src/main/java/org/apache/pinot/server/predownload/PredownloadSegmentInfo.java
@@ -19,16 +19,20 @@
package org.apache.pinot.server.predownload;
import io.netty.util.internal.StringUtil;
+import java.io.DataInputStream;
import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
import javax.annotation.Nullable;
+import org.apache.commons.io.FileUtils;
import org.apache.pinot.common.metadata.segment.SegmentZKMetadata;
import org.apache.pinot.common.utils.config.TierConfigUtils;
import org.apache.pinot.segment.local.segment.index.loader.IndexLoadingConfig;
-import org.apache.pinot.segment.spi.index.metadata.SegmentMetadataImpl;
import org.apache.pinot.segment.spi.loader.SegmentDirectoryLoader;
import org.apache.pinot.segment.spi.loader.SegmentDirectoryLoaderContext;
import org.apache.pinot.segment.spi.loader.SegmentDirectoryLoaderRegistry;
import org.apache.pinot.segment.spi.store.SegmentDirectory;
+import org.apache.pinot.segment.spi.store.SegmentDirectoryPaths;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -172,9 +176,31 @@ public class PredownloadSegmentInfo {
}
}
- public void updateSegmentInfoFromLocal(@Nullable SegmentDirectory
segmentDirectory) {
- SegmentMetadataImpl segmentMetadata = (segmentDirectory == null) ? null :
segmentDirectory.getSegmentMetadata();
- _localCrc = (segmentMetadata == null) ? null : segmentMetadata.getCrc();
- _localSizeBytes = (segmentDirectory == null) ? 0 :
segmentDirectory.getDiskSizeBytes();
+ /// Populates local CRC and size from the segment directory on disk,
avoiding mmap of index files.
+ /// Reads CRC from `creation.meta` (8 bytes) and computes size via directory
traversal.
+ /// Sets `_localCrc` to null and `_localSizeBytes` to 0 if the segment or its
+ /// creation.meta does not exist.
+ public void updateSegmentInfoFromLocal(File segDir) {
+ if (!segDir.isDirectory()) {
+ LOGGER.warn("Segment path is not a directory: {}", segDir);
+ return;
+ }
+ File creationMeta = SegmentDirectoryPaths.findCreationMetaFile(segDir);
+ if (creationMeta == null || !creationMeta.exists()) {
+ LOGGER.warn("creation.meta not found for segment: {} of table: {}",
_segmentName, _tableNameWithType);
+ return;
+ }
+ try (DataInputStream ds = new DataInputStream(new
FileInputStream(creationMeta))) {
+ // creation.meta layout: [8 bytes CRC] [8 bytes creation time]
+ _localCrc = String.valueOf(ds.readLong());
+ } catch (IOException e) {
+ LOGGER.warn("Failed to read creation.meta for segment: {} of table: {}",
_segmentName, _tableNameWithType, e);
+ return;
+ }
+ try {
+ _localSizeBytes = FileUtils.sizeOfDirectory(segDir);
+ } catch (IllegalArgumentException e) {
+ LOGGER.warn("Failed to compute size for segment: {} of table: {}",
_segmentName, _tableNameWithType, e);
+ }
}
}
diff --git
a/pinot-server/src/main/java/org/apache/pinot/server/predownload/PredownloadTableInfo.java
b/pinot-server/src/main/java/org/apache/pinot/server/predownload/PredownloadTableInfo.java
index ed51c946837..90c37143905 100644
---
a/pinot-server/src/main/java/org/apache/pinot/server/predownload/PredownloadTableInfo.java
+++
b/pinot-server/src/main/java/org/apache/pinot/server/predownload/PredownloadTableInfo.java
@@ -20,8 +20,6 @@ package org.apache.pinot.server.predownload;
import java.io.File;
import javax.annotation.Nullable;
-import org.apache.pinot.segment.local.segment.index.loader.IndexLoadingConfig;
-import org.apache.pinot.segment.spi.store.SegmentDirectory;
import org.apache.pinot.spi.config.instance.InstanceDataManagerConfig;
import org.apache.pinot.spi.config.table.TableConfig;
import org.apache.pinot.spi.data.Schema;
@@ -45,16 +43,6 @@ public class PredownloadTableInfo {
_instanceDataManagerConfig = instanceDataManagerConfig;
}
- private static void closeSegmentDirectoryQuietly(@Nullable SegmentDirectory
segmentDirectory) {
- if (segmentDirectory != null) {
- try {
- segmentDirectory.close();
- } catch (Exception e) {
- LOGGER.warn("Failed to close SegmentDirectory due to error: {}",
e.getMessage());
- }
- }
- }
-
public TableConfig getTableConfig() {
return _tableConfig;
}
@@ -63,45 +51,38 @@ public class PredownloadTableInfo {
return _instanceDataManagerConfig;
}
- /**
- * After loading segment metadata from ZK, try to load from local and check
if we are able to skip
- * the downloading
- *
- * @param predownloadSegmentInfo SegmentInfo of segment to be loaded
- * @return true if already presents, false if needs to be downloaded
- */
+ /// Checks whether the segment already exists locally with a matching CRC,
and if so populates
+ /// its local size. Reads CRC directly from `creation.meta` and size from
directory
+ /// traversal — no mmap of index files is performed (segment loading).
+ ///
+ /// **Note:** a CRC match does not guarantee segment integrity. If the local
segment directory is
+ /// corrupted (e.g. truncated index files), the server startup path handles
recovery via
+ /// `BaseTableDataManager.addNewOnlineSegment` which performs a full segment
load. If loading fails, it falls
+ /// back to `downloadAndLoadSegment` to re-fetch the segment from deep store
or peers.
+ ///
+ /// @param predownloadSegmentInfo SegmentInfo of segment to be checked
+ /// @return true if the segment is present with matching CRC (download can
be skipped),
+ /// false if it is missing or has a CRC mismatch
public boolean loadSegmentFromLocal(PredownloadSegmentInfo
predownloadSegmentInfo) {
- SegmentDirectory segmentDirectory = null;
- try {
- segmentDirectory = getSegmentDirectory(predownloadSegmentInfo,
_instanceDataManagerConfig);
- predownloadSegmentInfo.updateSegmentInfoFromLocal(segmentDirectory);
+ File segDir = predownloadSegmentInfo.getSegmentDataDir(this, true);
+ if (!segDir.isDirectory()) {
+ LOGGER.info("Segment: {} of table: {} does not exist",
predownloadSegmentInfo.getSegmentName(),
+ _tableNameWithType);
+ return false;
+ }
+ predownloadSegmentInfo.updateSegmentInfoFromLocal(segDir);
- String segmentName = predownloadSegmentInfo.getSegmentName();
- // If the segment doesn't exist on server or its CRC has changed, then we
- // need to fall back to download the segment from deep store to load it.
- if (!predownloadSegmentInfo.hasSameCRC()) {
- if (predownloadSegmentInfo.getLocalCrc() == null) {
- LOGGER.info("Segment: {} of table: {} does not exist", segmentName,
_tableNameWithType);
- } else {
- LOGGER.info("Segment: {} of table: {} has crc change from: {} to:
{}", segmentName, _tableNameWithType,
- predownloadSegmentInfo.getLocalCrc(),
predownloadSegmentInfo.getCrc());
- }
- return false;
+ String segmentName = predownloadSegmentInfo.getSegmentName();
+ if (!predownloadSegmentInfo.hasSameCRC()) {
+ if (predownloadSegmentInfo.getLocalCrc() == null) {
+ LOGGER.info("Segment: {} of table: {} has no creation.meta",
segmentName, _tableNameWithType);
+ } else {
+ LOGGER.info("Segment: {} of table: {} has crc change from: {} to: {}",
segmentName, _tableNameWithType,
+ predownloadSegmentInfo.getLocalCrc(),
predownloadSegmentInfo.getCrc());
}
- LOGGER.info("Skip downloading segment: {} of table: {} as it already
exists", segmentName, _tableNameWithType);
- return true;
- } finally {
- closeSegmentDirectoryQuietly(segmentDirectory);
+ return false;
}
- }
-
- @Nullable
- private SegmentDirectory getSegmentDirectory(PredownloadSegmentInfo
predownloadSegmentInfo,
- InstanceDataManagerConfig instanceDataManagerConfig) {
- String dataDir = instanceDataManagerConfig.getInstanceDataDir() +
File.separator + _tableConfig.getTableName();
- IndexLoadingConfig indexLoadingConfig = new
IndexLoadingConfig(instanceDataManagerConfig, _tableConfig, _schema);
- indexLoadingConfig.setSegmentTier(predownloadSegmentInfo.getTier());
- indexLoadingConfig.setTableDataDir(dataDir);
- return predownloadSegmentInfo.initSegmentDirectory(indexLoadingConfig,
this);
+ LOGGER.info("Skip downloading segment: {} of table: {} as it already
exists", segmentName, _tableNameWithType);
+ return true;
}
}
diff --git
a/pinot-server/src/test/java/org/apache/pinot/server/predownload/PredownloadSchedulerTest.java
b/pinot-server/src/test/java/org/apache/pinot/server/predownload/PredownloadSchedulerTest.java
index c33f7498a3a..a5dca3bd8b5 100644
---
a/pinot-server/src/test/java/org/apache/pinot/server/predownload/PredownloadSchedulerTest.java
+++
b/pinot-server/src/test/java/org/apache/pinot/server/predownload/PredownloadSchedulerTest.java
@@ -18,8 +18,11 @@
*/
package org.apache.pinot.server.predownload;
+import java.io.DataOutputStream;
import java.io.File;
+import java.io.FileOutputStream;
import java.io.IOException;
+import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -32,8 +35,6 @@ import org.apache.helix.model.InstanceConfig;
import org.apache.pinot.common.metadata.segment.SegmentZKMetadata;
import org.apache.pinot.common.utils.TarCompressionUtils;
import org.apache.pinot.common.utils.fetcher.SegmentFetcherFactory;
-import org.apache.pinot.segment.spi.index.metadata.SegmentMetadataImpl;
-import org.apache.pinot.segment.spi.store.SegmentDirectory;
import org.apache.pinot.spi.config.instance.InstanceDataManagerConfig;
import org.apache.pinot.spi.config.table.TableConfig;
import org.apache.pinot.spi.env.CommonsConfigurationUtils;
@@ -216,25 +217,31 @@ public class PredownloadSchedulerTest {
_predownloadScheduler.getSegmentsInfo();
}
- public void loadSegmentsFromLocal() {
- // Only segment 3 will be loaded
- SegmentDirectory segmentDirectory = mock(SegmentDirectory.class);
- SegmentMetadataImpl segmentMetadata = mock(SegmentMetadataImpl.class);
- when(segmentDirectory.getSegmentMetadata()).thenReturn(segmentMetadata);
- when(segmentDirectory.getDiskSizeBytes()).thenReturn(DISK_SIZE_BYTES);
- when(segmentMetadata.getCrc()).thenReturn(String.valueOf(CRC));
+ public void loadSegmentsFromLocal()
+ throws Exception {
+ // Only segment 3 will be loaded — create a real creation.meta with
matching CRC
+ File seg3Dir = Files.createTempDirectory("predownload-seg3-").toFile();
+ File creationMeta = new File(seg3Dir, "creation.meta");
+ try (DataOutputStream dos = new DataOutputStream(new
FileOutputStream(creationMeta))) {
+ dos.writeLong(CRC);
+ dos.writeLong(0L);
+ }
when(_predownloadTableInfo.loadSegmentFromLocal(eq(_predownloadSegmentInfoList.get(2)))).thenAnswer(
invocation -> {
-
_predownloadSegmentInfoList.get(2).updateSegmentInfoFromLocal(segmentDirectory);
+
_predownloadSegmentInfoList.get(2).updateSegmentInfoFromLocal(seg3Dir);
return true;
});
when(_predownloadTableInfo.loadSegmentFromLocal(eq(_predownloadSegmentInfoList.get(0)))).thenReturn(false);
when(_predownloadTableInfo.loadSegmentFromLocal(eq(_predownloadSegmentInfoList.get(1)))).thenReturn(false);
- _predownloadScheduler.loadSegmentsFromLocal();
- assertEquals(_predownloadScheduler._failedSegments.size(), 1);
- assertEquals(_predownloadScheduler._failedSegments.iterator().next(),
- _predownloadSegmentInfoList.get(0).getSegmentName());
+ try {
+ _predownloadScheduler.loadSegmentsFromLocal();
+ assertEquals(_predownloadScheduler._failedSegments.size(), 1);
+ assertEquals(_predownloadScheduler._failedSegments.iterator().next(),
+ _predownloadSegmentInfoList.get(0).getSegmentName());
+ } finally {
+ FileUtils.deleteQuietly(seg3Dir);
+ }
}
public void downloadSegments()
@@ -271,6 +278,7 @@ public class PredownloadSchedulerTest {
if (!untaredFile.exists() && !untaredFile.mkdirs()) {
throw new IOException("Failed to create directory: " +
untaredFile.getAbsolutePath());
}
+ FileUtils.writeByteArrayToFile(new File(untaredFile, "dummy.idx"),
new byte[]{1, 2, 3, 4, 5});
return untaredFile;
});
try (MockedStatic<TarCompressionUtils> tarCompressionUtilsMockedStatic =
mockStatic(TarCompressionUtils.class)) {
@@ -280,6 +288,7 @@ public class PredownloadSchedulerTest {
if (!untaredFile.exists() && !untaredFile.mkdirs()) {
throw new IOException("Failed to create directory: " +
untaredFile.getAbsolutePath());
}
+ FileUtils.writeByteArrayToFile(new File(untaredFile,
"dummy.idx"), new byte[]{1, 2, 3, 4, 5});
return List.of(untaredFile);
});
diff --git
a/pinot-server/src/test/java/org/apache/pinot/server/predownload/PredownloadSegmentInfoTest.java
b/pinot-server/src/test/java/org/apache/pinot/server/predownload/PredownloadSegmentInfoTest.java
index bfc9c6e5f26..cb3933581d4 100644
---
a/pinot-server/src/test/java/org/apache/pinot/server/predownload/PredownloadSegmentInfoTest.java
+++
b/pinot-server/src/test/java/org/apache/pinot/server/predownload/PredownloadSegmentInfoTest.java
@@ -18,6 +18,10 @@
*/
package org.apache.pinot.server.predownload;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.nio.file.Files;
import org.apache.pinot.common.metadata.segment.SegmentZKMetadata;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
@@ -27,6 +31,7 @@ import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertThrows;
+import static org.testng.Assert.assertTrue;
public class PredownloadSegmentInfoTest {
@@ -69,4 +74,57 @@ public class PredownloadSegmentInfoTest {
_predownloadSegmentInfo.updateSegmentInfo(metadata);
assertThrows(PredownloadException.class, () ->
_predownloadSegmentInfo.getSegmentDataDir(null, true));
}
+
+ @Test
+ public void testUpdateSegmentInfoFromLocalFile()
+ throws Exception {
+ PredownloadSegmentInfo segmentInfo = new
PredownloadSegmentInfo(TABLE_NAME, SEGMENT_NAME);
+ segmentInfo.updateSegmentInfo(createSegmentZKMetadata());
+
+ File tempDir = Files.createTempDirectory("predownload-seg-test-").toFile();
+ try {
+ // Non-existent path — logs warning and returns without updating fields
+ File missingSegDir = new File(tempDir, "missing");
+ segmentInfo.updateSegmentInfoFromLocal(missingSegDir);
+ assertNull(segmentInfo.getLocalCrc());
+ assertEquals(segmentInfo.getLocalSizeBytes(), 0);
+
+ // Regular file (not a directory) — logs warning and returns without
updating fields
+ File regularFile = new File(tempDir, "not-a-dir");
+ assertTrue(regularFile.createNewFile());
+ segmentInfo.updateSegmentInfoFromLocal(regularFile);
+ assertNull(segmentInfo.getLocalCrc());
+ assertEquals(segmentInfo.getLocalSizeBytes(), 0);
+
+ // Segment directory exists but has no creation.meta — fields stay at
defaults
+ File segDir = new File(tempDir, SEGMENT_NAME);
+ assertTrue(segDir.mkdirs());
+ segmentInfo.updateSegmentInfoFromLocal(segDir);
+ assertNull(segmentInfo.getLocalCrc());
+ assertEquals(segmentInfo.getLocalSizeBytes(), 0);
+
+ // creation.meta present with matching CRC — fields populated,
isDownloaded true
+ File creationMeta = new File(segDir, "creation.meta");
+ try (DataOutputStream dos = new DataOutputStream(new
FileOutputStream(creationMeta))) {
+ dos.writeLong(CRC);
+ dos.writeLong(System.currentTimeMillis());
+ }
+ org.apache.commons.io.FileUtils.writeByteArrayToFile(new File(segDir,
"columns.psf"), new byte[]{1, 2, 3});
+ segmentInfo.updateSegmentInfoFromLocal(segDir);
+ assertEquals(segmentInfo.getLocalCrc(), String.valueOf(CRC));
+ assertTrue(segmentInfo.getLocalSizeBytes() > 0);
+ assertTrue(segmentInfo.isDownloaded());
+
+ // creation.meta present with different CRC — localCrc set, isDownloaded
false
+ try (DataOutputStream dos = new DataOutputStream(new
FileOutputStream(creationMeta))) {
+ dos.writeLong(CRC + 1);
+ dos.writeLong(System.currentTimeMillis());
+ }
+ segmentInfo.updateSegmentInfoFromLocal(segDir);
+ assertEquals(segmentInfo.getLocalCrc(), String.valueOf(CRC + 1));
+ assertFalse(segmentInfo.isDownloaded());
+ } finally {
+ org.apache.commons.io.FileUtils.deleteQuietly(tempDir);
+ }
+ }
}
diff --git
a/pinot-server/src/test/java/org/apache/pinot/server/predownload/PredownloadTableInfoTest.java
b/pinot-server/src/test/java/org/apache/pinot/server/predownload/PredownloadTableInfoTest.java
index b41af078e0d..6cbd06b3f46 100644
---
a/pinot-server/src/test/java/org/apache/pinot/server/predownload/PredownloadTableInfoTest.java
+++
b/pinot-server/src/test/java/org/apache/pinot/server/predownload/PredownloadTableInfoTest.java
@@ -18,25 +18,20 @@
*/
package org.apache.pinot.server.predownload;
-import java.io.IOException;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.nio.file.Files;
import org.apache.pinot.common.metadata.segment.SegmentZKMetadata;
-import org.apache.pinot.segment.spi.index.metadata.SegmentMetadataImpl;
-import org.apache.pinot.segment.spi.loader.SegmentDirectoryLoader;
-import org.apache.pinot.segment.spi.loader.SegmentDirectoryLoaderRegistry;
-import org.apache.pinot.segment.spi.store.SegmentDirectory;
-import org.apache.pinot.server.starter.helix.HelixInstanceDataManagerConfig;
import org.apache.pinot.spi.config.instance.InstanceDataManagerConfig;
import org.apache.pinot.spi.config.table.IndexingConfig;
import org.apache.pinot.spi.config.table.TableConfig;
import org.apache.pinot.spi.data.Schema;
import org.apache.pinot.spi.env.PinotConfiguration;
-import org.mockito.MockedStatic;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import static org.apache.pinot.server.predownload.PredownloadTestUtil.*;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
@@ -68,59 +63,48 @@ public class PredownloadTableInfoTest {
@Test
public void testLoadSegmentFromLocal()
throws Exception {
- PredownloadSegmentInfo predownloadSegmentInfo = new
PredownloadSegmentInfo(TABLE_NAME, SEGMENT_NAME);
- SegmentZKMetadata metadata = createSegmentZKMetadata();
- predownloadSegmentInfo.updateSegmentInfo(metadata);
- InstanceDataManagerConfig instanceDataManagerConfig = spy(new
HelixInstanceDataManagerConfig(_pinotConfiguration));
+ File tempDir =
Files.createTempDirectory("predownload-table-test-").toFile();
+ try {
+ PredownloadSegmentInfo predownloadSegmentInfo = new
PredownloadSegmentInfo(TABLE_NAME, SEGMENT_NAME);
+ SegmentZKMetadata metadata = createSegmentZKMetadata();
+ predownloadSegmentInfo.updateSegmentInfo(metadata);
- SegmentDirectoryLoader segmentDirectoryLoader =
mock(SegmentDirectoryLoader.class);
- SegmentDirectory segmentDirectory = mock(SegmentDirectory.class);
- SegmentMetadataImpl segmentMetadataImpl = mock(SegmentMetadataImpl.class);
-
when(segmentDirectory.getSegmentMetadata()).thenReturn(segmentMetadataImpl);
- when(segmentDirectory.getDiskSizeBytes()).thenReturn(DISK_SIZE_BYTES);
- when(segmentDirectoryLoader.load(any(),
any())).thenReturn(segmentDirectory);
+ when(_tableConfig.getTableName()).thenReturn(TABLE_NAME);
+
when(_instanceDataManagerConfig.getInstanceDataDir()).thenReturn(tempDir.getAbsolutePath());
+ when(_instanceDataManagerConfig.getTierConfigs()).thenReturn(null);
- // Has segment with same CRC
- try (MockedStatic<SegmentDirectoryLoaderRegistry>
segmentDirectoryLoaderRegistryMockedStatic = mockStatic(
- SegmentDirectoryLoaderRegistry.class)) {
- segmentDirectoryLoaderRegistryMockedStatic.when(
- () ->
SegmentDirectoryLoaderRegistry.getSegmentDirectoryLoader(anyString()))
- .thenReturn(segmentDirectoryLoader);
- when(segmentMetadataImpl.getCrc()).thenReturn(String.valueOf(CRC));
-
-
assertTrue(_predownloadTableInfo.loadSegmentFromLocal(predownloadSegmentInfo));
- assertEquals(predownloadSegmentInfo.getLocalCrc(), String.valueOf(CRC));
- assertTrue(predownloadSegmentInfo.isDownloaded());
- assertEquals(predownloadSegmentInfo.getLocalSizeBytes(),
DISK_SIZE_BYTES);
- }
-
- // Has segment with different CRC
- try (MockedStatic<SegmentDirectoryLoaderRegistry>
segmentDirectoryLoaderRegistryMockedStatic = mockStatic(
- SegmentDirectoryLoaderRegistry.class)) {
- segmentDirectoryLoaderRegistryMockedStatic.when(
- () ->
SegmentDirectoryLoaderRegistry.getSegmentDirectoryLoader(anyString()))
- .thenReturn(segmentDirectoryLoader);
- long newCrc = CRC + 1;
- when(segmentMetadataImpl.getCrc()).thenReturn(String.valueOf(newCrc));
+ // Segment directory does not exist — returns false
+
assertFalse(_predownloadTableInfo.loadSegmentFromLocal(predownloadSegmentInfo));
+ assertFalse(predownloadSegmentInfo.isDownloaded());
+ // Segment directory exists but no creation.meta — returns false
+ File segDir = new File(tempDir, TABLE_NAME + "/" + SEGMENT_NAME);
+ segDir.mkdirs();
assertFalse(_predownloadTableInfo.loadSegmentFromLocal(predownloadSegmentInfo));
- assertEquals(predownloadSegmentInfo.getLocalCrc(),
String.valueOf(newCrc));
assertFalse(predownloadSegmentInfo.isDownloaded());
- assertEquals(predownloadSegmentInfo.getLocalSizeBytes(),
DISK_SIZE_BYTES);
- }
- // Does not have segment
- try (MockedStatic<SegmentDirectoryLoaderRegistry>
segmentDirectoryLoaderRegistryMockedStatic = mockStatic(
- SegmentDirectoryLoaderRegistry.class)) {
- segmentDirectoryLoaderRegistryMockedStatic.when(
- () ->
SegmentDirectoryLoaderRegistry.getSegmentDirectoryLoader(anyString()))
- .thenReturn(segmentDirectoryLoader);
- when(segmentMetadataImpl.getCrc()).thenReturn(null);
- doThrow(IOException.class).when(segmentDirectory).close();
+ // creation.meta present with matching CRC — returns true and populates
size
+ File creationMeta = new File(segDir, "creation.meta");
+ try (DataOutputStream dos = new DataOutputStream(new
FileOutputStream(creationMeta))) {
+ dos.writeLong(CRC);
+ dos.writeLong(System.currentTimeMillis());
+ }
+ org.apache.commons.io.FileUtils.writeByteArrayToFile(new File(segDir,
"columns.psf"), new byte[]{1, 2, 3});
+
assertTrue(_predownloadTableInfo.loadSegmentFromLocal(predownloadSegmentInfo));
+ assertEquals(predownloadSegmentInfo.getLocalCrc(), String.valueOf(CRC));
+ assertTrue(predownloadSegmentInfo.isDownloaded());
+ assertTrue(predownloadSegmentInfo.getLocalSizeBytes() > 0);
+ // creation.meta present with different CRC — returns false
+ try (DataOutputStream dos = new DataOutputStream(new
FileOutputStream(creationMeta))) {
+ dos.writeLong(CRC + 1);
+ dos.writeLong(System.currentTimeMillis());
+ }
assertFalse(_predownloadTableInfo.loadSegmentFromLocal(predownloadSegmentInfo));
+ assertEquals(predownloadSegmentInfo.getLocalCrc(), String.valueOf(CRC +
1));
assertFalse(predownloadSegmentInfo.isDownloaded());
- assertEquals(predownloadSegmentInfo.getLocalSizeBytes(),
DISK_SIZE_BYTES);
+ } finally {
+ org.apache.commons.io.FileUtils.deleteQuietly(tempDir);
}
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]