@VisibleForTesting
  int loadRecordsCount(final long storageSizeBytes) throws IOException {
    if (storageSizeBytes == 0) {
      return 0;
    }
    final long fullPagesOccupied = storageSizeBytes / pageSize;
    if (fullPagesOccupied == 0) {
      final long fullRecordsOnHeaderPage = (storageSizeBytes - HEADER_SIZE) / RECORD_SIZE_IN_BYTES;
      final long recordExcess = (storageSizeBytes - HEADER_SIZE) % RECORD_SIZE_IN_BYTES;
      if (recordExcess > 0) {
        throw new IOException(
          this.storage + " is corrupted: " +
          "(" + storageSizeBytes + "b on a header page) = (" + fullRecordsOnHeaderPage + " whole records)" +
          " + (" + recordExcess + "b excess)" +
          " -> storage is likely truncated, or was created with pageSize != current(" + pageSize + "b)"
        );
      }

      return (int)fullRecordsOnHeaderPage;
    }
    else {
      final long lastPageOccupiedBytes = storageSizeBytes % pageSize;

      final long fullRecordsOnLastPage = lastPageOccupiedBytes / RECORD_SIZE_IN_BYTES;
      final long recordExcess = lastPageOccupiedBytes % RECORD_SIZE_IN_BYTES;
      if (recordExcess > 0) {
        throw new IOException(
          this.storage + " is corrupted: " +
          "(" + lastPageOccupiedBytes + "b on last page) = (" + fullRecordsOnLastPage + " whole records)" +
          " + (" + recordExcess + "b excess)" +
          " -> storage is likely truncated, or was created with pageSize != current(" + pageSize + "b)"
        );
      }

      return (int)(
        (pageSize - HEADER_SIZE) / RECORD_SIZE_IN_BYTES //header page has fewer records!
        + (fullPagesOccupied - 1) * recordsPerPage
        + fullRecordsOnLastPage);
    }
  }
@VisibleForTesting
  int loadRecordsCount(final long storageSizeBytes)