class BaseHighLimitRecordFormat extends BaseOneByteHeaderRecordFormat<RECORD> {

    @Override
    public void read( RECORD record, PageCursor primaryCursor, RecordLoad mode, int recordSize )
            throws IOException
    {
        int primaryStartOffset = primaryCursor.getOffset();
        byte headerByte = primaryCursor.getByte();
        boolean inUse = isInUse( headerByte );
        boolean doubleRecordUnit = has( headerByte, HEADER_BIT_RECORD_UNIT );
        record.setUseFixedReferences( false );
        if ( doubleRecordUnit )
        {
            boolean firstRecordUnit = has( headerByte, HEADER_BIT_FIRST_RECORD_UNIT );
            if ( !firstRecordUnit )
            {
                // This is a record unit and not even the first one, so you cannot go here directly and read it,
                // it may only be read as part of reading the primary unit.
                record.clear();
                // Return and try again
                primaryCursor.setCursorException(
                        "Expected record to be the first unit in the chain, but record header says it's not" );
                return;
            }

            // This is a record that is split into multiple record units. We need a bit more clever
            // data structures here. For the time being this means instantiating one object,
            // but the trade-off is a great reduction in complexity.
            long secondaryId = Reference.decode( primaryCursor );
            long pageId = pageIdForRecord( secondaryId, primaryCursor.getCurrentPageSize(), recordSize );
            int offset = offsetForId( secondaryId, primaryCursor.getCurrentPageSize(), recordSize );
            PageCursor secondaryCursor = primaryCursor.openLinkedCursor( pageId );
            if ( (!secondaryCursor.next()) | offset < 0 )
            {
                // We must have made an inconsistent read of the secondary record unit reference.
                // No point in trying to read this.
                record.clear();
                primaryCursor.setCursorException( illegalSecondaryReferenceMessage( pageId ) );
                return;
            }
            secondaryCursor.setOffset( offset + HEADER_BYTE);
            int primarySize = recordSize - (primaryCursor.getOffset() - primaryStartOffset);
            // We *could* sanity check the secondary record header byte here, but we won't. If it is wrong, then we most
            // likely did an inconsistent read, in which case we'll just retry. Otherwise, if the header byte is wrong,
            // then there is little we can do about it here, since we are not allowed to throw exceptions.

            int secondarySize = recordSize - HEADER_BYTE;
            PageCursor composite = CompositePageCursor.compose(
                    primaryCursor, primarySize, secondaryCursor, secondarySize );
            doReadInternal( record, composite, recordSize, headerByte, inUse );
            record.setSecondaryUnitId( secondaryId );
            record.setRequiresSecondaryUnit(true); // Force override since we have secondaryUnitId
        }
        else
        {
            record.setUseFixedReferences( isUseFixedReferences( headerByte ) );
            doReadInternal( record, primaryCursor, recordSize, headerByte, inUse );
        }

        // Set cursor offset to next record to prepare next read in case of scanning.
        primaryCursor.setOffset( primaryStartOffset + recordSize );
    }

    protected  BaseHighLimitRecordFormat( Function<StoreHeader,Integer> recordSize, int recordHeaderSize, int maxIdBits );

}