@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 ) ); } } }
public IdRangeIterator( IdRange idRange ) { this.defrag = idRange.getDefragIds(); this.start = idRange.getRangeStart(); this.length = idRange.getRangeLength(); }
@Override public long nextId() { long id; if ( batch == null || (id = batch.nextId()) == -1 ) { IdRange idRange = source.nextIdBatch( batchSize ); while ( IdValidator.hasReservedIdInRange( idRange.getRangeStart(), idRange.getRangeStart() + idRange.getRangeLength() ) ) { idRange = source.nextIdBatch( batchSize ); } batch = new IdRangeIterator( idRange ); id = batch.nextId(); } return id; }
private IdRange respectingHighId( IdRange idRange ) { int adjustment = 0; long originalRangeStart = idRange.getRangeStart(); if ( highId > originalRangeStart ) { adjustment = (int) (highId - originalRangeStart); } long rangeStart = max( this.highId, originalRangeStart ); int rangeLength = idRange.getRangeLength() - adjustment; if ( rangeLength <= 0 ) { throw new IllegalStateException( "IdAllocation state is probably corrupted or out of sync with the cluster. " + "Local highId is " + highId + " and allocation range is " + idRange ); } return new IdRange( idRange.getDefragIds(), rangeStart, rangeLength ); }
@Override public IdRange nextIdBatch( int size ) { while ( IdValidator.hasReservedIdInRange( nextId, nextId + size ) ) { nextId += size; } long startId = nextId; nextId += size; return new IdRange( EMPTY_LONG_ARRAY, startId, size ); }
private void acquireNextIdBatch() { IdAllocation allocation = acquirer.acquireIds( idType ); assert allocation.getIdRange().getRangeLength() > 0; log.debug( "Received id allocation " + allocation + " for " + idType ); storeLocally( allocation ); }
@Override public long nextId() { assert !closed; long id; while ( currentBatch == null || (id = currentBatch.nextId()) == VALUE_REPRESENTING_NULL ) { currentBatch = source.nextIdBatch( batchSize ).iterator(); } return id; }
@Override public synchronized IdRange nextIdBatch( int size ) { IdRange idBatch = getReusableIdBatch( size ); if ( idBatch.totalSize() > 0 ) { return idBatch; } IdRange range = idQueue.nextIdBatch( size ); if ( range.totalSize() == 0 ) { acquireNextIdBatch(); range = idQueue.nextIdBatch( size ); setHighId( range.getHighId() ); } return range; }
private IdRange respectingHighId( IdRange idRange ) { int adjustment = 0; long originalRangeStart = idRange.getRangeStart(); if ( highId > originalRangeStart ) { adjustment = (int) (highId - originalRangeStart); } long rangeStart = max( this.highId, originalRangeStart ); int rangeLength = idRange.getRangeLength() - adjustment; if ( rangeLength <= 0 ) { throw new IllegalStateException( "IdAllocation state is probably corrupted or out of sync with the cluster. " + "Local highId is " + highId + " and allocation range is " + idRange ); } return new IdRange( idRange.getDefragIds(), rangeStart, rangeLength ); } }
@Override public IdRange nextIdBatch( int batchSize ) { calls++; try { return new IdRange( EMPTY_LONG_ARRAY, nextId, batchSize ); } finally { nextId += batchSize; } }
@Override public long nextId() { long id; if ( batch == null || (id = batch.nextId()) == -1 ) { IdRange idRange = source.nextIdBatch( batchSize ); while ( IdValidator.hasReservedIdInRange( idRange.getRangeStart(), idRange.getRangeStart() + idRange.getRangeLength() ) ) { idRange = source.nextIdBatch( batchSize ); } batch = new IdRangeIterator( idRange ); id = batch.nextId(); } return id; }
@Override public synchronized long nextId() { long nextId = idQueue.next(); if ( nextId == VALUE_REPRESENTING_NULL ) { IdAllocation allocation; allocation = acquirer.acquireIds( idType ); assert allocation.getIdRange().getRangeLength() > 0; log.debug( "Received id allocation " + allocation + " for " + idType ); nextId = storeLocally( allocation ); } highId = max( highId, nextId + 1 ); return 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 assertNoReservedId( IdRange range ) { for ( long id : range.getDefragIds() ) { assertFalse( IdValidator.isReservedId( id ) ); } assertFalse( IdValidator.hasReservedIdInRange( range.getRangeStart(), range.getRangeStart() + range.getRangeLength() ) ); } }
@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() ); }
public IdRange getReusableIdBatch( int maxSize ) { long[] tmpIdArr = new long[maxSize]; int count = 0; while ( count < maxSize ) { long id = freeIdKeeper.getId(); if ( id == NO_RESULT ) { break; } tmpIdArr[count++] = id; } long[] defragIdArr = count == maxSize ? tmpIdArr : Arrays.copyOfRange( tmpIdArr, 0, count ); return new IdRange( defragIdArr, 0, 0 ); }
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(); }
public IdRangeIterator( IdRange idRange ) { this.defrag = idRange.getDefragIds(); this.start = idRange.getRangeStart(); this.length = idRange.getRangeLength(); }
@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() ); }
@Override public synchronized IdRange nextIdBatch( int size ) { assertStillOpen(); long[] reusableIds = idContainer.getReusableIds( size ); int sizeLeftForRange = size - reusableIds.length; long start = highId; setHighId( start + sizeLeftForRange ); return new IdRange( reusableIds, start, sizeLeftForRange ); }