    @Override
    public RecordCheck<PropertyRecord, PropertyConsistencyReport> decoratePropertyChecker(
            final RecordCheck<PropertyRecord, PropertyConsistencyReport> checker )
    {
        if ( owners == null && dynamics == null )
        {
            return checker;
        }
        return ( record, engine, records ) ->
        {
            if ( record.inUse() )
            {
                if ( owners != null && Record.NO_PREVIOUS_PROPERTY.is( record.getPrevProp() ) )
                { // this record is first in a chain
                    PropertyOwner.UnknownOwner owner = new PropertyOwner.UnknownOwner();
                    engine.comparativeCheck( owner, ORPHAN_CHECKER );
                    if ( null == owners.putIfAbsent( record.getId(), owner ) )
                    {
                        owner.markInCustody();
                    }
                }
                if ( dynamics != null )
                {
                    for ( PropertyBlock block : record )
                    {
                        RecordType type = recordType( block.forceGetType() );
                        if ( type != null )
                        {
                            ConcurrentMap<Long, DynamicOwner> dynamicOwners = dynamics.get( type );
                            if ( dynamicOwners != null )
                            {
                                long id = block.getSingleValueLong();
                                DynamicOwner.Property owner = new DynamicOwner.Property( type, record );
                                DynamicOwner prev = dynamicOwners.put( id, owner );
                                if ( prev != null )
                                {
                                    engine.comparativeCheck( prev.record( records ), owner );
                                }
                            }
                        }
                    }
                }
            }
            checker.check( record, engine, records );
        };
    }

    @Override
    public RecordCheck<PropertyRecord, PropertyConsistencyReport> decoratePropertyChecker(
            final RecordCheck<PropertyRecord, PropertyConsistencyReport> checker )
    {
        if ( owners == null && dynamics == null )
        {
            return checker;
        }
        return new RecordCheck<PropertyRecord, PropertyConsistencyReport>()
        {
            @Override
            public void check( PropertyRecord record,
                               CheckerEngine<PropertyRecord, PropertyConsistencyReport> engine,
                               RecordAccess records )
            {
                if ( record.inUse() )
                {
                    if ( owners != null && Record.NO_PREVIOUS_PROPERTY.is( record.getPrevProp() ) )
                    { // this record is first in a chain
                        PropertyOwner.UnknownOwner owner = new PropertyOwner.UnknownOwner();
                        engine.comparativeCheck( owner, ORPHAN_CHECKER );
                        if ( null == owners.putIfAbsent( record.getId(), owner ) )
                        {
                            owner.markInCustody();
                        }
                    }
                    if ( dynamics != null )
                    {
                        for ( PropertyBlock block : record )
                        {
                            RecordType type = recordType( block.forceGetType() );
                            if ( type != null )
                            {
                                ConcurrentMap<Long, DynamicOwner> dynamicOwners = dynamics.get( type );
                                if ( dynamicOwners != null )
                                {
                                    long id = block.getSingleValueLong();
                                    DynamicOwner.Property owner = new DynamicOwner.Property( type, record );
                                    DynamicOwner prev = dynamicOwners.put( id, owner );
                                    if ( prev != null )
                                    {
                                        engine.comparativeCheck( prev.record( records ), owner );
                                    }
                                }
                            }
                        }
                    }
                }
                checker.check( record, engine, records );
            }
        };
    }

