Skip to content

Commit

Permalink
minor refactoring and additional file reading method overload for eas…
Browse files Browse the repository at this point in the history
…ier usage and spotlessApply

Signed-off-by: Atanas Atanasov <[email protected]>
  • Loading branch information
ata-nas committed Oct 23, 2024
1 parent 63c6b40 commit db7654d
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 58 deletions.
120 changes: 73 additions & 47 deletions common/src/main/java/com/hedera/block/common/utils/FileUtilities.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package com.hedera.block.common.utils;

import edu.umd.cs.findbugs.annotations.NonNull;
import java.io.File;
import java.io.IOException;
import java.lang.System.Logger;
import java.nio.file.Files;
Expand All @@ -28,7 +29,9 @@
import java.util.Set;
import java.util.zip.GZIPInputStream;

/** A utility class that deals with logic related to dealing with files. */
/**
* A utility class that deals with logic related to dealing with files.
*/
public final class FileUtilities {
private static final Logger LOGGER = System.getLogger(FileUtilities.class.getName());

Expand Down Expand Up @@ -62,21 +65,22 @@ public final class FileUtilities {
PosixFilePermission.OTHERS_EXECUTE));

/**
* Log message template used when a path is not created because a file
* or folder already exists at the requested path.
* Log message template used when a path is not created because a file or folder already exists
* at the requested path.
*/
private static final String PRE_EXISTING_FOLDER_MESSAGE =
"Requested %s [%s] not created because %s already exists at %s";

