### Question:
GBPTree implements Closeable { public Writer<KEY,VALUE> writer() throws IOException { return writer( InternalTreeLogic.DEFAULT_SPLIT_RATIO ); } GBPTree( PageCache pageCache, File indexFile, Layout<KEY,VALUE> layout, int tentativePageSize,
            Monitor monitor, Header.Reader headerReader, Consumer<PageCursor> headerWriter,
            RecoveryCleanupWorkCollector recoveryCleanupWorkCollector, boolean readOnly ); static void readHeader( PageCache pageCache, File indexFile, Header.Reader headerReader ); RawCursor<Hit<KEY,VALUE>,IOException> seek( KEY fromInclusive, KEY toExclusive ); void checkpoint( IOLimiter ioLimiter, Consumer<PageCursor> headerWriter ); void checkpoint( IOLimiter ioLimiter ); @Override void close(); Writer<KEY,VALUE> writer(); Writer<KEY,VALUE> writer( double ratioToKeepInLeftOnSplit ); VISITOR visit( VISITOR visitor ); @SuppressWarnings( "unused" ) void printTree(); void printState(); boolean consistencyCheck(); boolean consistencyCheck( boolean reportCrashPointers ); boolean consistencyCheck( GBPTreeConsistencyCheckVisitor<KEY> visitor ); boolean consistencyCheck( GBPTreeConsistencyCheckVisitor<KEY> visitor, boolean reportCrashPointers ); @VisibleForTesting void unsafe( GBPTreeUnsafe<KEY,VALUE> unsafe ); @Override String toString(); boolean wasDirtyOnStartup(); int keyValueSizeCap(); static final Monitor NO_MONITOR; static final Header.Reader NO_HEADER_READER; static final Consumer<PageCursor> NO_HEADER_WRITER; }### Answer:
@Test public void failureDuringInitializeWriterShouldNotFailNextInitialize() throws Exception { IOException no = new IOException( "No" ); AtomicBoolean throwOnNextIO = new AtomicBoolean(); PageCache controlledPageCache = pageCacheThatThrowExceptionWhenToldTo( no, throwOnNextIO ); try ( GBPTree<MutableLong, MutableLong> index = index( controlledPageCache ).build() ) { assertTrue( throwOnNextIO.compareAndSet( false, true ) ); try ( Writer<MutableLong,MutableLong> ignored = index.writer() ) { fail( "Expected to throw" ); } catch ( IOException e ) { assertSame( no, e ); } try ( Writer<MutableLong,MutableLong> writer = index.writer() ) { writer.put( new MutableLong( 1 ), new MutableLong( 1 ) ); } } }
@Test( timeout = 5_000L ) public void writerShouldLockOutClose() throws Exception { GBPTree<MutableLong,MutableLong> index = index().build(); Barrier.Control barrier = new Barrier.Control(); Future<?> write = executor.submit( throwing( () -> { try ( Writer<MutableLong,MutableLong> writer = index.writer() ) { writer.put( new MutableLong( 1 ), new MutableLong( 1 ) ); barrier.reached(); } } ) ); barrier.awaitUninterruptibly(); Future<?> close = executor.submit( throwing( index::close ) ); shouldWait( close ); barrier.release(); close.get(); write.get(); }