class AbstractKeyValueStore extends LifecycleAdapter {

    protected final <Value> Value lookup( Key key, Reader<Value> reader ) throws IOException
    {
        ValueLookup<Value> lookup = new ValueLookup<>( reader );
        long retriesLeft = MAX_LOOKUP_RETRY_COUNT;
        while ( retriesLeft > 0 )
        {
            ProgressiveState<Key> originalState = this.state;
            try
            {
                return lookup.value( !originalState.lookup( key, lookup ) );
            }
            catch ( FileIsNotMappedException e )
            {
                // if the state has changed we think the exception is caused by a rotation event. In this
                // case we simply retry the lookup on the rotated state. Otherwise we rethrow.
                if ( originalState == this.state )
                {
                    throw e;
                }
            }
            retriesLeft--;
        }
        throw new IOException( String.format( "Failed to lookup `%s` in key value store, after %d retries", key, MAX_LOOKUP_RETRY_COUNT ) );
    }

    public  AbstractKeyValueStore( FileSystemAbstraction fs, PageCache pages, DatabaseLayout databaseLayout, RotationMonitor monitor, Logger logger,
            RotationTimerFactory timerFactory, VersionContextSupplier versionContextSupplier, int keySize,
            int valueSize, HeaderField<?>... headerFields );

}