Replace Anonymous With Lambda org.neo4j.consistency.checking.full.OwnerCheck.decoratePropertyChecker.new RecordCheck<PropertyRecord,PropertyConsistencyReport> with (record, engine, records) -> {if(record.inUse()){if(owners != null && Record.NO_PREVIOUS_PROPERTY.is(record.getPrevProp())){PropertyOwner.UnknownOwner owner=new PropertyOwner.UnknownOwner(); in method public decoratePropertyChecker(checker RecordCheck<PropertyRecord,PropertyConsistencyReport>) : RecordCheck<PropertyRecord,PropertyConsistencyReport> from class org.neo4j.consistency.checking.full.OwnerCheck


    RecordCheck<DynamicRecord, DynamicConsistencyReport> decorateDynamicChecker(
            final RecordType type, final RecordCheck<DynamicRecord, DynamicConsistencyReport> checker )
    {
        final ConcurrentMap<Long, DynamicOwner> dynamicOwners = dynamicOwners( type );
        if ( dynamicOwners == null )
        {
            return checker;
        }
        return ( record, engine, records ) ->
        {
            if ( record.inUse() )
            {
                DynamicOwner.Unknown owner = new DynamicOwner.Unknown();
                engine.comparativeCheck( owner, DynamicOwner.ORPHAN_CHECK );
                if ( null == dynamicOwners.putIfAbsent( record.getId(), owner ) )
                {
                    owner.markInCustody();
                }
                if ( !Record.NO_NEXT_BLOCK.is( record.getNextBlock() ) )
                {
                    DynamicOwner.Dynamic nextOwner = new DynamicOwner.Dynamic( type, record );
                    DynamicOwner prevOwner = dynamicOwners.put( record.getNextBlock(), nextOwner );
                    if ( prevOwner != null )
                    {
                        engine.comparativeCheck( prevOwner.record( records ), nextOwner );
                    }
                }
            }
            checker.check( record, engine, records );
        };
    }

    RecordCheck<DynamicRecord, DynamicConsistencyReport> decorateDynamicChecker(
            final RecordType type, final RecordCheck<DynamicRecord, DynamicConsistencyReport> checker )
    {
        final ConcurrentMap<Long, DynamicOwner> dynamicOwners = dynamicOwners( type );
        if ( dynamicOwners == null )
        {
            return checker;
        }
        return new RecordCheck<DynamicRecord, DynamicConsistencyReport>()
        {
            @Override
            public void check( DynamicRecord record,
                               CheckerEngine<DynamicRecord, DynamicConsistencyReport> engine,
                               RecordAccess records )
            {
                if ( record.inUse() )
                {
                    DynamicOwner.Unknown owner = new DynamicOwner.Unknown();
                    engine.comparativeCheck( owner, DynamicOwner.ORPHAN_CHECK );
                    if ( null == dynamicOwners.putIfAbsent( record.getId(), owner ) )
                    {
                        owner.markInCustody();
                    }
                    if ( !Record.NO_NEXT_BLOCK.is( record.getNextBlock() ) )
                    {
                        DynamicOwner.Dynamic nextOwner = new DynamicOwner.Dynamic( type, record );
                        DynamicOwner prevOwner = dynamicOwners.put( record.getNextBlock(), nextOwner );
                        if ( prevOwner != null )
                        {
                            engine.comparativeCheck( prevOwner.record( records ), nextOwner );
                        }
                    }
                }
                checker.check( record, engine, records );
            }
        };
    }

Replace Anonymous With Lambda org.neo4j.consistency.checking.full.OwnerCheck.decorateDynamicChecker.new RecordCheck<DynamicRecord,DynamicConsistencyReport> with (record, engine, records) -> {if(record.inUse()){DynamicOwner.Unknown owner=new DynamicOwner.Unknown(); in method package decorateDynamicChecker(type RecordType, checker RecordCheck<DynamicRecord,DynamicConsistencyReport>) : RecordCheck<DynamicRecord,DynamicConsistencyReport> from class org.neo4j.consistency.checking.full.OwnerCheck


    private ConsistencySummaryStatistics check( DirectStoreAccess stores ) throws ConsistencyCheckIncompleteException
    {
        Config config = config();
        FullCheck checker = new FullCheck( config, ProgressMonitorFactory.NONE, fixture.getAccessStatistics(),
                defaultConsistencyCheckThreadsNumber() );
        return checker.execute( stores, FormattedLog.toOutputStream( System.out ),
                ( report, method, message ) ->
                {
                    Set<String> types = allReports.get( report );
                    assert types != null;
                    types.remove( method );
                } );
    }

    private ConsistencySummaryStatistics check( DirectStoreAccess stores ) throws ConsistencyCheckIncompleteException
    {
        Config config = config();
        FullCheck checker = new FullCheck( config, ProgressMonitorFactory.NONE, fixture.getAccessStatistics(),
                defaultConsistencyCheckThreadsNumber() );
        return checker.execute( stores, FormattedLog.toOutputStream( System.out ),
                new ConsistencyReporter.Monitor()
                {
                    @Override
                    public void reported( Class<?> report, String method, String message )
                    {
                        Set<String> types = allReports.get( report );
                        assert types != null;
                        types.remove( method );
                    }
                } );
    }

Replace Anonymous With Lambda org.neo4j.consistency.checking.full.FullCheckIntegrationTest.check.execute.new ConsistencyReporter.Monitor with (report, method, message) -> {Set<String> types=allReports.get(report); in method private check(stores DirectStoreAccess) : ConsistencySummaryStatistics from class org.neo4j.consistency.checking.full.FullCheckIntegrationTest


    @Test
    public void shouldDoProcessingInitializationInOrder() throws Throwable
    {
        // GIVEN
        final Race race = new Race();
        final AtomicInteger coordination = new AtomicInteger( -1 );
        final AtomicInteger expected = new AtomicInteger();
        final int threads = 30;
        @SuppressWarnings( "unchecked" )
        final RecordCheckWorker<Integer>[] workers = new RecordCheckWorker[threads];
        final RecordProcessor<Integer> processor = new RecordProcessor.Adapter<Integer>()
        {
            @Override
            public void process( Integer record )
            {
                // We're testing init() here, not really process()
            }

            @Override
            public void init( int id )
            {
                assertEquals( id, expected.getAndAdd( 1 ) );
            }
        };
        for ( int id = 0; id < threads; id++ )
        {
            ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<>( 10 );
            race.addContestant( workers[id] = new RecordCheckWorker<>( id, coordination, queue, processor ) );
        }
        race.addContestant( () ->
        {
            try
            {
                long end = currentTimeMillis() + SECONDS.toMillis( 100 );
                while ( currentTimeMillis() < end && expected.get() < threads )
                {
                    parkNanos( MILLISECONDS.toNanos( 10 ) );
                }
                assertEquals( threads, expected.get() );
            }
            finally
            {
                for ( RecordCheckWorker<Integer> worker : workers )
                {
                    worker.done();
                }
            }
        } );

        // WHEN
        race.go();
    }

    @Test
    public void shouldDoProcessingInitializationInOrder() throws Throwable
    {
        // GIVEN
        final Race race = new Race();
        final AtomicInteger coordination = new AtomicInteger( -1 );
        final AtomicInteger expected = new AtomicInteger();
        final int threads = 30;
        @SuppressWarnings( "unchecked" )
        final RecordCheckWorker<Integer>[] workers = new RecordCheckWorker[threads];
        final RecordProcessor<Integer> processor = new RecordProcessor.Adapter<Integer>()
        {
            @Override
            public void process( Integer record )
            {
                // We're testing init() here, not really process()
            }

            @Override
            public void init( int id )
            {
                assertEquals( id, expected.getAndAdd( 1 ) );
            }
        };
        for ( int id = 0; id < threads; id++ )
        {
            ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<>( 10 );
            race.addContestant( workers[id] = new RecordCheckWorker<>( id, coordination, queue, processor ) );
        }
        race.addContestant( new Runnable()
        {
            @Override
            public void run()
            {
                try
                {
                    long end = currentTimeMillis() + SECONDS.toMillis( 100 );
                    while ( currentTimeMillis() < end && expected.get() < threads )
                    {
                        parkNanos( MILLISECONDS.toNanos( 10 ) );
                    }
                    assertEquals( threads, expected.get() );
                }
                finally
                {
                    for ( RecordCheckWorker<Integer> worker : workers )
                    {
                        worker.done();
                    }
                }
            }
        } );

        // WHEN
        race.go();
    }

Replace Anonymous With Lambda org.neo4j.consistency.checking.full.RecordCheckWorkerTest.shouldDoProcessingInitializationInOrder.addContestant.new Runnable with () -> {trylong end=currentTimeMillis() + SECONDS.toMillis(100); in method public shouldDoProcessingInitializationInOrder() : void from class org.neo4j.consistency.checking.full.RecordCheckWorkerTest


        @Override
        public <REFERRED extends AbstractBaseRecord> void comparativeCheck(
                final RecordReference<REFERRED> other,
                final ComparativeRecordChecker<RECORD, ? super REFERRED, REPORT> checker )
        {
            deferredTasks.add( () ->
            {
                PendingReferenceCheck mock = mock( PendingReferenceCheck.class );
                DeferredReferenceCheck check = new DeferredReferenceCheck( Engine.this, checker );
                doAnswer( check ).when( mock ).checkReference( any( AbstractBaseRecord.class ),
                                                               any( RecordAccess.class ) );
                doAnswer( check ).when( mock ).checkDiffReference( any( AbstractBaseRecord.class ),
                                                                   any( AbstractBaseRecord.class ),
                                                                   any( RecordAccess.class ) );
                other.dispatch( mock );
            } );
        }

        @Override
        public <REFERRED extends AbstractBaseRecord> void comparativeCheck(
                final RecordReference<REFERRED> other,
                final ComparativeRecordChecker<RECORD, ? super REFERRED, REPORT> checker )
        {
            deferredTasks.add( new Runnable()
            {
                @Override
                @SuppressWarnings( "unchecked" )
                public void run()
                {
                    PendingReferenceCheck mock = mock( PendingReferenceCheck.class );
                    DeferredReferenceCheck check = new DeferredReferenceCheck( Engine.this, checker );
                    doAnswer( check ).when( mock ).checkReference( any( AbstractBaseRecord.class ),
                                                                   any( RecordAccess.class ) );
                    doAnswer( check ).when( mock ).checkDiffReference( any( AbstractBaseRecord.class ),
                                                                       any( AbstractBaseRecord.class ),
                                                                       any( RecordAccess.class ) );
                    other.dispatch( mock );
                }
            } );
        }

Replace Anonymous With Lambda org.neo4j.consistency.store.RecordAccessStub.Engine.comparativeCheck.add.new Runnable with () -> {PendingReferenceCheck mock=mock(PendingReferenceCheck.class); in method public comparativeCheck(other RecordReference<REFERRED>, checker ComparativeRecordChecker<RECORD,? super REFERRED,REPORT>) : void from class org.neo4j.consistency.store.RecordAccessStub.Engine


    private Iterable<Node> nodeIterator( final Node start, final Iterable<Relationship> relationships )
    {
        return () -> new Iterator<Node>()
        {
            Node current = start;
            int index;
            Iterator<Relationship> relationshipIterator = relationships.iterator();

            public boolean hasNext()
            {
                return index <= path.length;
            }

            public Node next()
            {
                if ( current == null )
                {
                    throw new NoSuchElementException();
                }
                Node next = null;
                if ( index < path.length )
                {
                    if ( !relationshipIterator.hasNext() )
                    {
                        throw new IllegalStateException( String.format( "Number of relationships: %d does not" +
                                              " match with path length: %d.", index, path.length ) );
                    }
                    next = relationshipIterator.next().getOtherNode( current );
                }
                index += 1;
                try
                {
                    return current;
                }
                finally
                {
                    current = next;
                }
            }

            public void remove()
            {
                throw new UnsupportedOperationException();
            }
        };
    }

    private Iterable<Node> nodeIterator( final Node start, final Iterable<Relationship> relationships )
    {
        return new Iterable<Node>()
        {
            public Iterator<Node> iterator()
            {
                return new Iterator<Node>()
                {
                    Node current = start;
                    int index;
                    Iterator<Relationship> relationshipIterator = relationships.iterator();

                    public boolean hasNext()
                    {
                        return index <= path.length;
                    }

                    public Node next()
                    {
                        if ( current == null )
                        {
                            throw new NoSuchElementException();
                        }
                        Node next = null;
                        if ( index < path.length )
                        {
                            if ( !relationshipIterator.hasNext() )
                            {
                                throw new IllegalStateException( String.format( "Number of relationships: %d does not" +
                                                      " match with path length: %d.", index, path.length ) );
                            }
                            next = relationshipIterator.next().getOtherNode( current );
                        }
                        index += 1;
                        try
                        {
                            return current;
                        }
                        finally
                        {
                            current = next;
                        }
                    }

                    public void remove()
                    {
                        throw new UnsupportedOperationException();
                    }
                };
            }
        };
    }

Replace Anonymous With Lambda org.neo4j.graphalgo.impl.util.PathImpl.nodeIterator.new Iterable<Node> with () -> new Iterator<Node>(){ in method private nodeIterator(start Node, relationships Iterable<Relationship>) : Iterable<Node> from class org.neo4j.graphalgo.impl.util.PathImpl


    /**
     * Same network as above, but with direction BOTH and weights in different
     * directions are given by a map.
     */
    @Test
    public void testWeightAndDirection()
    {
        graph.makeEdgeChain( "a,b" );
        graph.makeEdgeChain( "b,c" );
        graph.makeEdgeChain( "c,d" );
        graph.makeEdgeChain( "c,a" );
        final Map<String,Double> costs = new HashMap<String,Double>();
        costs.put( "a,b", 1.0 );
        costs.put( "b,c", 1.0 );
        costs.put( "c,d", 1.0 );
        costs.put( "c,b", 0.1 );
        costs.put( "c,a", 0.1 );
        EigenvectorCentrality eigenvectorCentrality = getEigenvectorCentrality(
            Direction.BOTH, ( relationship, direction ) ->
                {
                    String start = graph
                        .getNodeId( relationship.getStartNode() );
                    String end = graph.getNodeId( relationship.getEndNode() );
                    if ( direction == Direction.INCOMING )
                    {
                        // swap
                        String tmp = end;
                        end = start;
                        start = tmp;
                    }
                    Double value = costs.get( start + "," + end );
                    if ( value == null )
                    {
                        return 0.0;
                    }
                    return value;
                }, graph.getAllNodes(), graph.getAllEdges(), 0.01 );

        assertApproximateCentrality( eigenvectorCentrality, "a", 0.0851, 0.02 );
        assertApproximateCentrality( eigenvectorCentrality, "b", 0.244, 0.02 );
        assertApproximateCentrality( eigenvectorCentrality, "c", 0.456, 0.02 );
        assertApproximateCentrality( eigenvectorCentrality, "d", 0.852, 0.02 );
    }

    /**
     * Same network as above, but with direction BOTH and weights in different
     * directions are given by a map.
     */
    @Test
    public void testWeightAndDirection()
    {
        graph.makeEdgeChain( "a,b" );
        graph.makeEdgeChain( "b,c" );
        graph.makeEdgeChain( "c,d" );
        graph.makeEdgeChain( "c,a" );
        final Map<String,Double> costs = new HashMap<String,Double>();
        costs.put( "a,b", 1.0 );
        costs.put( "b,c", 1.0 );
        costs.put( "c,d", 1.0 );
        costs.put( "c,b", 0.1 );
        costs.put( "c,a", 0.1 );
        EigenvectorCentrality eigenvectorCentrality = getEigenvectorCentrality(
            Direction.BOTH, new CostEvaluator<Double>()
            {
                public Double getCost( Relationship relationship,
                            Direction direction )
                {
                    String start = graph
                        .getNodeId( relationship.getStartNode() );
                    String end = graph.getNodeId( relationship.getEndNode() );
                    if ( direction == Direction.INCOMING )
                    {
                        // swap
                        String tmp = end;
                        end = start;
                        start = tmp;
                    }
                    Double value = costs.get( start + "," + end );
                    if ( value == null )
                    {
                        return 0.0;
                    }
                    return value;
                }
            }, graph.getAllNodes(), graph.getAllEdges(), 0.01 );

        assertApproximateCentrality( eigenvectorCentrality, "a", 0.0851, 0.02 );
        assertApproximateCentrality( eigenvectorCentrality, "b", 0.244, 0.02 );
        assertApproximateCentrality( eigenvectorCentrality, "c", 0.456, 0.02 );
        assertApproximateCentrality( eigenvectorCentrality, "d", 0.852, 0.02 );
    }

Replace Anonymous With Lambda org.neo4j.graphalgo.centrality.EigenvectorCentralityTest.testWeightAndDirection.eigenvectorCentrality.getEigenvectorCentrality.new CostEvaluator<Double> with (relationship, direction) -> {String start=graph.getNodeId(relationship.getStartNode()); in method public testWeightAndDirection() : void from class org.neo4j.graphalgo.centrality.EigenvectorCentralityTest


    @Override
    public Iterable<Relationship> relationships()
    {
        return () -> new PrefetchingIterator<Relationship>()
        {
            final Iterator<Relationship> startRelationships = start.relationships().iterator();
            boolean lastReturned;

            @Override
            protected Relationship fetchNextOrNull()
            {
                if ( startRelationships.hasNext() )
                {
                    return startRelationships.next();
                }
                if ( !lastReturned )
                {
                    lastReturned = true;
                    return lastRelationship;
                }
                return null;
            }
        };
    }

    @Override
    public Iterable<Relationship> relationships()
    {
        return new Iterable<Relationship>()
        {
            @Override
            public Iterator<Relationship> iterator()
            {
                return new PrefetchingIterator<Relationship>()
                {
                    final Iterator<Relationship> startRelationships = start.relationships().iterator();
                    boolean lastReturned;

                    @Override
                    protected Relationship fetchNextOrNull()
                    {
                        if ( startRelationships.hasNext() )
                        {
                            return startRelationships.next();
                        }
                        if ( !lastReturned )
                        {
                            lastReturned = true;
                            return lastRelationship;
                        }
                        return null;
                    }
                };
            }
        };
    }

Replace Anonymous With Lambda org.neo4j.graphdb.impl.ExtendedPath.relationships.new Iterable<Relationship> with () -> new PrefetchingIterator<Relationship>(){ in method public relationships() : Iterable<Relationship> from class org.neo4j.graphdb.impl.ExtendedPath


    @Override
    public Iterable<Relationship> reverseRelationships()
    {
        return () -> new PrefetchingIterator<Relationship>()
        {
            final Iterator<Relationship> startRelationships = start.reverseRelationships().iterator();
            boolean endReturned;

            @Override
            protected Relationship fetchNextOrNull()
            {
                if ( !endReturned )
                {
                    endReturned = true;
                    return lastRelationship;
                }
                return startRelationships.hasNext() ? startRelationships.next() : null;
            }
        };
    }

    @Override
    public Iterable<Relationship> reverseRelationships()
    {
        return new Iterable<Relationship>()
        {
            @Override
            public Iterator<Relationship> iterator()
            {
                return new PrefetchingIterator<Relationship>()
                {
                    final Iterator<Relationship> startRelationships = start.reverseRelationships().iterator();
                    boolean endReturned;

                    @Override
                    protected Relationship fetchNextOrNull()
                    {
                        if ( !endReturned )
                        {
                            endReturned = true;
                            return lastRelationship;
                        }
                        return startRelationships.hasNext() ? startRelationships.next() : null;
                    }
                };
            }
        };
    }

Replace Anonymous With Lambda org.neo4j.graphdb.impl.ExtendedPath.reverseRelationships.new Iterable<Relationship> with () -> new PrefetchingIterator<Relationship>(){ in method public reverseRelationships() : Iterable<Relationship> from class org.neo4j.graphdb.impl.ExtendedPath


    @Override
    public Iterable<Node> nodes()
    {
        return () -> new PrefetchingIterator<Node>()
        {
            final Iterator<Node> startNodes = start.nodes().iterator();
            boolean lastReturned;

            @Override
            protected Node fetchNextOrNull()
            {
                if ( startNodes.hasNext() )
                {
                    return startNodes.next();
                }
                if ( !lastReturned )
                {
                    lastReturned = true;
                    return endNode;
                }
                return null;
            }
        };
    }

    @Override
    public Iterable<Node> nodes()
    {
        return new Iterable<Node>()
        {
            @Override
            public Iterator<Node> iterator()
            {
                return new PrefetchingIterator<Node>()
                {
                    final Iterator<Node> startNodes = start.nodes().iterator();
                    boolean lastReturned;

                    @Override
                    protected Node fetchNextOrNull()
                    {
                        if ( startNodes.hasNext() )
                        {
                            return startNodes.next();
                        }
                        if ( !lastReturned )
                        {
                            lastReturned = true;
                            return endNode;
                        }
                        return null;
                    }
                };
            }
        };
    }

Replace Anonymous With Lambda org.neo4j.graphdb.impl.ExtendedPath.nodes.new Iterable<Node> with () -> new PrefetchingIterator<Node>(){ in method public nodes() : Iterable<Node> from class org.neo4j.graphdb.impl.ExtendedPath


    @Override
    public Iterable<Node> reverseNodes()
    {
        return () -> new PrefetchingIterator<Node>()
        {
            final Iterator<Node> startNodes = start.reverseNodes().iterator();
            boolean endReturned;

            @Override
            protected Node fetchNextOrNull()
            {
                if ( !endReturned )
                {
                    endReturned = true;
                    return endNode;
                }
                return startNodes.hasNext() ? startNodes.next() : null;
            }
        };
    }

    @Override
    public Iterable<Node> reverseNodes()
    {
        return new Iterable<Node>()
        {
            @Override
            public Iterator<Node> iterator()
            {
                return new PrefetchingIterator<Node>()
                {
                    final Iterator<Node> startNodes = start.reverseNodes().iterator();
                    boolean endReturned;

                    @Override
                    protected Node fetchNextOrNull()
                    {
                        if ( !endReturned )
                        {
                            endReturned = true;
                            return endNode;
                        }
                        return startNodes.hasNext() ? startNodes.next() : null;
                    }
                };
            }
        };
    }

Replace Anonymous With Lambda org.neo4j.graphdb.impl.ExtendedPath.reverseNodes.new Iterable<Node> with () -> new PrefetchingIterator<Node>(){ in method public reverseNodes() : Iterable<Node> from class org.neo4j.graphdb.impl.ExtendedPath


    private <K extends ThirdPartyFileSystem> ThirdPartyFileSystem adversarialProxy(
            final ThirdPartyFileSystem fileSystem,
            Class<K> clazz )
    {
        InvocationHandler handler = ( proxy, method, args ) ->
        {
            adversary.injectFailure( (Class<? extends Throwable>[]) method.getExceptionTypes() );
            return method.invoke( fileSystem, args );
        };
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        return (ThirdPartyFileSystem) Proxy.newProxyInstance( loader, new Class[] { clazz }, handler );
    }

    private <K extends ThirdPartyFileSystem> ThirdPartyFileSystem adversarialProxy(
            final ThirdPartyFileSystem fileSystem,
            Class<K> clazz )
    {
        InvocationHandler handler = new InvocationHandler()
        {
            @Override
            public Object invoke( Object proxy, Method method, Object[] args ) throws Throwable
            {
                adversary.injectFailure( (Class<? extends Throwable>[]) method.getExceptionTypes() );
                return method.invoke( fileSystem, args );
            }
        };
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        return (ThirdPartyFileSystem) Proxy.newProxyInstance( loader, new Class[] { clazz }, handler );
    }

Replace Anonymous With Lambda org.neo4j.adversaries.fs.AdversarialFileSystemAbstraction.adversarialProxy.handler.new InvocationHandler with (proxy, method, args) -> {adversary.injectFailure((Class<? extends Throwable>[])method.getExceptionTypes()); in method private adversarialProxy(fileSystem ThirdPartyFileSystem, clazz Class<K>) : ThirdPartyFileSystem from class org.neo4j.adversaries.fs.AdversarialFileSystemAbstraction


    private static <T> Iterable<T> filterExceptions( final Iterable<T> iterable )
    {
        return () -> new PrefetchingIterator<T>()
        {
            final Iterator<T> iterator = iterable.iterator();

            @Override
            protected T fetchNextOrNull()
            {
                while ( iterator.hasNext() )
                {
                    try
                    {
                        return iterator.next();
                    }
                    catch ( Throwable e )
                    {
                        if ( printServiceLoaderStackTraces )
                        {
                            e.printStackTrace();
                        }
                    }
                }
                return null;
            }
        };
    }

    private static <T> Iterable<T> filterExceptions( final Iterable<T> iterable )
    {
        return new Iterable<T>()
        {
            @Override
            public Iterator<T> iterator()
            {
                return new PrefetchingIterator<T>()
                {
                    final Iterator<T> iterator = iterable.iterator();

                    @Override
                    protected T fetchNextOrNull()
                    {
                        while ( iterator.hasNext() )
                        {
                            try
                            {
                                return iterator.next();
                            }
                            catch ( Throwable e )
                            {
                                if ( printServiceLoaderStackTraces )
                                {
                                    e.printStackTrace();
                                }
                            }
                        }
                        return null;
                    }
                };
            }
        };
    }

Replace Anonymous With Lambda org.neo4j.helpers.Service.filterExceptions.new Iterable<T> with () -> new PrefetchingIterator<T>(){ in method private filterExceptions(iterable Iterable<T>) : Iterable<T> from class org.neo4j.helpers.Service


    public void scheduleSamplingJob( final IndexSamplingJob samplingJob )
    {
        lock.lock();
        try
        {
            if ( stopped )
            {
                return;
            }

            long indexId = samplingJob.indexId();
            if ( executingJobs.contains( indexId ) )
            {
                return;
            }

            executingJobs.add( indexId );
            jobScheduler.schedule( JobScheduler.Groups.indexSampling, () ->
            {
                try
                {
                    samplingJob.run();
                }
                finally
                {
                    samplingJobCompleted( samplingJob );
                }
            } );
        }
        finally
        {
            lock.unlock();
        }
    }

    public void scheduleSamplingJob( final IndexSamplingJob samplingJob )
    {
        lock.lock();
        try
        {
            if ( stopped )
            {
                return;
            }

            long indexId = samplingJob.indexId();
            if ( executingJobs.contains( indexId ) )
            {
                return;
            }

            executingJobs.add( indexId );
            jobScheduler.schedule( JobScheduler.Groups.indexSampling, new Runnable()
            {
                @Override
                public void run()
                {
                    try
                    {
                        samplingJob.run();
                    }
                    finally
                    {
                        samplingJobCompleted( samplingJob );
                    }
                }
            } );
        }
        finally
        {
            lock.unlock();
        }
    }

Replace Anonymous With Lambda org.neo4j.kernel.impl.api.index.sampling.IndexSamplingJobTracker.scheduleSamplingJob.schedule.new Runnable with () -> {trysamplingJob.run(); in method public scheduleSamplingJob(samplingJob IndexSamplingJob) : void from class org.neo4j.kernel.impl.api.index.sampling.IndexSamplingJobTracker


    /**
     * Throws cause of store not being OK.
     */
    public void verifyStoreOk()
    {
        visitStore( store ->
        {
            store.checkStoreOk();
            return false;
        } );
    }

    /**
     * Throws cause of store not being OK.
     */
    public void verifyStoreOk()
    {
        visitStore( new Visitor<CommonAbstractStore,RuntimeException>()
        {
            @Override
            public boolean visit( CommonAbstractStore store )
            {
                store.checkStoreOk();
                return false;
            }
        } );
    }

Replace Anonymous With Lambda org.neo4j.kernel.impl.store.NeoStores.verifyStoreOk.visitStore.new Visitor<CommonAbstractStore,RuntimeException> with store -> {store.checkStoreOk(); in method public verifyStoreOk() : void from class org.neo4j.kernel.impl.store.NeoStores


    public void deleteIdGenerators()
    {
        visitStore( store ->
        {
            store.deleteIdGenerator();
            return false;
        } );
    }

    public void deleteIdGenerators()
    {
        visitStore( new Visitor<CommonAbstractStore,RuntimeException>()
        {
            @Override
            public boolean visit( CommonAbstractStore store ) throws RuntimeException
            {
                store.deleteIdGenerator();
                return false;
            }
        } );
    }

Replace Anonymous With Lambda org.neo4j.kernel.impl.store.NeoStores.deleteIdGenerators.visitStore.new Visitor<CommonAbstractStore,RuntimeException> with store -> {store.deleteIdGenerator(); in method public deleteIdGenerators() : void from class org.neo4j.kernel.impl.store.NeoStores


    private PrimitiveLongObjectMap<List<DuplicateCluster>> collectConflictingProperties( final PropertyStore store )
    {
        final PrimitiveLongObjectMap<List<DuplicateCluster>> duplicateClusters = Primitive.longObjectMap();

        long highId = store.getHighId();
        PropertyRecord head = store.newRecord();
        PropertyRecord tail = store.newRecord();
        for ( long headRecordId = 0; headRecordId < highId; ++headRecordId )
        {
            store.getRecord( headRecordId, head, FORCE );
            // Skip property propertyRecordIds that are not in use.
            // Skip property propertyRecordIds that are not at the start of a chain.
            if ( !head.inUse() || head.getPrevProp() != Record.NO_NEXT_PROPERTY.intValue() )
            {
                continue;
            }

            long propertyId = headRecordId;
            while ( propertyId != Record.NO_NEXT_PROPERTY.intValue() )
            {
                store.getRecord( propertyId, tail, NORMAL );

                Iterable<PropertyBlock> propertyBlocks = tail;
                scanForDuplicates( propertyId, propertyBlocks );

                propertyId = tail.getNextProp();
            }

            final long localHeadRecordId = headRecordId;
            localDuplicateClusters.visitEntries( ( key, duplicateCluster ) ->
            {
                List<DuplicateCluster> clusters = duplicateClusters.get( localHeadRecordId );
                if ( clusters == null )
                {
                    clusters = new ArrayList<>();
                    duplicateClusters.put( localHeadRecordId, clusters );
                }
                clusters.add( duplicateCluster );
                return false;
            } );

            seenPropertyKeys.clear();
            localDuplicateClusters.clear();
        }

        return duplicateClusters;
    }

    private PrimitiveLongObjectMap<List<DuplicateCluster>> collectConflictingProperties( final PropertyStore store )
    {
        final PrimitiveLongObjectMap<List<DuplicateCluster>> duplicateClusters = Primitive.longObjectMap();

        long highId = store.getHighId();
        PropertyRecord head = store.newRecord();
        PropertyRecord tail = store.newRecord();
        for ( long headRecordId = 0; headRecordId < highId; ++headRecordId )
        {
            store.getRecord( headRecordId, head, FORCE );
            // Skip property propertyRecordIds that are not in use.
            // Skip property propertyRecordIds that are not at the start of a chain.
            if ( !head.inUse() || head.getPrevProp() != Record.NO_NEXT_PROPERTY.intValue() )
            {
                continue;
            }

            long propertyId = headRecordId;
            while ( propertyId != Record.NO_NEXT_PROPERTY.intValue() )
            {
                store.getRecord( propertyId, tail, NORMAL );

                Iterable<PropertyBlock> propertyBlocks = tail;
                scanForDuplicates( propertyId, propertyBlocks );

                propertyId = tail.getNextProp();
            }

            final long localHeadRecordId = headRecordId;
            localDuplicateClusters.visitEntries( new PrimitiveIntObjectVisitor<DuplicateCluster, RuntimeException>()
            {
                @Override
                public boolean visited( int key, DuplicateCluster duplicateCluster )
                {
                    List<DuplicateCluster> clusters = duplicateClusters.get( localHeadRecordId );
                    if ( clusters == null )
                    {
                        clusters = new ArrayList<>();
                        duplicateClusters.put( localHeadRecordId, clusters );
                    }
                    clusters.add( duplicateCluster );
                    return false;
                }
            } );

            seenPropertyKeys.clear();
            localDuplicateClusters.clear();
        }

        return duplicateClusters;
    }

Replace Anonymous With Lambda org.neo4j.kernel.impl.storemigration.legacystore.v21.propertydeduplication.PropertyDeduplicator.collectConflictingProperties.visitEntries.new PrimitiveIntObjectVisitor<DuplicateCluster,RuntimeException> with (key, duplicateCluster) -> {List<DuplicateCluster> clusters=duplicateClusters.get(localHeadRecordId); in method private collectConflictingProperties(store PropertyStore) : PrimitiveLongObjectMap<List<DuplicateCluster>> from class org.neo4j.kernel.impl.storemigration.legacystore.v21.propertydeduplication.PropertyDeduplicator


    @Override
    public Iterable<Relationship> reverseRelationships()
    {
        return () -> new PrefetchingIterator<Relationship>()
        {
            private TraversalBranch branch = TraversalBranchImpl.this;

            @Override
            protected Relationship fetchNextOrNull()
            {
                try
                {
                    return branch != null ? branch.lastRelationship() : null;
                }
                finally
                {
                    branch = branch != null ? branch.parent() : null;
                }
            }
        };
    }

    @Override
    public Iterable<Relationship> reverseRelationships()
    {
        return new Iterable<Relationship>()
        {
            @Override
            public Iterator<Relationship> iterator()
            {
                return new PrefetchingIterator<Relationship>()
                {
                    private TraversalBranch branch = TraversalBranchImpl.this;

                    @Override
                    protected Relationship fetchNextOrNull()
                    {
                        try
                        {
                            return branch != null ? branch.lastRelationship() : null;
                        }
                        finally
                        {
                            branch = branch != null ? branch.parent() : null;
                        }
                    }
                };
            }
        };
    }

Replace Anonymous With Lambda org.neo4j.kernel.impl.traversal.TraversalBranchImpl.reverseRelationships.new Iterable<Relationship> with () -> new PrefetchingIterator<Relationship>(){ in method public reverseRelationships() : Iterable<Relationship> from class org.neo4j.kernel.impl.traversal.TraversalBranchImpl


    @Override
    public Iterable<Node> reverseNodes()
    {
        return () -> new PrefetchingIterator<Node>()
        {
            private TraversalBranch branch = TraversalBranchImpl.this;

            @Override
            protected Node fetchNextOrNull()
            {
                try
                {
                    return branch.length() >= 0 ? branch.endNode() : null;
                }
                finally
                {
                    branch = branch.parent();
                }
            }
        };
    }

    @Override
    public Iterable<Node> reverseNodes()
    {
        return new Iterable<Node>()
        {
            @Override
            public Iterator<Node> iterator()
            {
                return new PrefetchingIterator<Node>()
                {
                    private TraversalBranch branch = TraversalBranchImpl.this;

                    @Override
                    protected Node fetchNextOrNull()
                    {
                        try
                        {
                            return branch.length() >= 0 ? branch.endNode() : null;
                        }
                        finally
                        {
                            branch = branch.parent();
                        }
                    }
                };
            }
        };
    }

Replace Anonymous With Lambda org.neo4j.kernel.impl.traversal.TraversalBranchImpl.reverseNodes.new Iterable<Node> with () -> new PrefetchingIterator<Node>(){ in method public reverseNodes() : Iterable<Node> from class org.neo4j.kernel.impl.traversal.TraversalBranchImpl


    private Map<String, Object> getPropertyChain( long nextProp )
    {
        final Map<String, Object> map = new HashMap<>();
        propertyTraverser.getPropertyChain( nextProp, recordAccess.getPropertyRecords(), propBlock ->
        {
            String key = propertyKeyTokens.byId( propBlock.getKeyIndexId() ).name();
            DefinedProperty propertyData = propBlock.newPropertyData( propertyStore );
            Object value = propertyData.value() != null ? propertyData.value() :
                           propBlock.getType().getValue( propBlock, propertyStore );
            map.put( key, value );
        } );
        return map;
    }

    private Map<String, Object> getPropertyChain( long nextProp )
    {
        final Map<String, Object> map = new HashMap<>();
        propertyTraverser.getPropertyChain( nextProp, recordAccess.getPropertyRecords(), new Listener<PropertyBlock>()
        {
            @Override
            public void receive( PropertyBlock propBlock )
            {
                String key = propertyKeyTokens.byId( propBlock.getKeyIndexId() ).name();
                DefinedProperty propertyData = propBlock.newPropertyData( propertyStore );
                Object value = propertyData.value() != null ? propertyData.value() :
                               propBlock.getType().getValue( propBlock, propertyStore );
                map.put( key, value );
            }
        } );
        return map;
    }

Replace Anonymous With Lambda org.neo4j.unsafe.batchinsert.internal.BatchInserterImpl.getPropertyChain.getPropertyChain.new Listener<PropertyBlock> with propBlock -> {String key=propertyKeyTokens.byId(propBlock.getKeyIndexId()).name(); in method private getPropertyChain(nextProp long) : Map<String,Object> from class org.neo4j.unsafe.batchinsert.internal.BatchInserterImpl


    public InputIterable<InputRelationship> relationships( String subType, boolean deleteAfterUse )
    {
        return entities( () -> new InputRelationshipReader( channel( RELATIONSHIPS, subType, "r" ),
                channel( RELATIONSHIPS_HEADER, subType, "r" ), bufferSize,
                deleteAction( deleteAfterUse, RELATIONSHIPS, RELATIONSHIPS_HEADER, subType ),
                config.maxNumberOfProcessors() ) );
    }

    public InputIterable<InputRelationship> relationships( String subType, boolean deleteAfterUse )
    {
        return entities( new ThrowingSupplier<InputIterator<InputRelationship>, IOException>()
        {
            @Override
            public InputIterator<InputRelationship> get() throws IOException
            {
                return new InputRelationshipReader( channel( RELATIONSHIPS, subType, "r" ),
                        channel( RELATIONSHIPS_HEADER, subType, "r" ), bufferSize,
                        deleteAction( deleteAfterUse, RELATIONSHIPS, RELATIONSHIPS_HEADER, subType ),
                        config.maxNumberOfProcessors() );
            }
        } );
    }

Replace Anonymous With Lambda org.neo4j.unsafe.impl.batchimport.input.InputCache.relationships.entities.new ThrowingSupplier<InputIterator<InputRelationship>,IOException> with () -> new InputRelationshipReader(channel(RELATIONSHIPS,subType,"r"),channel(RELATIONSHIPS_HEADER,subType,"r"),bufferSize,deleteAction(deleteAfterUse,RELATIONSHIPS,RELATIONSHIPS_HEADER,subType),config.maxNumberOfProcessors()) in method public relationships(subType String, deleteAfterUse boolean) : InputIterable<InputRelationship> from class org.neo4j.unsafe.impl.batchimport.input.InputCache


    /**
     * @param stat statistics {@link Key}.
     * @param trueForAscending {@code true} for ordering by ascending, otherwise descending.
     * @return the steps ordered by the {@link Stat#asLong() long value representation} of the given
     * {@code stat} accompanied a factor by how it compares to the next value, where a value close to
     * {@code 1.0} signals them being close to equal, and a value of for example {@code 0.5} signals that
     * the value of the current step is half that of the next step.
     */
    public Iterable<Pair<Step<?>,Float>> stepsOrderedBy( final Key stat, final boolean trueForAscending )
    {
        final List<Step<?>> steps = new ArrayList<>( pipeline );
        Collections.sort( steps, ( o1, o2 ) ->
        {
            Long stat1 = o1.stats().stat( stat ).asLong();
            Long stat2 = o2.stats().stat( stat ).asLong();
            return trueForAscending
                    ? stat1.compareTo( stat2 )
                    : stat2.compareTo( stat1 );
        } );

        return () -> new PrefetchingIterator<Pair<Step<?>,Float>>()
        {
            private final Iterator<Step<?>> source = steps.iterator();
            private Step<?> next = source.hasNext() ? source.next() : null;

            @Override
            protected Pair<Step<?>,Float> fetchNextOrNull()
            {
                if ( next == null )
                {
                    return null;
                }

                Step<?> current = next;
                next = source.hasNext() ? source.next() : null;
                float factor = next != null
                        ? (float) stat( current, stat ) / (float) stat( next, stat )
                        : 1.0f;
                return Pair.of( current, factor );
            }

            private long stat( Step<?> step, Key stat12 )
            {
                return step.stats().stat( stat12 ).asLong();
            }
        };
    }

    /**
     * @param stat statistics {@link Key}.
     * @param trueForAscending {@code true} for ordering by ascending, otherwise descending.
     * @return the steps ordered by the {@link Stat#asLong() long value representation} of the given
     * {@code stat} accompanied a factor by how it compares to the next value, where a value close to
     * {@code 1.0} signals them being close to equal, and a value of for example {@code 0.5} signals that
     * the value of the current step is half that of the next step.
     */
    public Iterable<Pair<Step<?>,Float>> stepsOrderedBy( final Key stat, final boolean trueForAscending )
    {
        final List<Step<?>> steps = new ArrayList<>( pipeline );
        Collections.sort( steps, new Comparator<Step<?>>()
        {
            @Override
            public int compare( Step<?> o1, Step<?> o2 )
            {
                Long stat1 = o1.stats().stat( stat ).asLong();
                Long stat2 = o2.stats().stat( stat ).asLong();
                return trueForAscending
                        ? stat1.compareTo( stat2 )
                        : stat2.compareTo( stat1 );
            }
        } );

        return new Iterable<Pair<Step<?>,Float>>()
        {
            @Override
            public Iterator<Pair<Step<?>,Float>> iterator()
            {
                return new PrefetchingIterator<Pair<Step<?>,Float>>()
                {
                    private final Iterator<Step<?>> source = steps.iterator();
                    private Step<?> next = source.hasNext() ? source.next() : null;

                    @Override
                    protected Pair<Step<?>,Float> fetchNextOrNull()
                    {
                        if ( next == null )
                        {
                            return null;
                        }

                        Step<?> current = next;
                        next = source.hasNext() ? source.next() : null;
                        float factor = next != null
                                ? (float) stat( current, stat ) / (float) stat( next, stat )
                                : 1.0f;
                        return Pair.of( current, factor );
                    }

                    private long stat( Step<?> step, Key stat )
                    {
                        return step.stats().stat( stat ).asLong();
                    }
                };
            }
        };
    }

Replace Anonymous With Lambda org.neo4j.unsafe.impl.batchimport.staging.StageExecution.stepsOrderedBy.new Iterable<Pair<Step<?>,Float>> with (o1, o2) -> {Long stat1=o1.stats().stat(stat).asLong(); in method public stepsOrderedBy(stat Key, trueForAscending boolean) : Iterable<Pair<Step<?>,Float>> from class org.neo4j.unsafe.impl.batchimport.staging.StageExecution


    @Test
    public void shouldReadConsistentPropertyValues() throws Throwable
    {
        // GIVEN
        final Node[] nodes = new Node[10];
        final String[] keys = new String[] {"1", "2", "3"};
        final String[] values = new String[] {
                longString( 'a' ),
                longString( 'b' ),
                longString( 'c' ),
        };
        try ( Transaction tx = db.beginTx() )
        {
            for ( int i = 0; i < nodes.length; i++ )
            {
                nodes[i] = db.createNode();
                for ( int j = 0; j < keys.length; j++ )
                {
                    nodes[i].setProperty( keys[j], values[0] );
                }
            }
            tx.success();
        }

        int updaters = 10;
        final AtomicLong updatersDone = new AtomicLong( updaters );
        Race race = new Race();
        for ( int i = 0; i < updaters; i++ )
        {
            // Changers
            race.addContestant( () ->
            {
                try
                {
                    ThreadLocalRandom random = ThreadLocalRandom.current();
                    for ( int j = 0; j < 100; j++ )
                    {
                        Node node = nodes[random.nextInt( nodes.length )];
                        String key = keys[random.nextInt( keys.length )];
                        try ( Transaction tx = db.beginTx() )
                        {
                            node.removeProperty( key );
                            tx.success();
                        }
                        try ( Transaction tx = db.beginTx() )
                        {
                            node.setProperty( key, values[random.nextInt( values.length )] );
                            tx.success();
                        }
                    }
                }
                finally
                {
                    updatersDone.decrementAndGet();
                }
            } );
        }
        for ( int i = 0; i < 100; i++ )
        {
            // Readers
            race.addContestant( () ->
            {
                ThreadLocalRandom random = ThreadLocalRandom.current();
                while ( updatersDone.get() > 0 )
                {
                    try ( Transaction tx = db.beginTx() )
                    {
                        String value = (String) nodes[random.nextInt( nodes.length )]
                                .getProperty( keys[random.nextInt( keys.length )], null );
                        assertTrue( value, value == null || ArrayUtil.contains( values, value ) );
                        tx.success();
                    }
                }
            } );
        }

        // WHEN
        race.go();
    }

    @Test
    public void shouldReadConsistentPropertyValues() throws Throwable
    {
        // GIVEN
        final Node[] nodes = new Node[10];
        final String[] keys = new String[] {"1", "2", "3"};
        final String[] values = new String[] {
                longString( 'a' ),
                longString( 'b' ),
                longString( 'c' ),
        };
        try ( Transaction tx = db.beginTx() )
        {
            for ( int i = 0; i < nodes.length; i++ )
            {
                nodes[i] = db.createNode();
                for ( int j = 0; j < keys.length; j++ )
                {
                    nodes[i].setProperty( keys[j], values[0] );
                }
            }
            tx.success();
        }

        int updaters = 10;
        final AtomicLong updatersDone = new AtomicLong( updaters );
        Race race = new Race();
        for ( int i = 0; i < updaters; i++ )
        {
            // Changers
            race.addContestant( new Runnable()
            {
                @Override
                public void run()
                {
                    try
                    {
                        ThreadLocalRandom random = ThreadLocalRandom.current();
                        for ( int j = 0; j < 100; j++ )
                        {
                            Node node = nodes[random.nextInt( nodes.length )];
                            String key = keys[random.nextInt( keys.length )];
                            try ( Transaction tx = db.beginTx() )
                            {
                                node.removeProperty( key );
                                tx.success();
                            }
                            try ( Transaction tx = db.beginTx() )
                            {
                                node.setProperty( key, values[random.nextInt( values.length )] );
                                tx.success();
                            }
                        }
                    }
                    finally
                    {
                        updatersDone.decrementAndGet();
                    }
                }
            } );
        }
        for ( int i = 0; i < 100; i++ )
        {
            // Readers
            race.addContestant( new Runnable()
            {
                @Override
                public void run()
                {
                    ThreadLocalRandom random = ThreadLocalRandom.current();
                    while ( updatersDone.get() > 0 )
                    {
                        try ( Transaction tx = db.beginTx() )
                        {
                            String value = (String) nodes[random.nextInt( nodes.length )]
                                    .getProperty( keys[random.nextInt( keys.length )], null );
                            assertTrue( value, value == null || ArrayUtil.contains( values, value ) );
                            tx.success();
                        }
                    }
                }
            } );
        }

        // WHEN
        race.go();
    }

Replace Anonymous With Lambda org.neo4j.graphdb.ConsistentPropertyReadsIT.shouldReadConsistentPropertyValues.addContestant.new Runnable with () -> {tryThreadLocalRandom random=ThreadLocalRandom.current(); in method public shouldReadConsistentPropertyValues() : void from class org.neo4j.graphdb.ConsistentPropertyReadsIT


    @Test
    public void shouldBeAbleToShutdownWhenThereAreTransactionsWaitingForLocks() throws Exception
    {
        // GIVEN
        final GraphDatabaseService db = newDb();

        final Node node;
        try ( Transaction tx = db.beginTx() )
        {
            node = db.createNode();
            tx.success();
        }

        final CountDownLatch nodeLockedLatch = new CountDownLatch( 1 );

        // WHEN
        // one thread locks previously create node and initiates graph db shutdown
        newSingleThreadExecutor().submit( (Callable<Void>) () ->
        {
            try ( Transaction tx = db.beginTx() )
            {
                node.addLabel( label( "ABC" ) );
                nodeLockedLatch.countDown();
                Thread.sleep( 1_000 ); // Let the second thread attempt to lock same node
                db.shutdown();
                tx.success();
            }
            return null;
        } );

        // other thread tries to lock the same node while it has been locked and graph db is being shutdown
        Future<Void> secondTxResult = newSingleThreadExecutor().submit( () ->
        {
            try ( Transaction tx = db.beginTx() )
            {
                nodeLockedLatch.await();
                node.addLabel( label( "DEF" ) );
                tx.success();
            }
            return null;
        } );

        // THEN
        // tx in second thread should fail in reasonable time
        try
        {
            secondTxResult.get( 60, SECONDS );
            fail( "Exception expected" );
        }
        catch ( Exception e )
        {
            assertThat( rootCause( e ), instanceOf( TransactionTerminatedException.class ) );
        }
    }

    @Test
    public void shouldBeAbleToShutdownWhenThereAreTransactionsWaitingForLocks() throws Exception
    {
        // GIVEN
        final GraphDatabaseService db = newDb();

        final Node node;
        try ( Transaction tx = db.beginTx() )
        {
            node = db.createNode();
            tx.success();
        }

        final CountDownLatch nodeLockedLatch = new CountDownLatch( 1 );

        // WHEN
        // one thread locks previously create node and initiates graph db shutdown
        newSingleThreadExecutor().submit( new Callable<Void>()
        {
            @Override
            public Void call() throws Exception
            {
                try ( Transaction tx = db.beginTx() )
                {
                    node.addLabel( label( "ABC" ) );
                    nodeLockedLatch.countDown();
                    Thread.sleep( 1_000 ); // Let the second thread attempt to lock same node
                    db.shutdown();
                    tx.success();
                }
                return null;
            }
        } );

        // other thread tries to lock the same node while it has been locked and graph db is being shutdown
        Future<Void> secondTxResult = newSingleThreadExecutor().submit( new Callable<Void>()
        {
            @Override
            public Void call() throws Exception
            {
                try ( Transaction tx = db.beginTx() )
                {
                    nodeLockedLatch.await();
                    node.addLabel( label( "DEF" ) );
                    tx.success();
                }
                return null;
            }
        } );

        // THEN
        // tx in second thread should fail in reasonable time
        try
        {
            secondTxResult.get( 60, SECONDS );
            fail( "Exception expected" );
        }
        catch ( Exception e )
        {
            assertThat( rootCause( e ), instanceOf( TransactionTerminatedException.class ) );
        }
    }

Replace Anonymous With Lambda org.neo4j.graphdb.GraphDatabaseShutdownTest.shouldBeAbleToShutdownWhenThereAreTransactionsWaitingForLocks.submit.new Callable<Void> with () -> {try(Transaction tx=db.beginTx())node.addLabel(label("ABC")); in method public shouldBeAbleToShutdownWhenThereAreTransactionsWaitingForLocks() : void from class org.neo4j.graphdb.GraphDatabaseShutdownTest


        ProgressMonitorFactory mock( final Indicator.OpenEnded indicatorMock )
        {
            ProgressMonitorFactory factory = Mockito.mock( ProgressMonitorFactory.class );
            when( factory.newOpenEndedIndicator( any( String.class ), anyInt() ) ).thenAnswer( invocation ->
            {
                when( indicatorMock.reportResolution() ).thenReturn( (Integer) invocation.getArguments()[1] );
                return indicatorMock;
            } );
            factoryMocks.put( factory, true );
            return factory;
        }

        ProgressMonitorFactory mock( final Indicator.OpenEnded indicatorMock )
        {
            ProgressMonitorFactory factory = Mockito.mock( ProgressMonitorFactory.class );
            when( factory.newOpenEndedIndicator( any( String.class ), anyInt() ) ).thenAnswer( new Answer<Indicator>()
            {
                @Override
                public Indicator answer( InvocationOnMock invocation ) throws Throwable
                {
                    when( indicatorMock.reportResolution() ).thenReturn( (Integer) invocation.getArguments()[1] );
                    return indicatorMock;
                }
            } );
            factoryMocks.put( factory, true );
            return factory;
        }

Replace Anonymous With Lambda org.neo4j.helpers.progress.ProgressMonitorTest.SingleIndicator.mock.thenAnswer.new Answer<Indicator> with invocation -> {when(indicatorMock.reportResolution()).thenReturn((Integer)invocation.getArguments()[1]); in method package mock(indicatorMock Indicator.OpenEnded) : ProgressMonitorFactory from class org.neo4j.helpers.progress.ProgressMonitorTest.SingleIndicator


    @Test
    public void shouldRecoverExistingData() throws Exception
    {
        final PhysicalLogFiles logFiles = new PhysicalLogFiles( directory.directory(), "log", fileSystemRule.get() );
        File file = logFiles.getLogFileForVersion( logVersion );

        writeSomeData( file, pair ->
        {
            LogEntryWriter writer = pair.first();
            Consumer<LogPositionMarker> consumer = pair.other();
            LogPositionMarker marker = new LogPositionMarker();

            // last committed tx
            consumer.accept( marker );
            LogPosition lastCommittedTxPosition = marker.newPosition();
            writer.writeStartEntry( 0, 1, 2L, 3L, new byte[0] );
            lastCommittedTxStartEntry = new LogEntryStart( 0, 1, 2L, 3L, new byte[0], lastCommittedTxPosition );
            writer.writeCommitEntry( 4L, 5L );
            lastCommittedTxCommitEntry = new OnePhaseCommit( 4L, 5L );

            // check point pointing to the previously committed transaction
            writer.writeCheckPointEntry( lastCommittedTxPosition );
            expectedCheckPointEntry = new CheckPoint( lastCommittedTxPosition );

            // tx committed after checkpoint
            consumer.accept( marker );
            writer.writeStartEntry( 0, 1, 6L, 4L, new byte[0] );
            expectedStartEntry = new LogEntryStart( 0, 1, 6L, 4L, new byte[0], marker.newPosition() );

            writer.writeCommitEntry( 5L, 7L );
            expectedCommitEntry = new OnePhaseCommit( 5L, 7L );

            return true;
        } );

        LifeSupport life = new LifeSupport();
        Recovery.Monitor monitor = mock( Recovery.Monitor.class );
        final AtomicBoolean recoveryRequired = new AtomicBoolean();
        try
        {
            StorageEngine storageEngine = mock( StorageEngine.class );
            final LogEntryReader<ReadableClosablePositionAwareChannel> reader = new VersionAwareLogEntryReader<>();
            LatestCheckPointFinder finder = new LatestCheckPointFinder( logFiles, fileSystemRule.get(), reader );

            LogHeaderCache logHeaderCache = new LogHeaderCache( 10 );
            TransactionMetadataCache metadataCache = new TransactionMetadataCache( 100 );
            LogFile logFile = life.add( new PhysicalLogFile( fileSystemRule.get(), logFiles, 50,
                    () -> transactionIdStore.getLastCommittedTransactionId(), logVersionRepository,
                    mock( PhysicalLogFile.Monitor.class ), logHeaderCache ) );
            LogicalTransactionStore txStore = new PhysicalLogicalTransactionStore( logFile, metadataCache, reader );

            life.add( new Recovery( new DefaultRecoverySPI( storageEngine, logFiles, fileSystemRule.get(),
                    logVersionRepository, finder, transactionIdStore, txStore, NO_MONITOR )
            {
                private int nr;

                @Override
                public Visitor<CommittedTransactionRepresentation,Exception> startRecovery()
                {
                    recoveryRequired.set( true );
                    final Visitor<CommittedTransactionRepresentation,Exception> actual = super.startRecovery();
                    return tx ->
                    {
                        actual.visit( tx );
                        switch ( nr++ )
                        {
                        case 0:
                            assertEquals( lastCommittedTxStartEntry, tx.getStartEntry() );
                            assertEquals( lastCommittedTxCommitEntry, tx.getCommitEntry() );
                            break;
                        case 1:
                            assertEquals( expectedStartEntry, tx.getStartEntry() );
                            assertEquals( expectedCommitEntry, tx.getCommitEntry() );
                            break;
                        default: fail( "Too many recovered transactions" );
                        }
                        return false;
                    };
                }
            }, monitor ) );

            life.start();

            InOrder order = inOrder( monitor );
            order.verify( monitor, times( 1 ) ).recoveryRequired( any( LogPosition.class ) );
            order.verify( monitor, times( 1 ) ).recoveryCompleted( 2 );
            assertTrue( recoveryRequired.get() );
        }
        finally
        {
            life.shutdown();
        }
    }

    @Test
    public void shouldRecoverExistingData() throws Exception
    {
        final PhysicalLogFiles logFiles = new PhysicalLogFiles( directory.directory(), "log", fileSystemRule.get() );
        File file = logFiles.getLogFileForVersion( logVersion );

        writeSomeData( file, new Visitor<Pair<LogEntryWriter, Consumer<LogPositionMarker>>,IOException>()
        {
            @Override
            public boolean visit( Pair<LogEntryWriter,Consumer<LogPositionMarker>> pair ) throws IOException
            {
                LogEntryWriter writer = pair.first();
                Consumer<LogPositionMarker> consumer = pair.other();
                LogPositionMarker marker = new LogPositionMarker();

                // last committed tx
                consumer.accept( marker );
                LogPosition lastCommittedTxPosition = marker.newPosition();
                writer.writeStartEntry( 0, 1, 2L, 3L, new byte[0] );
                lastCommittedTxStartEntry = new LogEntryStart( 0, 1, 2L, 3L, new byte[0], lastCommittedTxPosition );
                writer.writeCommitEntry( 4L, 5L );
                lastCommittedTxCommitEntry = new OnePhaseCommit( 4L, 5L );

                // check point pointing to the previously committed transaction
                writer.writeCheckPointEntry( lastCommittedTxPosition );
                expectedCheckPointEntry = new CheckPoint( lastCommittedTxPosition );

                // tx committed after checkpoint
                consumer.accept( marker );
                writer.writeStartEntry( 0, 1, 6L, 4L, new byte[0] );
                expectedStartEntry = new LogEntryStart( 0, 1, 6L, 4L, new byte[0], marker.newPosition() );

                writer.writeCommitEntry( 5L, 7L );
                expectedCommitEntry = new OnePhaseCommit( 5L, 7L );

                return true;
            }
        } );

        LifeSupport life = new LifeSupport();
        Recovery.Monitor monitor = mock( Recovery.Monitor.class );
        final AtomicBoolean recoveryRequired = new AtomicBoolean();
        try
        {
            StorageEngine storageEngine = mock( StorageEngine.class );
            final LogEntryReader<ReadableClosablePositionAwareChannel> reader = new VersionAwareLogEntryReader<>();
            LatestCheckPointFinder finder = new LatestCheckPointFinder( logFiles, fileSystemRule.get(), reader );

            LogHeaderCache logHeaderCache = new LogHeaderCache( 10 );
            TransactionMetadataCache metadataCache = new TransactionMetadataCache( 100 );
            LogFile logFile = life.add( new PhysicalLogFile( fileSystemRule.get(), logFiles, 50,
                    () -> transactionIdStore.getLastCommittedTransactionId(), logVersionRepository,
                    mock( PhysicalLogFile.Monitor.class ), logHeaderCache ) );
            LogicalTransactionStore txStore = new PhysicalLogicalTransactionStore( logFile, metadataCache, reader );

            life.add( new Recovery( new DefaultRecoverySPI( storageEngine, logFiles, fileSystemRule.get(),
                    logVersionRepository, finder, transactionIdStore, txStore, NO_MONITOR )
            {
                private int nr;

                @Override
                public Visitor<CommittedTransactionRepresentation,Exception> startRecovery()
                {
                    recoveryRequired.set( true );
                    final Visitor<CommittedTransactionRepresentation,Exception> actual = super.startRecovery();
                    return new Visitor<CommittedTransactionRepresentation,Exception>()
                    {
                        @Override
                        public boolean visit( CommittedTransactionRepresentation tx ) throws Exception
                        {
                            actual.visit( tx );
                            switch ( nr++ )
                            {
                            case 0:
                                assertEquals( lastCommittedTxStartEntry, tx.getStartEntry() );
                                assertEquals( lastCommittedTxCommitEntry, tx.getCommitEntry() );
                                break;
                            case 1:
                                assertEquals( expectedStartEntry, tx.getStartEntry() );
                                assertEquals( expectedCommitEntry, tx.getCommitEntry() );
                                break;
                            default: fail( "Too many recovered transactions" );
                            }
                            return false;
                        }
                    };
                }
            }, monitor ) );

            life.start();

            InOrder order = inOrder( monitor );
            order.verify( monitor, times( 1 ) ).recoveryRequired( any( LogPosition.class ) );
            order.verify( monitor, times( 1 ) ).recoveryCompleted( 2 );
            assertTrue( recoveryRequired.get() );
        }
        finally
        {
            life.shutdown();
        }
    }

Replace Anonymous With Lambda org.neo4j.kernel.RecoveryTest.shouldRecoverExistingData.writeSomeData.new Visitor<Pair<LogEntryWriter,Consumer<LogPositionMarker>>,IOException> with pair -> {LogEntryWriter writer=pair.first(); in method public shouldRecoverExistingData() : void from class org.neo4j.kernel.RecoveryTest


                @Override
                public Visitor<CommittedTransactionRepresentation,Exception> startRecovery()
                {
                    recoveryRequired.set( true );
                    final Visitor<CommittedTransactionRepresentation,Exception> actual = super.startRecovery();
                    return tx ->
                    {
                        actual.visit( tx );
                        switch ( nr++ )
                        {
                        case 0:
                            assertEquals( lastCommittedTxStartEntry, tx.getStartEntry() );
                            assertEquals( lastCommittedTxCommitEntry, tx.getCommitEntry() );
                            break;
                        case 1:
                            assertEquals( expectedStartEntry, tx.getStartEntry() );
                            assertEquals( expectedCommitEntry, tx.getCommitEntry() );
                            break;
                        default: fail( "Too many recovered transactions" );
                        }
                        return false;
                    };
                }

                @Override
                public Visitor<CommittedTransactionRepresentation,Exception> startRecovery()
                {
                    recoveryRequired.set( true );
                    final Visitor<CommittedTransactionRepresentation,Exception> actual = super.startRecovery();
                    return new Visitor<CommittedTransactionRepresentation,Exception>()
                    {
                        @Override
                        public boolean visit( CommittedTransactionRepresentation tx ) throws Exception
                        {
                            actual.visit( tx );
                            switch ( nr++ )
                            {
                            case 0:
                                assertEquals( lastCommittedTxStartEntry, tx.getStartEntry() );
                                assertEquals( lastCommittedTxCommitEntry, tx.getCommitEntry() );
                                break;
                            case 1:
                                assertEquals( expectedStartEntry, tx.getStartEntry() );
                                assertEquals( expectedCommitEntry, tx.getCommitEntry() );
                                break;
                            default: fail( "Too many recovered transactions" );
                            }
                            return false;
                        }
                    };
                }

Replace Anonymous With Lambda org.neo4j.kernel.RecoveryTest.shouldRecoverExistingData.add.new Recovery.new DefaultRecoverySPI.startRecovery.new Visitor<CommittedTransactionRepresentation,Exception> with tx -> {actual.visit(tx); in method public startRecovery() : Visitor<CommittedTransactionRepresentation,Exception> from class org.neo4j.kernel.RecoveryTest.shouldRecoverExistingData.add.new Recovery.new DefaultRecoverySPI


    @Test
    public void shouldSeeThatACleanDatabaseShouldNotRequireRecovery() throws Exception
    {
        final PhysicalLogFiles logFiles = new PhysicalLogFiles( directory.directory(), "log", fileSystemRule.get() );
        File file = logFiles.getLogFileForVersion( logVersion );

        writeSomeData( file, pair ->
        {
            LogEntryWriter writer = pair.first();
            Consumer<LogPositionMarker> consumer = pair.other();
            LogPositionMarker marker = new LogPositionMarker();

            // last committed tx
            consumer.accept( marker );
            writer.writeStartEntry( 0, 1, 2L, 3L, new byte[0] );
            writer.writeCommitEntry( 4L, 5L );

            // check point
            consumer.accept( marker );
            writer.writeCheckPointEntry( marker.newPosition() );

            return true;
        } );

        LifeSupport life = new LifeSupport();
        Recovery.Monitor monitor = mock( Recovery.Monitor.class );
        try
        {
            StorageEngine storageEngine = mock( StorageEngine.class );
            final LogEntryReader<ReadableClosablePositionAwareChannel> reader = new VersionAwareLogEntryReader<>();
            LatestCheckPointFinder finder = new LatestCheckPointFinder( logFiles, fileSystemRule.get(), reader );

            TransactionMetadataCache metadataCache = new TransactionMetadataCache( 100 );
            LogHeaderCache logHeaderCache = new LogHeaderCache( 10 );
            LogFile logFile = life.add( new PhysicalLogFile( fileSystemRule.get(), logFiles, 50,
                    () -> transactionIdStore.getLastCommittedTransactionId(), logVersionRepository,
                    mock( PhysicalLogFile.Monitor.class ), logHeaderCache ) );
            LogicalTransactionStore txStore = new PhysicalLogicalTransactionStore( logFile, metadataCache, reader );

            life.add( new Recovery( new DefaultRecoverySPI( storageEngine, logFiles, fileSystemRule.get(),
                    logVersionRepository, finder, transactionIdStore, txStore, NO_MONITOR )
            {
                @Override
                public Visitor<CommittedTransactionRepresentation,Exception> startRecovery()
                {
                    fail( "Recovery should not be required" );
                    return null; // <-- to satisfy the compiler
                }
            }, monitor ));

            life.start();

            verifyZeroInteractions( monitor );
        }
        finally
        {
            life.shutdown();
        }
    }

    @Test
    public void shouldSeeThatACleanDatabaseShouldNotRequireRecovery() throws Exception
    {
        final PhysicalLogFiles logFiles = new PhysicalLogFiles( directory.directory(), "log", fileSystemRule.get() );
        File file = logFiles.getLogFileForVersion( logVersion );

        writeSomeData( file, new Visitor<Pair<LogEntryWriter, Consumer<LogPositionMarker>>,IOException>()
        {
            @Override
            public boolean visit( Pair<LogEntryWriter,Consumer<LogPositionMarker>> pair ) throws IOException
            {
                LogEntryWriter writer = pair.first();
                Consumer<LogPositionMarker> consumer = pair.other();
                LogPositionMarker marker = new LogPositionMarker();

                // last committed tx
                consumer.accept( marker );
                writer.writeStartEntry( 0, 1, 2L, 3L, new byte[0] );
                writer.writeCommitEntry( 4L, 5L );

                // check point
                consumer.accept( marker );
                writer.writeCheckPointEntry( marker.newPosition() );

                return true;
            }
        } );

        LifeSupport life = new LifeSupport();
        Recovery.Monitor monitor = mock( Recovery.Monitor.class );
        try
        {
            StorageEngine storageEngine = mock( StorageEngine.class );
            final LogEntryReader<ReadableClosablePositionAwareChannel> reader = new VersionAwareLogEntryReader<>();
            LatestCheckPointFinder finder = new LatestCheckPointFinder( logFiles, fileSystemRule.get(), reader );

            TransactionMetadataCache metadataCache = new TransactionMetadataCache( 100 );
            LogHeaderCache logHeaderCache = new LogHeaderCache( 10 );
            LogFile logFile = life.add( new PhysicalLogFile( fileSystemRule.get(), logFiles, 50,
                    () -> transactionIdStore.getLastCommittedTransactionId(), logVersionRepository,
                    mock( PhysicalLogFile.Monitor.class ), logHeaderCache ) );
            LogicalTransactionStore txStore = new PhysicalLogicalTransactionStore( logFile, metadataCache, reader );

            life.add( new Recovery( new DefaultRecoverySPI( storageEngine, logFiles, fileSystemRule.get(),
                    logVersionRepository, finder, transactionIdStore, txStore, NO_MONITOR )
            {
                @Override
                public Visitor<CommittedTransactionRepresentation,Exception> startRecovery()
                {
                    fail( "Recovery should not be required" );
                    return null; // <-- to satisfy the compiler
                }
            }, monitor ));

            life.start();

            verifyZeroInteractions( monitor );
        }
        finally
        {
            life.shutdown();
        }
    }

Replace Anonymous With Lambda org.neo4j.kernel.RecoveryTest.shouldSeeThatACleanDatabaseShouldNotRequireRecovery.writeSomeData.new Visitor<Pair<LogEntryWriter,Consumer<LogPositionMarker>>,IOException> with pair -> {LogEntryWriter writer=pair.first(); in method public shouldSeeThatACleanDatabaseShouldNotRequireRecovery() : void from class org.neo4j.kernel.RecoveryTest


    @Test
    public void shouldTruncateLogAfterSinglePartialTransaction() throws Exception
    {
        // GIVEN
        final PhysicalLogFiles logFiles = new PhysicalLogFiles( directory.directory(), "log", fileSystemRule.get() );
        File file = logFiles.getLogFileForVersion( logVersion );
        final LogPositionMarker marker = new LogPositionMarker();

        writeSomeData( file, pair ->
        {
            LogEntryWriter writer = pair.first();
            Consumer<LogPositionMarker> consumer = pair.other();

            // incomplete tx
            consumer.accept( marker ); // <-- marker has the last good position
            writer.writeStartEntry( 0, 1, 5L, 4L, new byte[0] );

            return true;
        } );

        // WHEN
        boolean recoveryRequired = recover( logFiles );

        // THEN
        assertTrue( recoveryRequired );
        assertEquals( marker.getByteOffset(), file.length() );
    }

    @Test
    public void shouldTruncateLogAfterSinglePartialTransaction() throws Exception
    {
        // GIVEN
        final PhysicalLogFiles logFiles = new PhysicalLogFiles( directory.directory(), "log", fileSystemRule.get() );
        File file = logFiles.getLogFileForVersion( logVersion );
        final LogPositionMarker marker = new LogPositionMarker();

        writeSomeData( file, new Visitor<Pair<LogEntryWriter, Consumer<LogPositionMarker>>,IOException>()
        {
            @Override
            public boolean visit( Pair<LogEntryWriter,Consumer<LogPositionMarker>> pair ) throws IOException
            {
                LogEntryWriter writer = pair.first();
                Consumer<LogPositionMarker> consumer = pair.other();

                // incomplete tx
                consumer.accept( marker ); // <-- marker has the last good position
                writer.writeStartEntry( 0, 1, 5L, 4L, new byte[0] );

                return true;
            }
        } );

        // WHEN
        boolean recoveryRequired = recover( logFiles );

        // THEN
        assertTrue( recoveryRequired );
        assertEquals( marker.getByteOffset(), file.length() );
    }

Replace Anonymous With Lambda org.neo4j.kernel.RecoveryTest.shouldTruncateLogAfterSinglePartialTransaction.writeSomeData.new Visitor<Pair<LogEntryWriter,Consumer<LogPositionMarker>>,IOException> with pair -> {LogEntryWriter writer=pair.first(); in method public shouldTruncateLogAfterSinglePartialTransaction() : void from class org.neo4j.kernel.RecoveryTest


    @Test
    public void shouldTruncateLogAfterLastCompleteTransactionAfterSuccessfullRecovery() throws Exception
    {
        // GIVEN
        final PhysicalLogFiles logFiles = new PhysicalLogFiles( directory.directory(), "log", fileSystemRule.get() );
        File file = logFiles.getLogFileForVersion( logVersion );
        final LogPositionMarker marker = new LogPositionMarker();

        writeSomeData( file, pair ->
        {
            LogEntryWriter writer = pair.first();
            Consumer<LogPositionMarker> consumer = pair.other();

            // last committed tx
            writer.writeStartEntry( 0, 1, 2L, 3L, new byte[0] );
            writer.writeCommitEntry( 4L, 5L );

            // incomplete tx
            consumer.accept( marker ); // <-- marker has the last good position
            writer.writeStartEntry( 0, 1, 5L, 4L, new byte[0] );

            return true;
        } );

        // WHEN
        boolean recoveryRequired = recover( logFiles );

        // THEN
        assertTrue( recoveryRequired );
        assertEquals( marker.getByteOffset(), file.length() );
    }

    @Test
    public void shouldTruncateLogAfterLastCompleteTransactionAfterSuccessfullRecovery() throws Exception
    {
        // GIVEN
        final PhysicalLogFiles logFiles = new PhysicalLogFiles( directory.directory(), "log", fileSystemRule.get() );
        File file = logFiles.getLogFileForVersion( logVersion );
        final LogPositionMarker marker = new LogPositionMarker();

        writeSomeData( file, new Visitor<Pair<LogEntryWriter, Consumer<LogPositionMarker>>,IOException>()
        {
            @Override
            public boolean visit( Pair<LogEntryWriter,Consumer<LogPositionMarker>> pair ) throws IOException
            {
                LogEntryWriter writer = pair.first();
                Consumer<LogPositionMarker> consumer = pair.other();

                // last committed tx
                writer.writeStartEntry( 0, 1, 2L, 3L, new byte[0] );
                writer.writeCommitEntry( 4L, 5L );

                // incomplete tx
                consumer.accept( marker ); // <-- marker has the last good position
                writer.writeStartEntry( 0, 1, 5L, 4L, new byte[0] );

                return true;
            }
        } );

        // WHEN
        boolean recoveryRequired = recover( logFiles );

        // THEN
        assertTrue( recoveryRequired );
        assertEquals( marker.getByteOffset(), file.length() );
    }

Replace Anonymous With Lambda org.neo4j.kernel.RecoveryTest.shouldTruncateLogAfterLastCompleteTransactionAfterSuccessfullRecovery.writeSomeData.new Visitor<Pair<LogEntryWriter,Consumer<LogPositionMarker>>,IOException> with pair -> {LogEntryWriter writer=pair.first(); in method public shouldTruncateLogAfterLastCompleteTransactionAfterSuccessfullRecovery() : void from class org.neo4j.kernel.RecoveryTest


    @Test
    public void shouldTellTransactionIdStoreAfterSuccessfullRecovery() throws Exception
    {
        // GIVEN
        final PhysicalLogFiles logFiles = new PhysicalLogFiles( directory.directory(), "log", fileSystemRule.get() );
        File file = logFiles.getLogFileForVersion( logVersion );
        final LogPositionMarker marker = new LogPositionMarker();

        final byte[] additionalHeaderData = new byte[0];
        final int masterId = 0;
        final int authorId = 1;
        final long transactionId = 4;
        final long commitTimestamp = 5;
        writeSomeData( file, pair ->
        {
            LogEntryWriter writer = pair.first();
            Consumer<LogPositionMarker> consumer = pair.other();

            // last committed tx
            writer.writeStartEntry( masterId, authorId, 2L, 3L, additionalHeaderData );
            writer.writeCommitEntry( transactionId, commitTimestamp );
            consumer.accept( marker );

            return true;
        } );

        // WHEN
        boolean recoveryRequired = recover( logFiles );

        // THEN
        assertTrue( recoveryRequired );
        long[] lastClosedTransaction = transactionIdStore.getLastClosedTransaction();
        assertEquals( transactionId, lastClosedTransaction[0] );
        assertEquals( LogEntryStart.checksum( additionalHeaderData, masterId, authorId ),
                transactionIdStore.getLastCommittedTransaction().checksum() );
        assertEquals( commitTimestamp, transactionIdStore.getLastCommittedTransaction().commitTimestamp() );
        assertEquals( logVersion, lastClosedTransaction[1] );
        assertEquals( marker.getByteOffset(), lastClosedTransaction[2] );
    }

    @Test
    public void shouldTellTransactionIdStoreAfterSuccessfullRecovery() throws Exception
    {
        // GIVEN
        final PhysicalLogFiles logFiles = new PhysicalLogFiles( directory.directory(), "log", fileSystemRule.get() );
        File file = logFiles.getLogFileForVersion( logVersion );
        final LogPositionMarker marker = new LogPositionMarker();

        final byte[] additionalHeaderData = new byte[0];
        final int masterId = 0;
        final int authorId = 1;
        final long transactionId = 4;
        final long commitTimestamp = 5;
        writeSomeData( file, new Visitor<Pair<LogEntryWriter, Consumer<LogPositionMarker>>,IOException>()
        {
            @Override
            public boolean visit( Pair<LogEntryWriter,Consumer<LogPositionMarker>> pair ) throws IOException
            {
                LogEntryWriter writer = pair.first();
                Consumer<LogPositionMarker> consumer = pair.other();

                // last committed tx
                writer.writeStartEntry( masterId, authorId, 2L, 3L, additionalHeaderData );
                writer.writeCommitEntry( transactionId, commitTimestamp );
                consumer.accept( marker );

                return true;
            }
        } );

        // WHEN
        boolean recoveryRequired = recover( logFiles );

        // THEN
        assertTrue( recoveryRequired );
        long[] lastClosedTransaction = transactionIdStore.getLastClosedTransaction();
        assertEquals( transactionId, lastClosedTransaction[0] );
        assertEquals( LogEntryStart.checksum( additionalHeaderData, masterId, authorId ),
                transactionIdStore.getLastCommittedTransaction().checksum() );
        assertEquals( commitTimestamp, transactionIdStore.getLastCommittedTransaction().commitTimestamp() );
        assertEquals( logVersion, lastClosedTransaction[1] );
        assertEquals( marker.getByteOffset(), lastClosedTransaction[2] );
    }

Replace Anonymous With Lambda org.neo4j.kernel.RecoveryTest.shouldTellTransactionIdStoreAfterSuccessfullRecovery.writeSomeData.new Visitor<Pair<LogEntryWriter,Consumer<LogPositionMarker>>,IOException> with pair -> {LogEntryWriter writer=pair.first(); in method public shouldTellTransactionIdStoreAfterSuccessfullRecovery() : void from class org.neo4j.kernel.RecoveryTest