This is an automated email from the ASF dual-hosted git repository. mhubail pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/asterixdb.git
The following commit(s) were added to refs/heads/master by this push: new 56bca65d94 [NO ISSUE][STO] Download metadata files on lazy caching 56bca65d94 is described below commit 56bca65d9485c303d57e2e9bbd974a85aefe359a Author: Murtadha Hubail <mhub...@apache.org> AuthorDate: Tue Oct 10 03:09:54 2023 +0300 [NO ISSUE][STO] Download metadata files on lazy caching - user model changes: no - storage format changes: no - interface changes: yes Details: - Download metadata files for the node storage partitions on bootstrap on lazy caching. - Use the local + uncached files list to perform list operations rather than calling the cloud API. - Delay partition clean up on promotion for cloud deployments. Change-Id: I8ba767d5ffa0257a429af8c455bacea3df7ff7a7 Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/17856 Reviewed-by: Wail Alkowaileet <wael....@gmail.com> Integration-Tests: Jenkins <jenk...@fulliautomatix.ics.uci.edu> Tested-by: Jenkins <jenk...@fulliautomatix.ics.uci.edu> --- .../org/apache/asterix/app/cc/GlobalTxManager.java | 3 ++- .../org/apache/asterix/app/nc/ReplicaManager.java | 3 +-- .../app/replication/NcLifecycleCoordinator.java | 5 ++-- .../apache/asterix/cloud/LazyCloudIOManager.java | 28 +++++++++++++++---- .../apache/asterix/cloud/lazy/IParallelCacher.java | 4 +++ .../asterix/cloud/lazy/NoOpParallelCacher.java | 8 ++++++ .../apache/asterix/cloud/lazy/ParallelCacher.java | 31 +++++++++++++++------- .../lazy/accessor/ReplaceableCloudAccessor.java | 21 ++++++++++++--- .../asterix/common/utils/StorageConstants.java | 1 + .../asterix/common/utils/StoragePathUtil.java | 8 ++++++ .../PersistentLocalResourceRepository.java | 1 + .../hyracks/storage/common/LocalResource.java | 2 +- 12 files changed, 91 insertions(+), 24 deletions(-) diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/cc/GlobalTxManager.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/cc/GlobalTxManager.java index b4223bc4cb..0786895581 100644 --- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/cc/GlobalTxManager.java +++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/cc/GlobalTxManager.java @@ -32,6 +32,7 @@ import org.apache.asterix.common.cluster.IGlobalTxManager; import org.apache.asterix.common.exceptions.ACIDException; import org.apache.asterix.common.messaging.api.ICCMessageBroker; import org.apache.asterix.common.transactions.IGlobalTransactionContext; +import org.apache.asterix.common.utils.StorageConstants; import org.apache.asterix.transaction.management.service.transaction.GlobalTransactionContext; import org.apache.asterix.transaction.management.service.transaction.GlobalTxInfo; import org.apache.hyracks.api.application.ICCServiceContext; @@ -182,7 +183,7 @@ public class GlobalTxManager implements IGlobalTxManager { @Override public void rollback() throws Exception { - Set<FileReference> txnLogFileRefs = ioManager.list(ioManager.resolve(".")); + Set<FileReference> txnLogFileRefs = ioManager.list(ioManager.resolve(StorageConstants.GLOBAL_TXN_DIR_NAME)); for (FileReference txnLogFileRef : txnLogFileRefs) { IGlobalTransactionContext context = new GlobalTransactionContext(txnLogFileRef, ioManager); txnContextRepository.put(context.getJobId(), context); diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/nc/ReplicaManager.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/nc/ReplicaManager.java index 0684442bee..101b1b0fe2 100644 --- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/nc/ReplicaManager.java +++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/nc/ReplicaManager.java @@ -129,9 +129,8 @@ public class ReplicaManager implements IReplicaManager { LOGGER.warn("promoting partition {}", partition); final PersistentLocalResourceRepository localResourceRepository = (PersistentLocalResourceRepository) appCtx.getLocalResourceRepository(); - localResourceRepository.cleanup(partition); - localResourceRepository.clearResourcesCache(); if (!appCtx.isCloudDeployment()) { + localResourceRepository.cleanup(partition); final IRecoveryManager recoveryManager = appCtx.getTransactionSubsystem().getRecoveryManager(); recoveryManager.replayReplicaPartitionLogs(Stream.of(partition).collect(Collectors.toSet()), true); } diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/replication/NcLifecycleCoordinator.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/replication/NcLifecycleCoordinator.java index 5d0901d1a5..4135f356b3 100644 --- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/replication/NcLifecycleCoordinator.java +++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/replication/NcLifecycleCoordinator.java @@ -219,7 +219,7 @@ public class NcLifecycleCoordinator implements INcLifecycleCoordinator { protected List<INCLifecycleTask> buildIdleNcRegTasks(String newNodeId, boolean metadataNode, SystemState state, Set<Integer> activePartitions) { final List<INCLifecycleTask> tasks = new ArrayList<>(); - Set<Integer> nodeActivePartitions = getNodeActivePartitions(newNodeId, activePartitions, metadataNode); + Set<Integer> nodeActivePartitions = getNodeActivePartitions(newNodeId, activePartitions, metadataNode, state); tasks.add(new UpdateNodeStatusTask(NodeStatus.BOOTING, nodeActivePartitions)); int metadataPartitionId = clusterManager.getMetadataPartition().getPartitionId(); // Add any cloud-related tasks @@ -322,7 +322,8 @@ public class NcLifecycleCoordinator implements INcLifecycleCoordinator { return true; } - protected Set<Integer> getNodeActivePartitions(String nodeId, Set<Integer> nodePartitions, boolean metadataNode) { + protected Set<Integer> getNodeActivePartitions(String nodeId, Set<Integer> nodePartitions, boolean metadataNode, + SystemState state) { if (metadataNode) { nodePartitions.add(clusterManager.getMetadataPartition().getPartitionId()); } diff --git a/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/LazyCloudIOManager.java b/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/LazyCloudIOManager.java index 1a99a345a9..97a61733f0 100644 --- a/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/LazyCloudIOManager.java +++ b/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/LazyCloudIOManager.java @@ -18,6 +18,7 @@ */ package org.apache.asterix.cloud; +import static org.apache.asterix.cloud.lazy.ParallelCacher.METADATA_FILTER; import static org.apache.asterix.common.utils.StorageConstants.PARTITION_DIR_PREFIX; import static org.apache.asterix.common.utils.StorageConstants.STORAGE_ROOT_DIR_NAME; @@ -79,7 +80,8 @@ final class LazyCloudIOManager extends AbstractCloudIOManager { */ @Override - protected void downloadPartitions(boolean metadataNode, int metadataPartition) throws HyracksDataException { + protected synchronized void downloadPartitions(boolean metadataNode, int metadataPartition) + throws HyracksDataException { // Get the files in all relevant partitions from the cloud Set<String> cloudFiles = cloudClient.listObjects(bucket, STORAGE_ROOT_DIR_NAME, IoUtil.NO_OP_FILTER).stream() .filter(f -> partitions.contains(StoragePathUtil.getPartitionNumFromRelativePath(f))) @@ -99,12 +101,15 @@ final class LazyCloudIOManager extends AbstractCloudIOManager { cloudFiles.removeAll(localFiles); int remainingUncachedFiles = cloudFiles.size(); if (remainingUncachedFiles > 0) { + LOGGER.debug("The number of uncached files: {}. Uncached files: {}", remainingUncachedFiles, cloudFiles); // Get list of FileReferences from the list of cloud (i.e., resolve each path's string to FileReference) List<FileReference> uncachedFiles = resolve(cloudFiles); // Create a parallel downloader using the given cloudClient IParallelDownloader downloader = cloudClient.createParallelDownloader(bucket, localIoManager); // Download metadata partition (if this node is a metadata node) downloadMetadataPartition(downloader, uncachedFiles, metadataNode, metadataPartition); + // Download all metadata files to avoid (List) calls to the cloud when listing/reading these files + downloadMetadataFiles(downloader, uncachedFiles); // Create a parallel cacher which download and monitor all uncached files ParallelCacher cacher = new ParallelCacher(downloader, uncachedFiles); // Local cache misses some files, cloud-based accessor is needed for read operations @@ -113,20 +118,18 @@ final class LazyCloudIOManager extends AbstractCloudIOManager { // Everything is cached, no need to invoke cloud-based accessor for read operations accessor = new LocalAccessor(cloudClient, bucket, localIoManager); } - - LOGGER.info("The number of uncached files: {}. Uncached files: {}", remainingUncachedFiles, cloudFiles); } private void downloadMetadataPartition(IParallelDownloader downloader, List<FileReference> uncachedFiles, boolean metadataNode, int metadataPartition) throws HyracksDataException { String partitionDir = PARTITION_DIR_PREFIX + metadataPartition; if (metadataNode && uncachedFiles.stream().anyMatch(f -> f.getRelativePath().contains(partitionDir))) { - LOGGER.info("Downloading metadata partition {}, Current uncached files: {}", metadataPartition, + LOGGER.debug("Downloading metadata partition {}, Current uncached files: {}", metadataPartition, uncachedFiles); FileReference metadataDir = resolve(STORAGE_ROOT_DIR_NAME + File.separator + partitionDir); downloader.downloadDirectories(Collections.singleton(metadataDir)); uncachedFiles.removeIf(f -> f.getRelativePath().contains(partitionDir)); - LOGGER.info("Finished downloading metadata partition. Current uncached files: {}", uncachedFiles); + LOGGER.debug("Finished downloading metadata partition. Current uncached files: {}", uncachedFiles); } } @@ -192,4 +195,19 @@ final class LazyCloudIOManager extends AbstractCloudIOManager { LOGGER.debug("{} {}", op, fileReference.getRelativePath()); } } + + private void downloadMetadataFiles(IParallelDownloader downloader, List<FileReference> uncachedFiles) + throws HyracksDataException { + Set<FileReference> uncachedMetadataFiles = ParallelCacher.getFiles(uncachedFiles, METADATA_FILTER); + if (!uncachedMetadataFiles.isEmpty()) { + LOGGER.debug("Downloading metadata files for all partitions; current uncached files: {}", uncachedFiles); + downloader.downloadFiles(uncachedMetadataFiles); + uncachedFiles.removeAll(uncachedMetadataFiles); + LOGGER.debug("Finished downloading metadata files for all partitions. Current uncached files: {}", + uncachedFiles); + } else { + LOGGER.debug("all metadata files for all partitions are already cached; current uncached files: {} ", + uncachedFiles); + } + } } diff --git a/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/lazy/IParallelCacher.java b/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/lazy/IParallelCacher.java index 7e4bc4fe76..66003563bd 100644 --- a/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/lazy/IParallelCacher.java +++ b/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/lazy/IParallelCacher.java @@ -18,7 +18,9 @@ */ package org.apache.asterix.cloud.lazy; +import java.io.FilenameFilter; import java.util.Collection; +import java.util.Set; import org.apache.hyracks.api.exceptions.HyracksDataException; import org.apache.hyracks.api.io.FileReference; @@ -32,6 +34,8 @@ public interface IParallelCacher { */ boolean isCached(FileReference indexDir); + Set<FileReference> getUncachedFiles(FileReference dir, FilenameFilter filter); + /** * Downloads all index's data files for all partitions. * The index is inferred from the path of the provided file. diff --git a/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/lazy/NoOpParallelCacher.java b/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/lazy/NoOpParallelCacher.java index 010433dbbf..a77652c1b3 100644 --- a/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/lazy/NoOpParallelCacher.java +++ b/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/lazy/NoOpParallelCacher.java @@ -18,7 +18,10 @@ */ package org.apache.asterix.cloud.lazy; +import java.io.FilenameFilter; import java.util.Collection; +import java.util.Collections; +import java.util.Set; import org.apache.hyracks.api.io.FileReference; @@ -30,6 +33,11 @@ public class NoOpParallelCacher implements IParallelCacher { return false; } + @Override + public Set<FileReference> getUncachedFiles(FileReference dir, FilenameFilter filter) { + return Collections.emptySet(); + } + @Override public boolean downloadData(FileReference indexFile) { return false; diff --git a/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/lazy/ParallelCacher.java b/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/lazy/ParallelCacher.java index 2d55d06598..3cc481e607 100644 --- a/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/lazy/ParallelCacher.java +++ b/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/lazy/ParallelCacher.java @@ -26,6 +26,7 @@ import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; import org.apache.asterix.cloud.clients.IParallelDownloader; import org.apache.asterix.common.utils.StorageConstants; @@ -41,12 +42,11 @@ import org.apache.logging.log4j.Logger; * @see org.apache.asterix.cloud.lazy.accessor.ReplaceableCloudAccessor */ public final class ParallelCacher implements IParallelCacher { - private static final Logger LOGGER = LogManager.getLogger(); - private static final FilenameFilter METADATA_FILTER = - ((dir, name) -> name.startsWith(StorageConstants.INDEX_NON_DATA_FILES_PREFIX)); + public static final FilenameFilter METADATA_FILTER = + ((dir, name) -> name.startsWith(StorageConstants.INDEX_NON_DATA_FILES_PREFIX)); + private static final Logger LOGGER = LogManager.getLogger(); private final IParallelDownloader downloader; - /** * Uncached Indexes subpaths */ @@ -82,6 +82,19 @@ public final class ParallelCacher implements IParallelCacher { return !indexSubPath.isEmpty() && !uncachedIndexes.contains(indexSubPath); } + @Override + public Set<FileReference> getUncachedFiles(FileReference dir, FilenameFilter filter) { + if (dir.getRelativePath().endsWith(StorageConstants.STORAGE_ROOT_DIR_NAME)) { + return uncachedDataFiles.stream() + .filter(f -> StoragePathUtil.hasSameStorageRoot(dir, f) && filter.accept(null, f.getName())) + .collect(Collectors.toSet()); + } + return uncachedDataFiles + .stream().filter(f -> StoragePathUtil.hasSameStorageRoot(dir, f) + && StoragePathUtil.isRelativeParent(dir, f) && filter.accept(null, f.getName())) + .collect(Collectors.toSet()); + } + @Override public synchronized boolean downloadData(FileReference indexFile) throws HyracksDataException { String indexSubPath = StoragePathUtil.getIndexSubPath(indexFile, false); @@ -92,13 +105,13 @@ public final class ParallelCacher implements IParallelCacher { } } - LOGGER.info("Downloading data files for {} in all partitions: {}", indexSubPath, toDownload); + LOGGER.debug("Downloading data files for {} in all partitions: {}", indexSubPath, toDownload); Collection<FileReference> failed = downloader.downloadDirectories(toDownload); if (!failed.isEmpty()) { LOGGER.warn("Failed to download data files {}. Re-downloading: {}", indexSubPath, failed); downloader.downloadFiles(failed); } - LOGGER.info("Finished downloading data files for {}", indexSubPath); + LOGGER.debug("Finished downloading data files for {}", indexSubPath); uncachedIndexes.remove(indexSubPath); uncachedDataFiles.removeIf(f -> f.getRelativePath().contains(indexSubPath)); return isEmpty(); @@ -114,9 +127,9 @@ public final class ParallelCacher implements IParallelCacher { } } - LOGGER.info("Downloading metadata files for {} in all partitions: {}", indexSubPath, toDownload); + LOGGER.debug("Downloading metadata files for {} in all partitions: {}", indexSubPath, toDownload); downloader.downloadFiles(toDownload); - LOGGER.info("Finished downloading metadata files for {}", indexSubPath); + LOGGER.debug("Finished downloading metadata files for {}", indexSubPath); uncachedMetadataFiles.removeAll(toDownload); return isEmpty(); } @@ -149,7 +162,7 @@ public final class ParallelCacher implements IParallelCacher { LOGGER.info("Parallel cacher was closed"); } - private Set<FileReference> getFiles(List<FileReference> uncachedFiles, FilenameFilter filter) { + public static Set<FileReference> getFiles(List<FileReference> uncachedFiles, FilenameFilter filter) { Set<FileReference> fileReferences = ConcurrentHashMap.newKeySet(); for (FileReference fileReference : uncachedFiles) { if (filter.accept(null, fileReference.getName())) { diff --git a/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/lazy/accessor/ReplaceableCloudAccessor.java b/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/lazy/accessor/ReplaceableCloudAccessor.java index 3dd579b7e4..bfa353a2a0 100644 --- a/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/lazy/accessor/ReplaceableCloudAccessor.java +++ b/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/lazy/accessor/ReplaceableCloudAccessor.java @@ -26,17 +26,21 @@ import org.apache.asterix.cloud.CloudFileHandle; import org.apache.asterix.cloud.bulk.IBulkOperationCallBack; import org.apache.asterix.cloud.clients.ICloudClient; import org.apache.asterix.cloud.lazy.IParallelCacher; +import org.apache.asterix.common.utils.StorageConstants; import org.apache.asterix.common.utils.StoragePathUtil; import org.apache.hyracks.api.exceptions.HyracksDataException; import org.apache.hyracks.api.io.FileReference; import org.apache.hyracks.api.io.IIOManager; import org.apache.hyracks.control.nc.io.IOManager; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; /** * ReplaceableCloudAccessor will be used when some (or all) of the files in the cloud storage are not cached locally. * It will be replaced by {@link LocalAccessor} once everything is cached */ public class ReplaceableCloudAccessor extends AbstractLazyAccessor { + private static final Logger LOGGER = LogManager.getLogger(); private final Set<Integer> partitions; private final ILazyAccessorReplacer replacer; private final IParallelCacher cacher; @@ -78,10 +82,18 @@ public class ReplaceableCloudAccessor extends AbstractLazyAccessor { @Override public Set<FileReference> doList(FileReference dir, FilenameFilter filter) throws HyracksDataException { - if (cacher.isCached(dir)) { - return localIoManager.list(dir, filter); + if (isTxnDir(dir)) { + return cloudBackedList(dir, filter); } - return cloudBackedList(dir, filter); + Set<FileReference> localList = localIoManager.list(dir, filter); + Set<FileReference> uncachedFiles = cacher.getUncachedFiles(dir, filter); + localList.addAll(uncachedFiles); + return localList; + } + + private static boolean isTxnDir(FileReference dir) { + return dir.getRelativePath().startsWith(StorageConstants.METADATA_TXN_NOWAL_DIR_NAME) + || dir.getName().equals(StorageConstants.GLOBAL_TXN_DIR_NAME); } @Override @@ -129,6 +141,7 @@ public class ReplaceableCloudAccessor extends AbstractLazyAccessor { } private Set<FileReference> cloudBackedList(FileReference dir, FilenameFilter filter) throws HyracksDataException { + LOGGER.debug("CLOUD LIST: {}", dir); Set<String> cloudFiles = cloudClient.listObjects(bucket, dir.getRelativePath(), filter); if (cloudFiles.isEmpty()) { return Collections.emptySet(); @@ -151,7 +164,7 @@ public class ReplaceableCloudAccessor extends AbstractLazyAccessor { // Add the remaining files that are not stored locally in their designated partitions (if any) for (String cloudFile : cloudFiles) { FileReference localFile = localIoManager.resolve(cloudFile); - if (isInNodePartition(cloudFile) && dir.getDeviceHandle().equals(localFile.getDeviceHandle())) { + if (isInNodePartition(cloudFile) && StoragePathUtil.hasSameStorageRoot(dir, localFile)) { localFiles.add(localFile); } } diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/utils/StorageConstants.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/utils/StorageConstants.java index ed9c48e68b..5dcaaf493a 100644 --- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/utils/StorageConstants.java +++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/utils/StorageConstants.java @@ -31,6 +31,7 @@ import org.apache.hyracks.storage.am.lsm.common.impls.ConcurrentMergePolicyFacto public class StorageConstants { public static final String METADATA_TXN_NOWAL_DIR_NAME = "mtd-txn-logs"; + public static final String GLOBAL_TXN_DIR_NAME = "."; public static final String STORAGE_ROOT_DIR_NAME = "storage"; public static final String INGESTION_LOGS_DIR_NAME = "ingestion_logs"; public static final String PARTITION_DIR_PREFIX = "partition_"; diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/utils/StoragePathUtil.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/utils/StoragePathUtil.java index 9862be7826..e9a8753995 100644 --- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/utils/StoragePathUtil.java +++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/utils/StoragePathUtil.java @@ -218,4 +218,12 @@ public class StoragePathUtil { } return relativePath.substring(start, end); } + + public static boolean hasSameStorageRoot(FileReference file1, FileReference file2) { + return file1.getDeviceHandle().equals(file2.getDeviceHandle()); + } + + public static boolean isRelativeParent(FileReference parent, FileReference child) { + return child.getRelativePath().startsWith(parent.getRelativePath()); + } } diff --git a/asterixdb/asterix-transactions/src/main/java/org/apache/asterix/transaction/management/resource/PersistentLocalResourceRepository.java b/asterixdb/asterix-transactions/src/main/java/org/apache/asterix/transaction/management/resource/PersistentLocalResourceRepository.java index 33cbf2dc04..96ae699588 100644 --- a/asterixdb/asterix-transactions/src/main/java/org/apache/asterix/transaction/management/resource/PersistentLocalResourceRepository.java +++ b/asterixdb/asterix-transactions/src/main/java/org/apache/asterix/transaction/management/resource/PersistentLocalResourceRepository.java @@ -566,6 +566,7 @@ public class PersistentLocalResourceRepository implements ILocalResourceReposito throw HyracksDataException.create(e); } } finally { + clearResourcesCache(); afterReadAccess(); } } diff --git a/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/LocalResource.java b/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/LocalResource.java index f5e29455c0..7722fb1f01 100644 --- a/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/LocalResource.java +++ b/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/LocalResource.java @@ -106,7 +106,7 @@ public class LocalResource implements Serializable, IJsonSerializable { @Override public String toString() { return new StringBuilder("{\"").append(LocalResource.class.getSimpleName()).append("\" : ").append("{\"id\" = ") - .append(id).append(", \"resource\" : ").append(resource).append(", \"version\" : ").append(version) + .append(id).append(", \"resource\" : ").append(getPath()).append(", \"version\" : ").append(version) .append(" } ").toString(); }