private FreeIdKeeper getFreeIdKeeper( StoreChannel channel, int batchSize, boolean aggressiveMode ) throws IOException { return new FreeIdKeeper( channel, batchSize, aggressiveMode ); }
public void freeId( long id ) { freeIdKeeper.freeId( id ); }
public long getFreeIdCount() { return freeIdKeeper.getCount(); }
@Override public void close() throws IOException { ByteBuffer writeBuffer = ByteBuffer.allocate( batchSize * ID_ENTRY_SIZE ); flushFreeIds( writeBuffer ); freeIds.addAll( readFromDisk ); flushFreeIds( writeBuffer ); if ( !aggressiveMode ) { compact( writeBuffer ); } channel.force( false ); }
@Test public void allocateBatchWhenHaveLessIdsInMemoryButHaveOnDiskMore() throws IOException { FreeIdKeeper freeIdKeeper = getFreeIdKeeperAggressive( 4 ); for ( long id = 1L; id < 11L; id++ ) { freeIdKeeper.freeId( id ); } long[] ids = freeIdKeeper.getIds( 7 ); assertArrayEquals( new long[]{9L, 10L, 5L, 6L, 7L, 8L, 1L}, ids ); assertEquals( 3, freeIdKeeper.getCount() ); }
keeper.freeId( i ); freeIds.add( i ); for ( long i = batchSize; i < batchSize + extraIds; i++ ) keeper.freeId( i ); freeIds.add( i ); keeper.close(); channel.close(); assertEquals( batchSize + extraIds, keeper.getCount() ); assertEquals( freeIds.size(), keeper.getCount() ); long id = keeper.getId(); assertTrue( freeIds.contains( id ) );
@Test public void freeingAnIdShouldReturnThatIdAndUpdateTheCountWhenAggressiveModeIsSet() throws Exception { // Given FreeIdKeeper keeper = getFreeIdKeeperAggressive(); // when keeper.freeId( 13 ); // then assertEquals( 1, keeper.getCount() ); // when long result = keeper.getId(); // then assertEquals( 13, result ); assertEquals( 0, keeper.getCount() ); }
@Test public void persistedIdsShouldStillBeCounted() throws Exception { // given StoreChannel channel = getStoreChannel(); int batchSize = 10; FreeIdKeeper keeper = new FreeIdKeeper( channel, batchSize, true ); // when // we store enough ids to cause overflow to file for ( int i = 0; i < batchSize; i++ ) { keeper.freeId( i ); } // and then some more int extraIds = 3; for ( int i = batchSize; i < batchSize + extraIds; i++ ) { keeper.freeId( i ); } // then // the count should be returned correctly assertEquals( batchSize + extraIds, keeper.getCount() ); }
/** * @return next free id or {@link IdContainer#NO_RESULT} if not available */ public long getReusableId() { return freeIdKeeper.getId(); }
public long[] getReusableIds( int numberOfIds ) { return freeIdKeeper.getIds( numberOfIds ); }
public void close( long highId ) { if ( !closed ) { try { freeIdKeeper.close(); writeHeader( highId ); markAsCleanlyClosed(); closeChannel(); } catch ( IOException e ) { throw new UnderlyingStorageException( "Unable to close id file " + file, e ); } } }
static long readDefragCount( FileSystemAbstraction fileSystem, File file ) throws IOException { try ( StoreChannel channel = fileSystem.open( file, OpenMode.READ ) ) { return FreeIdKeeper.countFreeIds( new OffsetChannel( channel, HEADER_SIZE ) ); } }
/** * Flushes the currently collected in-memory freed IDs to the storage. */ private long flushFreeIds( ByteBuffer writeBuffer ) { try { return flushFreeIds0( writeBuffer ); } catch ( IOException e ) { throw new UnderlyingStorageException( "Unable to write free id batch", e ); } }
public void freeId( long id ) { freeIds.enqueue( id ); freeIdCount++; if ( freeIds.size() >= batchSize ) { long endPosition = flushFreeIds( ByteBuffer.allocate( batchSize * ID_ENTRY_SIZE ) ); if ( aggressiveMode ) { stackPosition = endPosition; } } }
@Test public void allocateBatchWhenHaveMoreIdsInMemory() throws IOException { FreeIdKeeper freeIdKeeper = getFreeIdKeeperAggressive(); for ( long id = 1L; id < 7L; id++ ) { freeIdKeeper.freeId( id ); } long[] ids = freeIdKeeper.getIds( 5 ); assertArrayEquals( new long[]{1L, 2L, 3L, 4L, 5L}, ids); assertEquals( 1, freeIdKeeper.getCount() ); }