/**
* Create a new path (folder or file) if it does not exist.
* Any folders or files created will use default permissions.
* Create a new path (folder or file) if it does not exist. Any folders or files created will
* use default permissions.
*
* @param toCreate valid, non-null instance of {@link Path} to be created
* @param logLevel valid, non-null instance of {@link System.Logger.Level} to use
* @param toCreate valid, non-null instance of {@link Path} to be created
* @param logLevel valid, non-null instance of {@link System.Logger.Level} to use
* @param semanticPathName valid, non-blank {@link String} used for logging that represents the
* desired path semantically
* @param createDir {@link Boolean} value if we should create a directory or a file
* desired path semantically
* @param createDir {@link Boolean} value if we should create a directory or a file
*
* @throws IOException if the path cannot be created
*/
public static void createPathIfNotExists(
Expand All @@ -97,16 +101,15 @@ public static void createPathIfNotExists(
/**
* Create a new path (folder or file) if it does not exist.
*
* @param toCreate The path to be created.
* @param logLevel The logging level to use when logging this event.
* @param filePermissions Permissions to use when creating a new file.
* @param toCreate The path to be created.
* @param logLevel The logging level to use when logging this event.
* @param filePermissions Permissions to use when creating a new file.
* @param folderPermissions Permissions to use when creating a new folder.
* @param semanticPathName A name to represent the path in a logging
* statement.
* @param createDir A flag indicating we should create a directory
* (true) or a file (false)
* @throws IOException if the path cannot be created due to a filesystem
* error.
* @param semanticPathName A name to represent the path in a logging statement.
* @param createDir A flag indicating we should create a directory (true) or a file
* (false)
*
* @throws IOException if the path cannot be created due to a filesystem error.
*/
public static void createPathIfNotExists(
@NonNull final Path toCreate,
Expand Down Expand Up @@ -143,20 +146,22 @@ public static void createPathIfNotExists(
/**
* Read a GZIP file and return the content as a byte array.
* <p>
* This method is _unsafe_ because it reads the entire file content into
* a single byte array, which can cause memory issues, and may fail if the
* file contains a large amount of data.
* This method is _unsafe_ because it reads the entire file content into a single byte array,
* which can cause memory issues, and may fail if the file contains a large amount of data.
*
* @param filePath Path to the GZIP file.
*
* @return byte array containing the _uncompressed_ content of the GZIP file.
* @throws IOException if unable to read the file.
* @throws OutOfMemoryError if a byte array large enough to contain the
* file contents cannot be allocated (either because it exceeds MAX_INT
* bytes or exceeds available heap memory).
*
* @throws IOException if unable to read the file.
* @throws OutOfMemoryError if a byte array large enough to contain the file contents cannot be
* allocated (either because it exceeds MAX_INT bytes or exceeds
* available heap memory).
*/
public static byte[] readGzipFileUnsafe(@NonNull final Path filePath) throws IOException {
Objects.requireNonNull(filePath);
try (final var gzipInputStream = new GZIPInputStream(Files.newInputStream(filePath))) {
try (final GZIPInputStream gzipInputStream =
new GZIPInputStream(Files.newInputStream(filePath))) {
return gzipInputStream.readAllBytes();
}
}
Expand All @@ -166,17 +171,38 @@ public static byte[] readGzipFileUnsafe(@NonNull final Path filePath) throws IOE
* <p>
* This method uses default extensions for gzip and block files.
* <p>
* This method is _unsafe_ because it reads the entire file content into
* a single byte array, which can cause memory issues, and may fail if the
* file contains a large amount of data.
* This method is _unsafe_ because it reads the entire file content into a single byte array,
* which can cause memory issues, and may fail if the file contains a large amount of data.
*
* @param file to read bytes from
*
* @return byte array of the content of the file or null if the file extension is not supported
*
* @throws IOException if unable to read the file.
* @throws OutOfMemoryError if a byte array large enough to contain the file contents cannot be
* allocated (either because it exceeds MAX_INT bytes or exceeds
* available heap memory).
*/
public static byte[] readFileBytesUnsafe(@NonNull final File file) throws IOException {
return readFileBytesUnsafe(file.toPath());

Check warning on line 187 in common/src/main/java/com/hedera/block/common/utils/FileUtilities.java

View check run for this annotation

Codecov / codecov/patch

common/src/main/java/com/hedera/block/common/utils/FileUtilities.java#L187

Added line #L187 was not covered by tests
}

/**
* Read a file and return the content as a byte array.
* <p>
* This method uses default extensions for gzip and block files.
* <p>
* This method is _unsafe_ because it reads the entire file content into a single byte array,
* which can cause memory issues, and may fail if the file contains a large amount of data.
*
* @param filePath Path to the file
* @return byte array of the content of the file or null if the file extension is not
* supported
* @throws IOException if unable to read the file.
* @throws OutOfMemoryError if a byte array large enough to contain the
* file contents cannot be allocated (either because it exceeds MAX_INT
* bytes or exceeds available heap memory).
*
* @return byte array of the content of the file or null if the file extension is not supported
*
* @throws IOException if unable to read the file.
* @throws OutOfMemoryError if a byte array large enough to contain the file contents cannot be
* allocated (either because it exceeds MAX_INT bytes or exceeds
* available heap memory).
*/
public static byte[] readFileBytesUnsafe(@NonNull final Path filePath) throws IOException {
return readFileBytesUnsafe(filePath, ".blk", ".gz");
Expand All @@ -185,20 +211,20 @@ public static byte[] readFileBytesUnsafe(@NonNull final Path filePath) throws IO
/**
* Read a file and return the content as a byte array.
* <p>
* This method is _unsafe_ because it reads the entire file content into
* a single byte array, which can cause memory issues, and may fail if the
* file contains a large amount of data.
* This method is _unsafe_ because it reads the entire file content into a single byte array,
* which can cause memory issues, and may fail if the file contains a large amount of data.
*
* @param filePath Path to the file to read.
* @param filePath Path to the file to read.
* @param blockFileExtension A file extension for block files.
* @param gzipFileExtension A file extension for gzip files.
* @return A byte array with the full contents of the file, or null if the
* file extension requested does not match at least one of the
* extensions provided (GZip or Block).
* @throws IOException if unable to read the file.
* @throws OutOfMemoryError if a byte array large enough to contain the
* file contents cannot be allocated (either because it exceeds MAX_INT
* bytes or exceeds available heap memory).
* @param gzipFileExtension A file extension for gzip files.
*
* @return A byte array with the full contents of the file, or null if the file extension
* requested does not match at least one of the extensions provided (GZip or Block).
*
* @throws IOException if unable to read the file.
* @throws OutOfMemoryError if a byte array large enough to contain the file contents cannot be
* allocated (either because it exceeds MAX_INT bytes or exceeds
* available heap memory).
*/
public static byte[] readFileBytesUnsafe(
@NonNull final Path filePath,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@

package com.hedera.block.simulator;

import static com.hedera.block.common.constants.StringsConstants.APPLICATION_PROPERTIES;
import static java.lang.System.Logger.Level.INFO;

import com.hedera.block.common.constants.StringsConstants;
import com.hedera.block.simulator.exception.BlockSimulatorParsingException;
import com.swirlds.config.api.Configuration;
import com.swirlds.config.api.ConfigurationBuilder;
Expand Down Expand Up @@ -58,9 +58,7 @@ public static void main(final String[] args)
ConfigurationBuilder.create()
.withSource(SystemEnvironmentConfigSource.getInstance())
.withSource(SystemPropertiesConfigSource.getInstance())
.withSource(
new ClasspathFileConfigSource(
Path.of(StringsConstants.APPLICATION_PROPERTIES)))
.withSource(new ClasspathFileConfigSource(Path.of(APPLICATION_PROPERTIES)))
.autoDiscoverExtensions();

final Configuration configuration = configurationBuilder.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@

package com.hedera.block.simulator.generator;

import static com.hedera.block.common.utils.FileUtilities.readFileBytesUnsafe;
import static java.lang.System.Logger.Level.DEBUG;
import static java.lang.System.Logger.Level.ERROR;
import static java.lang.System.Logger.Level.INFO;

import com.hedera.block.common.utils.FileUtilities;
import com.hedera.block.simulator.config.data.BlockGeneratorConfig;
import com.hedera.block.simulator.config.types.GenerationMode;
import com.hedera.hapi.block.stream.Block;
Expand Down Expand Up @@ -126,8 +126,7 @@ private void loadBlocks() throws IOException, ParseException {
.toList();

for (final Path pathBlockItem : sortedBlockItems) {
final byte[] blockItemBytes =
FileUtilities.readFileBytesUnsafe(pathBlockItem);
final byte[] blockItemBytes = readFileBytesUnsafe(pathBlockItem);
// if null means the file is not a block item and we can skip the file.
if (blockItemBytes == null) {
continue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@

package com.hedera.block.simulator.generator;

import static com.hedera.block.common.utils.FileUtilities.readFileBytesUnsafe;
import static java.lang.System.Logger.Level.DEBUG;
import static java.lang.System.Logger.Level.ERROR;
import static java.lang.System.Logger.Level.INFO;

import com.hedera.block.common.utils.FileUtilities;
import com.hedera.block.simulator.config.data.BlockGeneratorConfig;
import com.hedera.block.simulator.config.types.GenerationMode;
import com.hedera.hapi.block.stream.Block;
Expand Down Expand Up @@ -109,7 +109,7 @@ private void loadBlocks() throws IOException, ParseException {

for (final Path blockPath : sortedBlockFiles) {

final byte[] blockBytes = FileUtilities.readFileBytesUnsafe(blockPath);
final byte[] blockBytes = readFileBytesUnsafe(blockPath);
// skip if block is null, usually due to SO files like .DS_STORE
if (blockBytes == null) {
continue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@

package com.hedera.block.simulator.generator;

import static com.hedera.block.common.utils.FileUtilities.readFileBytesUnsafe;
import static java.lang.System.Logger.Level.INFO;

import com.hedera.block.common.utils.FileUtilities;
import com.hedera.block.simulator.config.data.BlockGeneratorConfig;
import com.hedera.block.simulator.config.types.GenerationMode;
import com.hedera.block.simulator.exception.BlockSimulatorParsingException;
Expand Down Expand Up @@ -86,7 +86,7 @@ public Block getNextBlock() throws IOException, BlockSimulatorParsingException {
}

try {
final byte[] blockBytes = FileUtilities.readFileBytesUnsafe(blockFile.toPath());
final byte[] blockBytes = readFileBytesUnsafe(blockFile);

LOGGER.log(INFO, "Loading block: " + blockFile.getName());

Expand Down

0 comments on commit db7654d

Please sign in to comment.