@Override public long nextId() { assert !closed; long id; while ( currentBatch == null || (id = currentBatch.nextId()) == VALUE_REPRESENTING_NULL ) { currentBatch = source.nextIdBatch( batchSize ).iterator(); } return id; }
@Test public void shouldNotHaveAnyGaps() { // given int rangeLength = 1024; IdRangeIterator iterator = new IdRange( new long[]{}, 0, rangeLength ).iterator(); // when Set<Long> seenIds = new HashSet<>(); for ( int i = 0; i < rangeLength; i++ ) { seenIds.add( iterator.nextId() ); if ( i > 0 ) { // then assertTrue( "Missing id " + (i - 1), seenIds.contains( (long) i - 1 ) ); } } }
@Test public void shouldGetNextIdBatchFromOnlyDefragIds() { // given IdRangeIterator iterator = new IdRange( new long[] {1, 2, 3, 4, 5, 6}, 7, 0 ).iterator(); // when IdRangeIterator subRange = iterator.nextIdBatch( 5 ).iterator(); // then assertEquals( 6, iterator.nextId() ); for ( long i = 0; i < 5; i++ ) { assertEquals( 1 + i, subRange.nextId() ); } assertEquals( VALUE_REPRESENTING_NULL, subRange.nextId() ); }
@Test public void shouldReturnValueRepresentingNullIfWeExhaustIdRange() { // given int rangeLength = 1024; IdRangeIterator iterator = new IdRange( new long[]{}, 0, rangeLength ).iterator(); // when for ( int i = 0; i < rangeLength; i++ ) { iterator.nextId(); } // then assertEquals( IdRangeIterator.VALUE_REPRESENTING_NULL, iterator.nextId() ); }
@Test public void shouldGetNextIdBatchFromOnlyDefragIdsWhenSomeDefragIdsHaveAlreadyBeenReturned() { // given IdRangeIterator iterator = new IdRange( new long[] {1, 2, 3, 4, 5, 6}, 7, 0 ).iterator(); iterator.nextId(); iterator.nextId(); // when IdRangeIterator subRange = iterator.nextIdBatch( 3 ).iterator(); // then assertEquals( 6, iterator.nextId() ); for ( long i = 0; i < 3; i++ ) { assertEquals( 3 + i, subRange.nextId() ); } assertEquals( VALUE_REPRESENTING_NULL, subRange.nextId() ); }
@Test public void shouldUseDefragIdsFirst() { // given int rangeLength = 1024; IdRangeIterator iterator = new IdRange( new long[] {7, 8, 9}, 1024, rangeLength ).iterator(); // then assertEquals( 7, iterator.nextId() ); assertEquals( 8, iterator.nextId() ); assertEquals( 9, iterator.nextId() ); assertEquals( 1024, iterator.nextId() ); }
@Test public void shouldGetNextIdBatchFromSomeDefragAndSomeRangeIds() { // given IdRangeIterator iterator = new IdRange( new long[] {1, 2, 3}, 10, 5 ).iterator(); iterator.nextId(); // when IdRangeIterator subRange = iterator.nextIdBatch( 5 ).iterator(); // then assertEquals( 13, iterator.nextId() ); assertEquals( 2, subRange.nextId() ); assertEquals( 3, subRange.nextId() ); assertEquals( 10, subRange.nextId() ); assertEquals( 11, subRange.nextId() ); assertEquals( 12, subRange.nextId() ); assertEquals( VALUE_REPRESENTING_NULL, subRange.nextId() ); }
@Test public void shouldGetNextIdBatchFromSomeRangeIds() { // given IdRangeIterator iterator = new IdRange( EMPTY_LONG_ARRAY, 0, 20 ).iterator(); iterator.nextId(); // when IdRangeIterator subRange = iterator.nextIdBatch( 5 ).iterator(); // then assertEquals( 6, iterator.nextId() ); assertEquals( 1, subRange.nextId() ); assertEquals( 2, subRange.nextId() ); assertEquals( 3, subRange.nextId() ); assertEquals( 4, subRange.nextId() ); assertEquals( 5, subRange.nextId() ); assertEquals( VALUE_REPRESENTING_NULL, subRange.nextId() ); // when subRange = iterator.nextIdBatch( 2 ).iterator(); // then assertEquals( 9, iterator.nextId() ); assertEquals( 7, subRange.nextId() ); assertEquals( 8, subRange.nextId() ); assertEquals( VALUE_REPRESENTING_NULL, subRange.nextId() ); }
@Test public void shouldGetNextIdBatchFromSomeRangeIdsWhenThereAreUsedDefragIds() { // given IdRangeIterator iterator = new IdRange( new long[] {0, 1, 2}, 3, 10 ).iterator(); iterator.nextId(); iterator.nextId(); iterator.nextId(); // when IdRangeIterator subRange = iterator.nextIdBatch( 3 ).iterator(); // then assertEquals( 6, iterator.nextId() ); assertEquals( 3, subRange.nextId() ); assertEquals( 4, subRange.nextId() ); assertEquals( 5, subRange.nextId() ); assertEquals( VALUE_REPRESENTING_NULL, subRange.nextId() ); // when subRange = iterator.nextIdBatch( 3 ).iterator(); // then assertEquals( 10, iterator.nextId() ); assertEquals( 7, subRange.nextId() ); assertEquals( 8, subRange.nextId() ); assertEquals( 9, subRange.nextId() ); assertEquals( VALUE_REPRESENTING_NULL, subRange.nextId() ); } }
@Override public long nextId() { assert !closed; long id; while ( currentBatch == null || (id = currentBatch.nextId()) == VALUE_REPRESENTING_NULL ) { currentBatch = source.nextIdBatch( batchSize ).iterator(); } return id; }
private void storeLocally( IdAllocation allocation ) { setHighId( allocation.getHighestIdInUse() + 1 ); // high id is certainly bigger than the highest id in use this.idQueue = respectingHighId( allocation.getIdRange() ).iterator(); }