From c30b3912ec10e59d53f231e14af3026bbc3f1ba7 Mon Sep 17 00:00:00 2001 From: Atanas Atanasov Date: Tue, 19 Nov 2024 16:52:44 +0200 Subject: [PATCH] WIP introducing PathResolver Signed-off-by: Atanas Atanasov --- .../PersistenceInjectionModule.java | 51 +++++++++++++++---- .../storage/path/AbstractPathResolver.java | 32 ++++++++++++ .../storage/path/BlockAsDirPathResolver.java | 34 +++++++++++++ .../storage/path/BlockAsFilePathResolver.java | 34 +++++++++++++ .../storage/path/NoOpPathResolver.java | 35 +++++++++++++ .../storage/path/PathResolver.java | 26 ++++++++++ .../storage/read/NoOpBlockReader.java | 6 +++ .../storage/remove/NoOpRemover.java | 6 +++ .../storage/write/AbstractBlockWriter.java | 7 ++- .../storage/write/BlockAsDirWriter.java | 12 +++-- .../write/BlockAsDirWriterBuilder.java | 17 +++++-- .../storage/write/BlockAsFileWriter.java | 8 ++- .../write/BlockAsFileWriterBuilder.java | 15 ++++-- .../storage/write/NoOpBlockWriter.java | 9 +++- server/src/main/java/module-info.java | 1 + server/src/main/resources/app.properties | 2 +- .../PbjBlockStreamServiceIntegrationTest.java | 19 ++++--- .../PersistenceInjectionModuleTest.java | 5 +- .../storage/read/BlockAsDirReaderTest.java | 11 ++-- .../storage/remove/BlockAsDirRemoverTest.java | 3 +- .../storage/write/BlockAsDirWriterTest.java | 11 ++-- 21 files changed, 291 insertions(+), 53 deletions(-) create mode 100644 server/src/main/java/com/hedera/block/server/persistence/storage/path/AbstractPathResolver.java create mode 100644 server/src/main/java/com/hedera/block/server/persistence/storage/path/BlockAsDirPathResolver.java create mode 100644 server/src/main/java/com/hedera/block/server/persistence/storage/path/BlockAsFilePathResolver.java create mode 100644 server/src/main/java/com/hedera/block/server/persistence/storage/path/NoOpPathResolver.java create mode 100644 server/src/main/java/com/hedera/block/server/persistence/storage/path/PathResolver.java diff --git a/server/src/main/java/com/hedera/block/server/persistence/PersistenceInjectionModule.java b/server/src/main/java/com/hedera/block/server/persistence/PersistenceInjectionModule.java index c4ec8258..f2b15447 100644 --- a/server/src/main/java/com/hedera/block/server/persistence/PersistenceInjectionModule.java +++ b/server/src/main/java/com/hedera/block/server/persistence/PersistenceInjectionModule.java @@ -21,6 +21,10 @@ import com.hedera.block.server.events.ObjectEvent; import com.hedera.block.server.persistence.storage.PersistenceStorageConfig; import com.hedera.block.server.persistence.storage.StorageType; +import com.hedera.block.server.persistence.storage.path.BlockAsDirPathResolver; +import com.hedera.block.server.persistence.storage.path.BlockAsFilePathResolver; +import com.hedera.block.server.persistence.storage.path.NoOpPathResolver; +import com.hedera.block.server.persistence.storage.path.PathResolver; import com.hedera.block.server.persistence.storage.read.BlockAsDirReaderBuilder; import com.hedera.block.server.persistence.storage.read.BlockAsFileReaderBuilder; import com.hedera.block.server.persistence.storage.read.BlockReader; @@ -49,7 +53,6 @@ /** A Dagger module for providing dependencies for Persistence Module. */ @Module public interface PersistenceInjectionModule { - /** * Provides a block writer singleton using the block node context. * @@ -59,9 +62,12 @@ public interface PersistenceInjectionModule { @Provides @Singleton static BlockWriter> providesBlockWriter( - @NonNull final BlockNodeContext blockNodeContext, @NonNull final BlockRemover blockRemover) { + @NonNull final BlockNodeContext blockNodeContext, + @NonNull final BlockRemover blockRemover, + @NonNull final PathResolver pathResolver) { Objects.requireNonNull(blockNodeContext); Objects.requireNonNull(blockRemover); + Objects.requireNonNull(pathResolver); final StorageType persistenceType = blockNodeContext .configuration() .getConfigData(PersistenceStorageConfig.class) @@ -70,11 +76,11 @@ static BlockWriter> providesBlockWriter( return switch (persistenceType) { case null -> throw new NullPointerException( "Persistence StorageType cannot be [null], cannot create an instance of BlockWriter"); - case BLOCK_AS_FILE -> BlockAsFileWriterBuilder.newBuilder(blockNodeContext, blockRemover) + case BLOCK_AS_FILE -> BlockAsFileWriterBuilder.newBuilder(blockNodeContext, blockRemover, pathResolver) .build(); - case BLOCK_AS_DIR -> BlockAsDirWriterBuilder.newBuilder(blockNodeContext, blockRemover) + case BLOCK_AS_DIR -> BlockAsDirWriterBuilder.newBuilder(blockNodeContext, blockRemover, pathResolver) .build(); - case NOOP -> new NoOpBlockWriter(blockNodeContext, blockRemover); + case NOOP -> new NoOpBlockWriter(blockNodeContext, blockRemover, pathResolver); }; } catch (final IOException e) { throw new RuntimeException("Failed to create BlockWriter", e); @@ -84,7 +90,8 @@ static BlockWriter> providesBlockWriter( /** * Provides a block reader singleton using the persistence storage config. * - * @param config the persistence storage configuration needed to build the block reader + * @param config the persistence storage configuration needed to build the + * block reader * @return a block reader singleton */ @Provides @@ -93,7 +100,7 @@ static BlockReader providesBlockReader(@NonNull final PersistenceStorageC final StorageType persistenceType = Objects.requireNonNull(config).type(); return switch (persistenceType) { case null -> throw new NullPointerException( - "Persistence StorageType cannot be [null], cannot create an instance of BlockWriter"); + "Persistence StorageType cannot be [null], cannot create an instance of BlockReader"); case BLOCK_AS_FILE -> BlockAsFileReaderBuilder.newBuilder().build(); case BLOCK_AS_DIR -> BlockAsDirReaderBuilder.newBuilder(config).build(); case NOOP -> new NoOpBlockReader(); @@ -101,10 +108,11 @@ static BlockReader providesBlockReader(@NonNull final PersistenceStorageC } /** - * Provides a block reader singleton using the persistence storage config. + * Provides a block remover singleton using the persistence storage config. * - * @param config the persistence storage configuration needed to build the block reader - * @return a block reader singleton + * @param config the persistence storage configuration needed to build the + * block remover + * @return a block remover singleton */ @Provides @Singleton @@ -112,13 +120,34 @@ static BlockRemover providesBlockRemover(@NonNull final PersistenceStorageConfig final StorageType persistenceType = Objects.requireNonNull(config).type(); return switch (persistenceType) { case null -> throw new NullPointerException( - "Persistence StorageType cannot be [null], cannot create an instance of BlockWriter"); + "Persistence StorageType cannot be [null], cannot create an instance of BlockRemover"); case BLOCK_AS_FILE -> new BlockAsFileRemover(); case BLOCK_AS_DIR -> new BlockAsDirRemover(Path.of(config.rootPath())); case NOOP -> new NoOpRemover(); }; } + /** + * Provides a path resolver singleton using the persistence storage config. + * + * @param config the persistence storage configuration needed to build the + * path resolver + * @return a path resolver singleton + */ + @Provides + @Singleton + static PathResolver providesPathResolver(@NonNull final PersistenceStorageConfig config) { + final StorageType persistenceType = Objects.requireNonNull(config).type(); + final Path root = Path.of(config.rootPath()); + return switch (persistenceType) { + case null -> throw new NullPointerException( + "Persistence StorageType cannot be [null], cannot create an instance of PathResolver"); + case BLOCK_AS_FILE -> new BlockAsFilePathResolver(root); + case BLOCK_AS_DIR -> new BlockAsDirPathResolver(root); + case NOOP -> new NoOpPathResolver(); + }; + } + /** * Binds the block node event handler to the stream persistence handler. * diff --git a/server/src/main/java/com/hedera/block/server/persistence/storage/path/AbstractPathResolver.java b/server/src/main/java/com/hedera/block/server/persistence/storage/path/AbstractPathResolver.java new file mode 100644 index 00000000..479abfd0 --- /dev/null +++ b/server/src/main/java/com/hedera/block/server/persistence/storage/path/AbstractPathResolver.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2024 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.hedera.block.server.persistence.storage.path; + +import edu.umd.cs.findbugs.annotations.NonNull; +import java.nio.file.Path; +import java.util.Objects; + +/** + * TODO: add documentation + */ +abstract class AbstractPathResolver implements PathResolver { + private final Path root; + + AbstractPathResolver(@NonNull final Path root) { + this.root = Objects.requireNonNull(root); + } +} diff --git a/server/src/main/java/com/hedera/block/server/persistence/storage/path/BlockAsDirPathResolver.java b/server/src/main/java/com/hedera/block/server/persistence/storage/path/BlockAsDirPathResolver.java new file mode 100644 index 00000000..b489d6c0 --- /dev/null +++ b/server/src/main/java/com/hedera/block/server/persistence/storage/path/BlockAsDirPathResolver.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2024 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.hedera.block.server.persistence.storage.path; + +import edu.umd.cs.findbugs.annotations.NonNull; +import java.nio.file.Path; + +/** + * TODO: add documentation + */ +public final class BlockAsDirPathResolver extends AbstractPathResolver { + public BlockAsDirPathResolver(@NonNull final Path root) { + super(root); + } + + @Override + public Path resolvePathToBlock(final long blockNumber) { + throw new UnsupportedOperationException("Not implemented yet"); + } +} diff --git a/server/src/main/java/com/hedera/block/server/persistence/storage/path/BlockAsFilePathResolver.java b/server/src/main/java/com/hedera/block/server/persistence/storage/path/BlockAsFilePathResolver.java new file mode 100644 index 00000000..e6824f4f --- /dev/null +++ b/server/src/main/java/com/hedera/block/server/persistence/storage/path/BlockAsFilePathResolver.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2024 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.hedera.block.server.persistence.storage.path; + +import edu.umd.cs.findbugs.annotations.NonNull; +import java.nio.file.Path; + +/** + * TODO: add documentation + */ +public final class BlockAsFilePathResolver extends AbstractPathResolver { + public BlockAsFilePathResolver(@NonNull final Path root) { + super(root); + } + + @Override + public Path resolvePathToBlock(final long blockNumber) { + throw new UnsupportedOperationException("Not implemented yet"); + } +} diff --git a/server/src/main/java/com/hedera/block/server/persistence/storage/path/NoOpPathResolver.java b/server/src/main/java/com/hedera/block/server/persistence/storage/path/NoOpPathResolver.java new file mode 100644 index 00000000..26c56fa2 --- /dev/null +++ b/server/src/main/java/com/hedera/block/server/persistence/storage/path/NoOpPathResolver.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2024 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.hedera.block.server.persistence.storage.path; + +import static java.lang.System.Logger.Level.INFO; + +import java.nio.file.Path; + +/** + * TODO: add documentation + */ +public final class NoOpPathResolver implements PathResolver { + public NoOpPathResolver() { + System.getLogger(getClass().getName()).log(INFO, "Using " + getClass().getSimpleName()); + } + + @Override + public Path resolvePathToBlock(final long blockNumber) { + return null; + } +} diff --git a/server/src/main/java/com/hedera/block/server/persistence/storage/path/PathResolver.java b/server/src/main/java/com/hedera/block/server/persistence/storage/path/PathResolver.java new file mode 100644 index 00000000..30fc0eeb --- /dev/null +++ b/server/src/main/java/com/hedera/block/server/persistence/storage/path/PathResolver.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2024 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.hedera.block.server.persistence.storage.path; + +import java.nio.file.Path; + +/** + * TODO: add documentation + */ +public interface PathResolver { + Path resolvePathToBlock(final long blockNumber); +} diff --git a/server/src/main/java/com/hedera/block/server/persistence/storage/read/NoOpBlockReader.java b/server/src/main/java/com/hedera/block/server/persistence/storage/read/NoOpBlockReader.java index c8669efe..4328cf32 100644 --- a/server/src/main/java/com/hedera/block/server/persistence/storage/read/NoOpBlockReader.java +++ b/server/src/main/java/com/hedera/block/server/persistence/storage/read/NoOpBlockReader.java @@ -16,6 +16,8 @@ package com.hedera.block.server.persistence.storage.read; +import static java.lang.System.Logger.Level.INFO; + import com.hedera.hapi.block.stream.Block; import com.hedera.pbj.runtime.ParseException; import edu.umd.cs.findbugs.annotations.NonNull; @@ -26,6 +28,10 @@ * TODO: add documentation */ public class NoOpBlockReader implements BlockReader { + public NoOpBlockReader() { + System.getLogger(getClass().getName()).log(INFO, "Using " + getClass().getSimpleName()); + } + @NonNull @Override public Optional read(final long blockNumber) throws IOException, ParseException { diff --git a/server/src/main/java/com/hedera/block/server/persistence/storage/remove/NoOpRemover.java b/server/src/main/java/com/hedera/block/server/persistence/storage/remove/NoOpRemover.java index d2a33afd..e15644b5 100644 --- a/server/src/main/java/com/hedera/block/server/persistence/storage/remove/NoOpRemover.java +++ b/server/src/main/java/com/hedera/block/server/persistence/storage/remove/NoOpRemover.java @@ -16,10 +16,16 @@ package com.hedera.block.server.persistence.storage.remove; +import static java.lang.System.Logger.Level.INFO; + /** * TODO: add documentation */ public class NoOpRemover implements BlockRemover { + public NoOpRemover() { + System.getLogger(getClass().getName()).log(INFO, "Using " + getClass().getSimpleName()); + } + @Override public void remove(final long blockNumber) { // do nothing diff --git a/server/src/main/java/com/hedera/block/server/persistence/storage/write/AbstractBlockWriter.java b/server/src/main/java/com/hedera/block/server/persistence/storage/write/AbstractBlockWriter.java index aebbf0be..fc5f0a26 100644 --- a/server/src/main/java/com/hedera/block/server/persistence/storage/write/AbstractBlockWriter.java +++ b/server/src/main/java/com/hedera/block/server/persistence/storage/write/AbstractBlockWriter.java @@ -19,6 +19,7 @@ import static com.hedera.block.server.metrics.BlockNodeMetricTypes.Counter.BlocksPersisted; import com.hedera.block.server.metrics.MetricsService; +import com.hedera.block.server.persistence.storage.path.PathResolver; import com.hedera.block.server.persistence.storage.remove.BlockRemover; import com.swirlds.metrics.api.Counter; import edu.umd.cs.findbugs.annotations.NonNull; @@ -30,12 +31,16 @@ abstract class AbstractBlockWriter implements BlockWriter { private final Counter blocksPersistedCounter; protected final BlockRemover blockRemover; + protected final PathResolver pathResolver; protected AbstractBlockWriter( - @NonNull final MetricsService metricsService, @NonNull final BlockRemover blockRemover) { + @NonNull final MetricsService metricsService, + @NonNull final BlockRemover blockRemover, + @NonNull final PathResolver pathResolver) { Objects.requireNonNull(metricsService); this.blocksPersistedCounter = Objects.requireNonNull(metricsService.get(BlocksPersisted)); this.blockRemover = Objects.requireNonNull(blockRemover); + this.pathResolver = Objects.requireNonNull(pathResolver); } protected final void incrementBlocksPersisted() { diff --git a/server/src/main/java/com/hedera/block/server/persistence/storage/write/BlockAsDirWriter.java b/server/src/main/java/com/hedera/block/server/persistence/storage/write/BlockAsDirWriter.java index 813e686e..b753ad0a 100644 --- a/server/src/main/java/com/hedera/block/server/persistence/storage/write/BlockAsDirWriter.java +++ b/server/src/main/java/com/hedera/block/server/persistence/storage/write/BlockAsDirWriter.java @@ -26,6 +26,7 @@ import com.hedera.block.common.utils.FileUtilities; import com.hedera.block.server.config.BlockNodeContext; import com.hedera.block.server.persistence.storage.PersistenceStorageConfig; +import com.hedera.block.server.persistence.storage.path.PathResolver; import com.hedera.block.server.persistence.storage.remove.BlockRemover; import com.hedera.hapi.block.stream.BlockItem; import edu.umd.cs.findbugs.annotations.NonNull; @@ -58,21 +59,24 @@ class BlockAsDirWriter extends AbstractBlockWriter> { private Path currentBlockDir; /** - * Use the corresponding builder to construct a new BlockAsDirWriter with the given parameters. + * Use the corresponding builder to construct a new BlockAsDirWriter with + * the given parameters. * * @param blockNodeContext the block node context to use for writing blocks * @param blockRemover the block remover to use for removing blocks - * @param folderPermissions the folder permissions to use for writing blocks, if null provided then defaults - * will be used + * @param pathResolver used internally to resolve paths + * @param folderPermissions the folder permissions to use for writing + * blocks, if null provided then defaults will be used * * @throws IOException if an error occurs while initializing the BlockAsDirWriter */ BlockAsDirWriter( @NonNull final BlockNodeContext blockNodeContext, @NonNull final BlockRemover blockRemover, + @NonNull final PathResolver pathResolver, final FileAttribute> folderPermissions) throws IOException { - super(blockNodeContext.metricsService(), blockRemover); + super(blockNodeContext.metricsService(), blockRemover, pathResolver); LOGGER.log(INFO, "Initializing FileSystemBlockStorage"); diff --git a/server/src/main/java/com/hedera/block/server/persistence/storage/write/BlockAsDirWriterBuilder.java b/server/src/main/java/com/hedera/block/server/persistence/storage/write/BlockAsDirWriterBuilder.java index 2052a4be..77a68ef0 100644 --- a/server/src/main/java/com/hedera/block/server/persistence/storage/write/BlockAsDirWriterBuilder.java +++ b/server/src/main/java/com/hedera/block/server/persistence/storage/write/BlockAsDirWriterBuilder.java @@ -17,6 +17,7 @@ package com.hedera.block.server.persistence.storage.write; import com.hedera.block.server.config.BlockNodeContext; +import com.hedera.block.server.persistence.storage.path.PathResolver; import com.hedera.block.server.persistence.storage.remove.BlockRemover; import com.hedera.hapi.block.stream.BlockItem; import edu.umd.cs.findbugs.annotations.NonNull; @@ -35,12 +36,16 @@ public final class BlockAsDirWriterBuilder { private final BlockNodeContext blockNodeContext; private final BlockRemover blockRemover; + private final PathResolver pathResolver; private FileAttribute> folderPermissions; private BlockAsDirWriterBuilder( - @NonNull final BlockNodeContext blockNodeContext, @NonNull final BlockRemover blockRemover) { + @NonNull final BlockNodeContext blockNodeContext, + @NonNull final BlockRemover blockRemover, + @NonNull final PathResolver pathResolver) { this.blockNodeContext = Objects.requireNonNull(blockNodeContext); this.blockRemover = Objects.requireNonNull(blockRemover); + this.pathResolver = Objects.requireNonNull(pathResolver); } /** @@ -48,13 +53,15 @@ private BlockAsDirWriterBuilder( * * @param blockNodeContext is required to provide metrics reporting mechanisms * @param blockRemover used internally - * + * @param pathResolver used internally * @return a block writer builder configured with required parameters. */ @NonNull public static BlockAsDirWriterBuilder newBuilder( - @NonNull final BlockNodeContext blockNodeContext, @NonNull final BlockRemover blockRemover) { - return new BlockAsDirWriterBuilder(blockNodeContext, blockRemover); + @NonNull final BlockNodeContext blockNodeContext, + @NonNull final BlockRemover blockRemover, + @NonNull final PathResolver pathResolver) { + return new BlockAsDirWriterBuilder(blockNodeContext, blockRemover, pathResolver); } /** @@ -79,6 +86,6 @@ public BlockAsDirWriterBuilder folderPermissions( */ @NonNull public BlockWriter> build() throws IOException { - return new BlockAsDirWriter(blockNodeContext, blockRemover, folderPermissions); + return new BlockAsDirWriter(blockNodeContext, blockRemover, pathResolver, folderPermissions); } } diff --git a/server/src/main/java/com/hedera/block/server/persistence/storage/write/BlockAsFileWriter.java b/server/src/main/java/com/hedera/block/server/persistence/storage/write/BlockAsFileWriter.java index 881253f6..37cd7da0 100644 --- a/server/src/main/java/com/hedera/block/server/persistence/storage/write/BlockAsFileWriter.java +++ b/server/src/main/java/com/hedera/block/server/persistence/storage/write/BlockAsFileWriter.java @@ -17,6 +17,7 @@ package com.hedera.block.server.persistence.storage.write; import com.hedera.block.server.config.BlockNodeContext; +import com.hedera.block.server.persistence.storage.path.PathResolver; import com.hedera.block.server.persistence.storage.remove.BlockRemover; import com.hedera.hapi.block.stream.BlockItem; import edu.umd.cs.findbugs.annotations.NonNull; @@ -28,8 +29,11 @@ * TODO: add documentation */ class BlockAsFileWriter extends AbstractBlockWriter> { - BlockAsFileWriter(@NonNull final BlockNodeContext blockNodeContext, @NonNull final BlockRemover blockRemover) { - super(blockNodeContext.metricsService(), blockRemover); + BlockAsFileWriter( + @NonNull final BlockNodeContext blockNodeContext, + @NonNull final BlockRemover blockRemover, + @NonNull final PathResolver pathResolver) { + super(blockNodeContext.metricsService(), blockRemover, pathResolver); } @Override diff --git a/server/src/main/java/com/hedera/block/server/persistence/storage/write/BlockAsFileWriterBuilder.java b/server/src/main/java/com/hedera/block/server/persistence/storage/write/BlockAsFileWriterBuilder.java index 50a5ecb6..4b14033e 100644 --- a/server/src/main/java/com/hedera/block/server/persistence/storage/write/BlockAsFileWriterBuilder.java +++ b/server/src/main/java/com/hedera/block/server/persistence/storage/write/BlockAsFileWriterBuilder.java @@ -17,6 +17,7 @@ package com.hedera.block.server.persistence.storage.write; import com.hedera.block.server.config.BlockNodeContext; +import com.hedera.block.server.persistence.storage.path.PathResolver; import com.hedera.block.server.persistence.storage.remove.BlockRemover; import com.hedera.hapi.block.stream.BlockItem; import edu.umd.cs.findbugs.annotations.NonNull; @@ -29,19 +30,25 @@ public final class BlockAsFileWriterBuilder { private final BlockNodeContext blockNodeContext; private final BlockRemover blockRemover; + private final PathResolver pathResolver; private BlockAsFileWriterBuilder( - @NonNull final BlockNodeContext blockNodeContext, @NonNull final BlockRemover blockRemover) { + @NonNull final BlockNodeContext blockNodeContext, + @NonNull final BlockRemover blockRemover, + @NonNull final PathResolver pathResolver) { this.blockNodeContext = Objects.requireNonNull(blockNodeContext); this.blockRemover = Objects.requireNonNull(blockRemover); + this.pathResolver = Objects.requireNonNull(pathResolver); } public static BlockAsFileWriterBuilder newBuilder( - @NonNull final BlockNodeContext blockNodeContext, @NonNull final BlockRemover blockRemover) { - return new BlockAsFileWriterBuilder(blockNodeContext, blockRemover); + @NonNull final BlockNodeContext blockNodeContext, + @NonNull final BlockRemover blockRemover, + @NonNull final PathResolver pathResolver) { + return new BlockAsFileWriterBuilder(blockNodeContext, blockRemover, pathResolver); } public BlockWriter> build() { - return new BlockAsFileWriter(blockNodeContext, blockRemover); + return new BlockAsFileWriter(blockNodeContext, blockRemover, pathResolver); } } diff --git a/server/src/main/java/com/hedera/block/server/persistence/storage/write/NoOpBlockWriter.java b/server/src/main/java/com/hedera/block/server/persistence/storage/write/NoOpBlockWriter.java index c965a486..c33ec355 100644 --- a/server/src/main/java/com/hedera/block/server/persistence/storage/write/NoOpBlockWriter.java +++ b/server/src/main/java/com/hedera/block/server/persistence/storage/write/NoOpBlockWriter.java @@ -19,6 +19,7 @@ import static java.lang.System.Logger.Level.INFO; import com.hedera.block.server.config.BlockNodeContext; +import com.hedera.block.server.persistence.storage.path.PathResolver; import com.hedera.block.server.persistence.storage.remove.BlockRemover; import com.hedera.hapi.block.stream.BlockItem; import edu.umd.cs.findbugs.annotations.NonNull; @@ -36,9 +37,13 @@ public class NoOpBlockWriter extends AbstractBlockWriter> { * Creates a new NoOpBlockWriter instance for testing and troubleshooting only. * * @param blockNodeContext the block node context + * @param pathResolver used internally */ - public NoOpBlockWriter(@NonNull final BlockNodeContext blockNodeContext, @NonNull final BlockRemover blockRemover) { - super(blockNodeContext.metricsService(), blockRemover); + public NoOpBlockWriter( + @NonNull final BlockNodeContext blockNodeContext, + @NonNull final BlockRemover blockRemover, + @NonNull final PathResolver pathResolver) { + super(blockNodeContext.metricsService(), blockRemover, pathResolver); System.getLogger(getClass().getName()).log(INFO, "Using " + getClass().getSimpleName()); } diff --git a/server/src/main/java/module-info.java b/server/src/main/java/module-info.java index 64246786..d00c922e 100644 --- a/server/src/main/java/module-info.java +++ b/server/src/main/java/module-info.java @@ -6,6 +6,7 @@ exports com.hedera.block.server.consumer; exports com.hedera.block.server.exception; exports com.hedera.block.server.persistence.storage; + exports com.hedera.block.server.persistence.storage.path; exports com.hedera.block.server.persistence.storage.write; exports com.hedera.block.server.persistence.storage.read; exports com.hedera.block.server.persistence.storage.remove; diff --git a/server/src/main/resources/app.properties b/server/src/main/resources/app.properties index 2d033a88..f66a24bc 100644 --- a/server/src/main/resources/app.properties +++ b/server/src/main/resources/app.properties @@ -11,4 +11,4 @@ prometheus.endpointPortNumber=9999 #Persistence Storage Config #persistence.storage.rootPath= -#persistence.storage.type=BLOCK_AS_FILE +persistence.storage.type=BLOCK_AS_DIR \ No newline at end of file diff --git a/server/src/test/java/com/hedera/block/server/pbj/PbjBlockStreamServiceIntegrationTest.java b/server/src/test/java/com/hedera/block/server/pbj/PbjBlockStreamServiceIntegrationTest.java index adf1b094..69b76375 100644 --- a/server/src/test/java/com/hedera/block/server/pbj/PbjBlockStreamServiceIntegrationTest.java +++ b/server/src/test/java/com/hedera/block/server/pbj/PbjBlockStreamServiceIntegrationTest.java @@ -20,7 +20,6 @@ import static com.hedera.block.server.producer.Util.getFakeHash; import static com.hedera.block.server.util.PersistTestUtils.generateBlockItems; import static java.lang.System.Logger; -import static java.lang.System.Logger.Level.INFO; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doCallRealMethod; @@ -38,6 +37,7 @@ import com.hedera.block.server.notifier.Notifier; import com.hedera.block.server.notifier.NotifierImpl; import com.hedera.block.server.persistence.StreamPersistenceHandlerImpl; +import com.hedera.block.server.persistence.storage.path.PathResolver; import com.hedera.block.server.persistence.storage.read.BlockReader; import com.hedera.block.server.persistence.storage.remove.BlockRemover; import com.hedera.block.server.persistence.storage.write.BlockAsDirWriterBuilder; @@ -67,7 +67,6 @@ import edu.umd.cs.findbugs.annotations.NonNull; import io.helidon.webserver.WebServer; import java.io.IOException; -import java.nio.file.Files; import java.nio.file.Path; import java.security.NoSuchAlgorithmException; import java.util.HashMap; @@ -81,6 +80,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.api.io.TempDir; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; @@ -132,23 +132,22 @@ public class PbjBlockStreamServiceIntegrationTest { private BlockReader blockReader; @Mock - private BlockRemover blockRemover; + private BlockRemover blockRemoverMock; - private static final String TEMP_DIR = "block-node-unit-test-dir"; + @Mock + private PathResolver pathResolverMock; + @TempDir private Path testPath; + private BlockNodeContext blockNodeContext; private static final int testTimeout = 2000; @BeforeEach public void setUp() throws IOException { - testPath = Files.createTempDirectory(TEMP_DIR); - LOGGER.log(INFO, "Created temp directory: " + testPath.toString()); - Map properties = new HashMap<>(); properties.put("persistence.storage.rootPath", testPath.toString()); - blockNodeContext = TestConfigUtil.getTestBlockNodeContext(properties); } @@ -299,7 +298,7 @@ public void testFullProducerConsumerHappyPath() throws IOException { int numberOfBlocks = 100; final BlockWriter> blockWriter = BlockAsDirWriterBuilder.newBuilder( - blockNodeContext, blockRemover) + blockNodeContext, blockRemoverMock, pathResolverMock) .build(); final PbjBlockStreamServiceProxy pbjBlockStreamServiceProxy = buildBlockStreamService(blockWriter); @@ -493,7 +492,7 @@ public void testMediatorExceptionHandlingWhenPersistenceFailure() throws IOExcep // Use a spy to make sure the write() method throws an IOException final BlockWriter> blockWriter = - spy(BlockAsDirWriterBuilder.newBuilder(blockNodeContext, blockRemover) + spy(BlockAsDirWriterBuilder.newBuilder(blockNodeContext, blockRemoverMock, pathResolverMock) .build()); doThrow(IOException.class).when(blockWriter).write(blockItems); diff --git a/server/src/test/java/com/hedera/block/server/persistence/PersistenceInjectionModuleTest.java b/server/src/test/java/com/hedera/block/server/persistence/PersistenceInjectionModuleTest.java index 8cfdb481..94fa21f0 100644 --- a/server/src/test/java/com/hedera/block/server/persistence/PersistenceInjectionModuleTest.java +++ b/server/src/test/java/com/hedera/block/server/persistence/PersistenceInjectionModuleTest.java @@ -30,6 +30,7 @@ import com.hedera.block.server.notifier.Notifier; import com.hedera.block.server.persistence.storage.PersistenceStorageConfig; import com.hedera.block.server.persistence.storage.StorageType; +import com.hedera.block.server.persistence.storage.path.NoOpPathResolver; import com.hedera.block.server.persistence.storage.read.BlockReader; import com.hedera.block.server.persistence.storage.remove.NoOpRemover; import com.hedera.block.server.persistence.storage.write.BlockWriter; @@ -80,7 +81,7 @@ void setup() throws IOException { void testProvidesBlockWriter() { BlockWriter> blockWriter = - PersistenceInjectionModule.providesBlockWriter(blockNodeContext, new NoOpRemover()); + PersistenceInjectionModule.providesBlockWriter(blockNodeContext, new NoOpRemover(), new NoOpPathResolver()); assertNotNull(blockWriter); } @@ -104,7 +105,7 @@ void testProvidesBlockWriter_IOException() { // Expect a RuntimeException due to the IOException assertThatRuntimeException() .isThrownBy(() -> { - PersistenceInjectionModule.providesBlockWriter(blockNodeContext, new NoOpRemover()); + PersistenceInjectionModule.providesBlockWriter(blockNodeContext, new NoOpRemover(), new NoOpPathResolver()); }) .withCauseInstanceOf(IOException.class) .withMessage("Failed to create BlockWriter"); diff --git a/server/src/test/java/com/hedera/block/server/persistence/storage/read/BlockAsDirReaderTest.java b/server/src/test/java/com/hedera/block/server/persistence/storage/read/BlockAsDirReaderTest.java index 5b48d29f..67ea6d22 100644 --- a/server/src/test/java/com/hedera/block/server/persistence/storage/read/BlockAsDirReaderTest.java +++ b/server/src/test/java/com/hedera/block/server/persistence/storage/read/BlockAsDirReaderTest.java @@ -27,6 +27,7 @@ import com.hedera.block.server.config.BlockNodeContext; import com.hedera.block.server.persistence.storage.PersistenceStorageConfig; +import com.hedera.block.server.persistence.storage.path.PathResolver; import com.hedera.block.server.persistence.storage.remove.BlockRemover; import com.hedera.block.server.persistence.storage.write.BlockAsDirWriterBuilder; import com.hedera.block.server.persistence.storage.write.BlockWriter; @@ -78,7 +79,7 @@ public void testReadPermsRepairSucceeded() throws IOException, ParseException { final List blockItems = generateBlockItems(1); final BlockWriter> blockWriter = BlockAsDirWriterBuilder.newBuilder( - blockNodeContext, mock(BlockRemover.class)) + blockNodeContext, mock(BlockRemover.class), mock(PathResolver.class)) .build(); for (BlockItem blockItem : blockItems) { blockWriter.write(List.of(blockItem)); @@ -100,7 +101,7 @@ public void testRemoveBlockReadPermsRepairFailed() throws IOException, ParseExce final List blockItems = generateBlockItems(1); final BlockWriter> blockWriter = BlockAsDirWriterBuilder.newBuilder( - blockNodeContext, mock(BlockRemover.class)) + blockNodeContext, mock(BlockRemover.class), mock(PathResolver.class)) .build(); blockWriter.write(blockItems); @@ -121,7 +122,7 @@ public void testRemoveBlockItemReadPerms() throws IOException { final List blockItems = generateBlockItems(1); final BlockWriter> blockWriter = BlockAsDirWriterBuilder.newBuilder( - blockNodeContext, mock(BlockRemover.class)) + blockNodeContext, mock(BlockRemover.class), mock(PathResolver.class)) .build(); blockWriter.write(blockItems); @@ -153,7 +154,7 @@ public void testRepairReadPermsFails() throws IOException, ParseException { final List blockItems = generateBlockItems(1); final BlockWriter> blockWriter = BlockAsDirWriterBuilder.newBuilder( - blockNodeContext, mock(BlockRemover.class)) + blockNodeContext, mock(BlockRemover.class), mock(PathResolver.class)) .build(); blockWriter.write(blockItems); @@ -190,7 +191,7 @@ public void testParseExceptionHandling() throws IOException, ParseException { final List blockItems = generateBlockItems(1); final BlockWriter> blockWriter = BlockAsDirWriterBuilder.newBuilder( - blockNodeContext, mock(BlockRemover.class)) + blockNodeContext, mock(BlockRemover.class), mock(PathResolver.class)) .build(); blockWriter.write(blockItems); diff --git a/server/src/test/java/com/hedera/block/server/persistence/storage/remove/BlockAsDirRemoverTest.java b/server/src/test/java/com/hedera/block/server/persistence/storage/remove/BlockAsDirRemoverTest.java index 0de6822f..208f6841 100644 --- a/server/src/test/java/com/hedera/block/server/persistence/storage/remove/BlockAsDirRemoverTest.java +++ b/server/src/test/java/com/hedera/block/server/persistence/storage/remove/BlockAsDirRemoverTest.java @@ -22,6 +22,7 @@ import com.hedera.block.server.config.BlockNodeContext; import com.hedera.block.server.persistence.storage.PersistenceStorageConfig; +import com.hedera.block.server.persistence.storage.path.PathResolver; import com.hedera.block.server.persistence.storage.read.BlockAsDirReaderBuilder; import com.hedera.block.server.persistence.storage.read.BlockReader; import com.hedera.block.server.persistence.storage.write.BlockAsDirWriterBuilder; @@ -60,7 +61,7 @@ public void testRemoveNonExistentBlock() throws IOException, ParseException { final List blockItems = PersistTestUtils.generateBlockItems(1); final BlockWriter> blockWriter = BlockAsDirWriterBuilder.newBuilder( - blockNodeContext, mock(BlockRemover.class)) + blockNodeContext, mock(BlockRemover.class), mock(PathResolver.class)) .build(); for (final BlockItem blockItem : blockItems) { blockWriter.write(List.of(blockItem)); diff --git a/server/src/test/java/com/hedera/block/server/persistence/storage/write/BlockAsDirWriterTest.java b/server/src/test/java/com/hedera/block/server/persistence/storage/write/BlockAsDirWriterTest.java index f39bb312..3b76e468 100644 --- a/server/src/test/java/com/hedera/block/server/persistence/storage/write/BlockAsDirWriterTest.java +++ b/server/src/test/java/com/hedera/block/server/persistence/storage/write/BlockAsDirWriterTest.java @@ -36,6 +36,7 @@ import com.hedera.block.server.config.BlockNodeContext; import com.hedera.block.server.persistence.storage.PersistenceStorageConfig; +import com.hedera.block.server.persistence.storage.path.PathResolver; import com.hedera.block.server.persistence.storage.read.BlockAsDirReaderBuilder; import com.hedera.block.server.persistence.storage.read.BlockReader; import com.hedera.block.server.persistence.storage.remove.BlockAsDirRemover; @@ -91,7 +92,7 @@ public void testWriterAndReaderHappyPath() throws IOException, ParseException { final List blockItems = generateBlockItems(1); final BlockWriter> blockWriter = BlockAsDirWriterBuilder.newBuilder( - blockNodeContext, mock(BlockRemover.class)) + blockNodeContext, mock(BlockRemover.class), mock(PathResolver.class)) .folderPermissions(DEFAULT_TEST_FOLDER_PERMISSIONS) .build(); for (int i = 0; i < 10; i++) { @@ -142,7 +143,7 @@ public void testRemoveBlockWritePerms() throws IOException, ParseException { final List blockItems = generateBlockItems(1); final BlockWriter> blockWriter = BlockAsDirWriterBuilder.newBuilder( - blockNodeContext, mock(BlockRemover.class)) + blockNodeContext, mock(BlockRemover.class), mock(PathResolver.class)) .build(); // Change the permissions on the block node root directory @@ -193,7 +194,7 @@ public void testUnrecoverableIOExceptionOnWrite() throws IOException { // Use a spy to simulate an IOException when the first block item is written final BlockWriter> blockWriter = - spy(BlockAsDirWriterBuilder.newBuilder(blockNodeContext, blockRemover) + spy(BlockAsDirWriterBuilder.newBuilder(blockNodeContext, blockRemover, mock(PathResolver.class)) .build()); doThrow(IOException.class).when(blockWriter).write(blockItems); assertThrows(IOException.class, () -> blockWriter.write(blockItems)); @@ -204,7 +205,7 @@ public void testRemoveRootDirReadPerm() throws IOException, ParseException { final List blockItems = generateBlockItems(1); final BlockWriter> blockWriter = BlockAsDirWriterBuilder.newBuilder( - blockNodeContext, mock(BlockRemover.class)) + blockNodeContext, mock(BlockRemover.class), mock(PathResolver.class)) .build(); // Write the first block item to create the block @@ -319,7 +320,7 @@ public TestBlockAsDirWriter( final FileAttribute> filePerms, final BlockNodeContext blockNodeContext) throws IOException { - super(blockNodeContext, blockRemover, filePerms); + super(blockNodeContext, blockRemover, mock(PathResolver.class), filePerms); } @Override