public static void handedOutTimestamps(TimestampRange range) { long count = range.getUpperBound() - range.getLowerBound() + 1L; logger.trace("Handing out {} timestamps, taking us to {}.", SafeArg.of("count", count), SafeArg.of("rangeUpperBound", range.getUpperBound())); }
public TimestampRange incrementBy(long delta) { TimestampRange range = timestamp.incrementBy(delta); upperLimit.increaseToAtLeast(range.getUpperBound()); return range; }
long candidate = range.getLowerBound() + shift; return range.getUpperBound() >= candidate ? OptionalLong.of(candidate) : OptionalLong.empty();
@Test public void timestampRangesAreReturnedInNonOverlappingOrder() { TimestampRange timestampRange1 = timestampService.getFreshTimestamps(10); TimestampRange timestampRange2 = timestampService.getFreshTimestamps(10); long firstUpperBound = timestampRange1.getUpperBound(); long secondLowerBound = timestampRange2.getLowerBound(); Assertions.assertThat(firstUpperBound).isLessThan(secondLowerBound); }
@Test public void shouldIncreaseTheValueToAHigherNumber() { TimestampRange range = timestamp.incrementBy(10); assertThat(range.getUpperBound(), is(INITIAL_TIMESTAMP + 10)); }
@VisibleForTesting static Consumer<List<BatchElement<Integer, TimestampRange>>> consumer(TimestampService delegate) { return batch -> { long totalTimestamps = batch.stream().mapToLong(BatchElement::argument).reduce(0, Math::addExact); long startInclusive = 0; long endExclusive = 0; for (BatchElement<Integer, TimestampRange> element : batch) { int timestampsRequired = element.argument(); if (element.argument() <= endExclusive - startInclusive) { element.result().set(createExclusiveRange(startInclusive, startInclusive + timestampsRequired)); startInclusive += timestampsRequired; totalTimestamps -= timestampsRequired; } else { TimestampRange requested = getFreshTimestampsFromDelegate( delegate, Ints.saturatedCast(totalTimestamps)); startInclusive = requested.getLowerBound(); endExclusive = Math.addExact(requested.getUpperBound(), 1); int toTake = Math.min(Ints.checkedCast(endExclusive - startInclusive), timestampsRequired); element.result().set(createExclusiveRange(startInclusive, startInclusive + toTake)); startInclusive += toTake; totalTimestamps -= timestampsRequired; } } }; }
@Test public void handleConcurrentlyIncreasingTheValue() throws InterruptedException { for (int i = 0; i < 100; i++) { executor.submit(() -> timestamp.incrementBy(1)); } waitForExecutorToFinish(); assertThat(timestamp.incrementBy(1).getUpperBound(), is(INITIAL_TIMESTAMP + 101)); }
@Test public void canRequestTimestampRangeWithGetFreshTimestamps() { int expectedNumTimestamps = 5; TimestampRange range = timestampService.getFreshTimestamps(expectedNumTimestamps); Assertions.assertThat((int) range.size()) .withFailMessage("Expected %d timestamps, got %d timestamps. (The returned range was: %d-%d)", expectedNumTimestamps, range.size(), range.getLowerBound(), range.getUpperBound()) .isGreaterThanOrEqualTo(1) .isLessThanOrEqualTo(expectedNumTimestamps); }
@Test public void shouldIncreaseUpperLimitWhenHandingOutNewTimestamps() { assertThat( timestamp.incrementBy(INITIAL_REMAINING_TIMESTAMPS + 10).getUpperBound(), is(UPPER_LIMIT + 10)); verify(upperLimit).increaseToAtLeast(UPPER_LIMIT + 10); }
private void punch(TestAtlasDbServices services, TimestampService tss, Clock clock) { // this is a really hacky way of forcing a punch to test the datetime output Uninterruptibles.sleepUninterruptibly(2, TimeUnit.MILLISECONDS); long punchTs = tss.getFreshTimestamps(1000).getUpperBound(); PuncherStore puncherStore = KeyValueServicePuncherStore.create(services.getKeyValueService()); Puncher puncher = SimplePuncher.create(puncherStore, clock, Suppliers.ofInstance(AtlasDbConstants.DEFAULT_TRANSACTION_READ_TIMEOUT)); puncher.punch(punchTs); Uninterruptibles.sleepUninterruptibly(2, TimeUnit.MILLISECONDS); }
@Test public void shouldHandOutNonOverLappingTimestampRanges() { TimestampRange first = timestamp.incrementBy(10); TimestampRange second = timestamp.incrementBy(10); assertThat(first.getUpperBound(), is(lessThan(second.getLowerBound()))); }
public static void handedOutTimestamps(TimestampRange range) { long count = range.getUpperBound() - range.getLowerBound() + 1L; logger.trace("Handing out {} timestamps, taking us to {}.", SafeArg.of("count", count), SafeArg.of("rangeUpperBound", range.getUpperBound())); }
private void runAndVerifyCli(Verifier verifier) throws Exception { try (SingleBackendCliTestRunner runner = makeRunner(cliArgs.toArray(new String[0]))) { TestAtlasDbServices services = runner.connect(moduleFactory); LockService lockService = services.getLockService(); TimestampService tss = services.getTimestampService(); LockClient client = services.getTestLockClient(); Clock clock = GlobalClock.create(lockService); long prePunch = clock.getTimeMillis(); punch(services, tss, clock); long postPunch = clock.getTimeMillis(); long immutableTs = tss.getFreshTimestamp(); LockRequest request = LockRequest.builder(ImmutableSortedMap.of(lock, LockMode.WRITE)) .withLockedInVersionId(immutableTs) .doNotBlock() .build(); LockRefreshToken token = lockService.lock(client.getClientId(), request); long lastFreshTs = tss.getFreshTimestamps(1000).getUpperBound(); verifier.verify(runner, tss, immutableTs, prePunch, postPunch, lastFreshTs, true); lockService.unlock(token); lastFreshTs = tss.getFreshTimestamps(1000).getUpperBound(); // there are no locks so we now expect immutable to just be a fresh runner.freshCommand(); verifier.verify(runner, tss, immutableTs, prePunch, postPunch, lastFreshTs, false); } }
public TimestampRange incrementBy(long delta) { TimestampRange range = timestamp.incrementBy(delta); upperLimit.increaseToAtLeast(range.getUpperBound()); return range; }
long candidate = range.getLowerBound() + shift; return range.getUpperBound() >= candidate ? OptionalLong.of(candidate) : OptionalLong.empty();
@Test public void timestampRangesAreReturnedInNonOverlappingOrder() { TimestampRange timestampRange1 = timestampService.getFreshTimestamps(10); TimestampRange timestampRange2 = timestampService.getFreshTimestamps(10); long firstUpperBound = timestampRange1.getUpperBound(); long secondLowerBound = timestampRange2.getLowerBound(); Assertions.assertThat(firstUpperBound).isLessThan(secondLowerBound); }
@VisibleForTesting static Consumer<List<BatchElement<Integer, TimestampRange>>> consumer(TimestampService delegate) { return batch -> { long totalTimestamps = batch.stream().mapToLong(BatchElement::argument).reduce(0, Math::addExact); long startInclusive = 0; long endExclusive = 0; for (BatchElement<Integer, TimestampRange> element : batch) { int timestampsRequired = element.argument(); if (element.argument() <= endExclusive - startInclusive) { element.result().set(createExclusiveRange(startInclusive, startInclusive + timestampsRequired)); startInclusive += timestampsRequired; totalTimestamps -= timestampsRequired; } else { TimestampRange requested = getFreshTimestampsFromDelegate( delegate, Ints.saturatedCast(totalTimestamps)); startInclusive = requested.getLowerBound(); endExclusive = Math.addExact(requested.getUpperBound(), 1); int toTake = Math.min(Ints.checkedCast(endExclusive - startInclusive), timestampsRequired); element.result().set(createExclusiveRange(startInclusive, startInclusive + toTake)); startInclusive += toTake; totalTimestamps -= timestampsRequired; } } }; }
@Test public void canRequestTimestampRangeWithGetFreshTimestamps() { int expectedNumTimestamps = 5; TimestampRange range = timestampService.getFreshTimestamps(expectedNumTimestamps); Assertions.assertThat((int) range.size()) .withFailMessage("Expected %d timestamps, got %d timestamps. (The returned range was: %d-%d)", expectedNumTimestamps, range.size(), range.getLowerBound(), range.getUpperBound()) .isGreaterThanOrEqualTo(1) .isLessThanOrEqualTo(expectedNumTimestamps); }