class TransactionLogBloomCacher {

  void cacheLogsBloomForBlockHeader(
      final BlockHeader blockHeader,
      final Optional<BlockHeader> commonAncestorBlockHeader,
      final Optional<File> reusedCacheFile) {
    try {
      if (cachingStatus.cachingCount.incrementAndGet() != 1) {
        return;
      }
      final long blockNumber = blockHeader.getNumber();
      LOG.debug("Caching logs bloom for block {}.", "0x" + Long.toHexString(blockNumber));
      final File cacheFile = reusedCacheFile.orElse(calculateCacheFileName(blockNumber, cacheDir));
      if (cacheFile.exists()) {
        try {
          final Optional<Long> ancestorBlockNumber =
              commonAncestorBlockHeader.map(ProcessableBlockHeader::getNumber);
          if (ancestorBlockNumber.isPresent()) {
            // walk through the blocks from the common ancestor to the received block in order to
            // reload the cache in case of reorg
            for (long number = ancestorBlockNumber.get() + 1;
                number < blockHeader.getNumber();
                number++) {
              Optional<BlockHeader> ancestorBlockHeader = blockchain.getBlockHeader(number);
              if (ancestorBlockHeader.isPresent()) {
                cacheSingleBlock(ancestorBlockHeader.get(), cacheFile);
              }
            }
          }
          cacheSingleBlock(blockHeader, cacheFile);
        } catch (final InvalidCacheException e) {
          populateLatestSegment(blockNumber);
        }
      } else {
        populateLatestSegment(blockNumber);
      }
    } catch (final IOException e) {
      LOG.error("Unhandled caching exception.", e);
    } finally {
      cachingStatus.cachingCount.decrementAndGet();
    }
  }

  public  TransactionLogBloomCacher(
      final Blockchain blockchain, final Path cacheDir, final EthScheduler scheduler);

}