Class FileSystemStorage

java.lang.Object
com.privatechain.storage.fs.FileSystemStorage
All Implemented Interfaces:
BlockchainStorage

public final class FileSystemStorage extends Object implements BlockchainStorage
File system backed BlockchainStorage implementation that stores each block as a separate JSON file.

This implementation has zero native library dependencies, making it suitable for environments where the native LevelDB or RocksDB JNI binaries are unavailable (FR-STOR-05). It relies entirely on the JDK's Files API.

File layout

 <dataDirectory>/
 ├── block-0000000000.json   (genesis block)
 ├── block-0000000001.json
 ├── block-0000000002.json
 └── ...
 

Each file is named block-%010d.json (10-digit zero-padded decimal index) so that lexicographic file-system ordering matches block order, making loadAll() a simple directory listing without extra sorting on any platform.

Write atomicity

Blocks are written atomically using the write-to-temp-then-rename strategy: the JSON is first written to a .tmp file, then atomically moved over the target via StandardCopyOption.ATOMIC_MOVE. On POSIX systems this maps to rename(2), which is atomic — readers never see a partial block file.

Stream resource management

Files.list(Path) returns a Stream backed by an open directory-handle. Every call site that opens a directory stream does so inside its own try-with-resources block so the handle is closed immediately after use, regardless of exceptions. No helper method returns an open stream to the caller — this is the pattern recommended by the JDK Javadoc and required to silence static-analysis warnings.

Thread safety

Concurrent reads use the read lock; all writes acquire the exclusive write lock, satisfying FR-STOR-06.

Usage


 BlockchainNode node = BlockchainConfig.builder()
     .storage(new FileSystemStorage("/var/blockchain/chain"))
     .build();
 
Since:
1.0.0
See Also:
  • Constructor Details

    • FileSystemStorage

      public FileSystemStorage(String dataDirectory)
      Constructs a FileSystemStorage rooted at the given directory path.

      The directory is created (including all missing parents) if it does not already exist.

      Parameters:
      dataDirectory - path to the directory where block files will be stored
      Throws:
      NullPointerException - if dataDirectory is null
      IllegalArgumentException - if dataDirectory is blank
      BlockValidationException - if the directory cannot be created
    • FileSystemStorage

      public FileSystemStorage(Path dataDirectory)
      Constructs a FileSystemStorage rooted at the given Path.
      Parameters:
      dataDirectory - path to the directory where block files will be stored
      Throws:
      NullPointerException - if dataDirectory is null
      BlockValidationException - if the directory cannot be created
  • Method Details

    • saveBlock

      public void saveBlock(Block block)
      Persists a block as a JSON file using an atomic write-then-rename strategy.
      1. Serialize the block to JSON bytes via BlockSerializer.
      2. Write bytes to block-XXXXXXXXXX.json.tmp.
      3. Atomically rename the temp file to block-XXXXXXXXXX.json.
      Specified by:
      saveBlock in interface BlockchainStorage
      Parameters:
      block - the block to persist (non-null)
      Throws:
      NullPointerException - if block is null
      BlockValidationException - if the write or rename fails
    • loadBlock

      public Block loadBlock(int index)
      Retrieves a block by loading and deserializing its JSON file.
      Specified by:
      loadBlock in interface BlockchainStorage
      Parameters:
      index - block index (≥ 0)
      Returns:
      the deserialized Block
      Throws:
      NoSuchElementException - if no file exists for index
      BlockValidationException - if deserialization or hash verification fails
    • loadBlockByHash

      public Optional<Block> loadBlockByHash(String hash)
      Searches for a block by its SHA-256 hash.

      Opens a directory stream inside a try-with-resources block to guarantee the underlying directory handle is closed after the search, whether or not a match is found.

      Specified by:
      loadBlockByHash in interface BlockchainStorage
      Parameters:
      hash - hex-encoded block hash (non-null)
      Returns:
      an Optional containing the matching block, or empty if absent
      Throws:
      NullPointerException - if hash is null
    • loadAll

      public List<Block> loadAll()
      Returns all stored blocks in ascending index order.

      Opens a directory stream inside a try-with-resources block to guarantee the underlying directory handle is closed after enumeration.

      The returned list is a defensive copy; mutations do not affect storage.

      Specified by:
      loadAll in interface BlockchainStorage
      Returns:
      non-null, ordered list (maybe empty)
    • exists

      public boolean exists(String hash)
      Returns true if a block with the given hash is stored.
      Specified by:
      exists in interface BlockchainStorage
      Parameters:
      hash - hex-encoded block hash (non-null)
      Returns:
      true if a matching block exists
      Throws:
      NullPointerException - if hash is null
    • chainHeight

      public int chainHeight()
      Returns the number of block JSON files present in the data directory.

      Opens a directory stream inside a try-with-resources block to guarantee the underlying directory handle is closed after counting.

      Specified by:
      chainHeight in interface BlockchainStorage
      Returns:
      block count (≥ 0)
    • deleteAll

      public void deleteAll()
      Deletes all block JSON files from the data directory.

      Warning: irreversible. Only block-*.json files are removed; other files in the directory are untouched.

      Opens a directory stream inside a try-with-resources block to guarantee the underlying directory handle is closed after deletion.

      Specified by:
      deleteAll in interface BlockchainStorage
    • toString

      public String toString()
      Returns a human-readable description of this storage instance.
      Overrides:
      toString in class Object
      Returns:
      string representation