@Override
  public <Out> Out readRecord(final int recordId,
                              final @NotNull ByteBufferReader<Out> reader,
                              final @Nullable IntRef redirectToIdRef) throws IOException {
    checkRecordIdExists(recordId);
    int currentRecordId = recordId;
    for (int i = 0; i < MAX_REDIRECTS; i++) {
      final long recordOffset = idToOffset(currentRecordId);
      try (final PageUnsafe page = (PageUnsafe)pagedStorage.pageByOffset(recordOffset, /*forWrite: */ false)) {
        final int offsetOnPage = pagedStorage.toOffsetInPage(recordOffset);
        page.lockPageForRead();
        try {
          final ByteBuffer buffer = page.rawPageBuffer();
          final RecordLayout recordLayout = RecordLayout.recordLayout(buffer, offsetOnPage);
          final byte recordType = recordLayout.recordType();

          if (redirectToIdRef != null) {
            redirectToIdRef.set(currentRecordId); //will be overwritten if we follow .redirectedToId chain
          }

          if (recordType == RecordLayout.RECORD_TYPE_ACTUAL) {
            final int recordPayloadLength = recordLayout.length(buffer, offsetOnPage);
            final ByteBuffer slice = buffer.slice(offsetOnPage + recordLayout.headerSize(), recordPayloadLength)
              .asReadOnlyBuffer()
              .order(buffer.order());
            return reader.read(slice);
          }

          if (recordType == RecordLayout.RECORD_TYPE_MOVED) {
            final int redirectToId = recordLayout.redirectToId(buffer, offsetOnPage);
            checkRedirectToId(recordId, currentRecordId, redirectToId);
            currentRecordId = redirectToId;
          }
          else {
            throw new AssertionError("RecordType(" + recordType + ") should not appear in the chain: " +
                                     "it is either not implemented yet, or all wrong");
          }
        }
        finally {
          page.unlockPageForRead();
        }
      }
    }
    throw new IOException("record[" + recordId + "].redirectTo chain is too long (>=" + MAX_REDIRECTS + "): circular reference?");
  }
@Override
  public <Out> Out readRecord(final int recordId,
                              final @NotNull ByteBufferReader<Out> reader,
                              final @Nullable IntRef redirectToIdRef)