@Test void testAllocationsParallelSeparateTransactions() { List<CompletableFuture<Pair<Long, String>>> allocationOperations = new ArrayList<>(); AtomicInteger count = new AtomicInteger(); for (int i = 0; i < 50; i++) { CompletableFuture<Pair<Long, String>> allocation = database.runAsync(context -> { HighContentionAllocator hca = new HighContentionAllocator(context, keySpace.path("test-path")); String storedValue = "allocate-" + count.getAndIncrement(); return hca.allocate(storedValue).thenApply(id -> Pair.of(id, storedValue)); }); allocationOperations.add(allocation); } Map<Long, String> allocated = AsyncUtil.getAll(allocationOperations).join().stream() .collect(Collectors.toMap(Pair::getLeft, Pair::getRight)); assertThat("all values are allocated", allocated.entrySet(), hasSize(50)); try (FDBRecordContext context = database.openContext()) { HighContentionAllocator hca = new HighContentionAllocator(context, keySpace.path("test-path")); validateAllocation(context, hca, allocated); } }
public CompletableFuture<Long> allocate(final String valueToStore) { final byte[] valueBytes = Tuple.from(valueToStore).pack(); return initialWindow() .thenCompose(initialWindow -> chooseWindow(initialWindow, false)) .thenCompose(window -> chooseCandidate(window, valueBytes)); }
HighContentionAllocator { public CompletableFuture<Long> allocate(final String valueToStore) { final byte[] valueBytes = Tuple.from(valueToStore).pack(); return initialWindow() .thenCompose(initialWindow -> chooseWindow(initialWindow, false)) .thenCompose(window -> chooseCandidate(window, valueBytes)); } }
HighContentionAllocator { public CompletableFuture<Long> allocate(final String valueToStore) { final byte[] valueBytes = Tuple.from(valueToStore).pack(); return initialWindow() .thenCompose(initialWindow -> chooseWindow(initialWindow, false)) .thenCompose(window -> chooseCandidate(window, valueBytes)); } HighContentionAllocator(@Nonnull FDBRecordContext context,
                                   @Nonnull KeySpacePath basePath);  HighContentionAllocator(@Nonnull FDBRecordContext context,
                                   @Nonnull KeySpacePath basePath,
                                   @Nonnull Function<Long, CompletableFuture<Boolean>> candidateCheck);  HighContentionAllocator(@Nonnull FDBRecordContext context,
                                   @Nonnull Subspace basePathSubspace,
                                   @Nonnull Function<Long, CompletableFuture<Boolean>> candidateCheck);  HighContentionAllocator(@Nonnull FDBRecordContext context,
                                   @Nonnull Subspace counterSubspace,
                                   @Nonnull Subspace allocationSubspace); protected  HighContentionAllocator(@Nonnull FDBRecordContext context,
                                      @Nonnull Subspace counterSubspace,
                                      @Nonnull Subspace allocationSubspace,
                                      @Nonnull Function<Long, CompletableFuture<Boolean>> candidateCheck); }
HighContentionAllocator { public CompletableFuture<Long> allocate(final String valueToStore) { final byte[] valueBytes = Tuple.from(valueToStore).pack(); return initialWindow() .thenCompose(initialWindow -> chooseWindow(initialWindow, false)) .thenCompose(window -> chooseCandidate(window, valueBytes)); } HighContentionAllocator(@Nonnull FDBRecordContext context,
                                   @Nonnull KeySpacePath basePath);  HighContentionAllocator(@Nonnull FDBRecordContext context,
                                   @Nonnull KeySpacePath basePath,
                                   @Nonnull Function<Long, CompletableFuture<Boolean>> candidateCheck);  HighContentionAllocator(@Nonnull FDBRecordContext context,
                                   @Nonnull Subspace basePathSubspace,
                                   @Nonnull Function<Long, CompletableFuture<Boolean>> candidateCheck);  HighContentionAllocator(@Nonnull FDBRecordContext context,
                                   @Nonnull Subspace counterSubspace,
                                   @Nonnull Subspace allocationSubspace); protected  HighContentionAllocator(@Nonnull FDBRecordContext context,
                                      @Nonnull Subspace counterSubspace,
                                      @Nonnull Subspace allocationSubspace,
                                      @Nonnull Function<Long, CompletableFuture<Boolean>> candidateCheck); static HighContentionAllocator forRoot(@Nonnull FDBRecordContext context,
                                                  @Nonnull Subspace counterSubspace,
                                                  @Nonnull Subspace allocationSubspace); static HighContentionAllocator forRoot(@Nonnull FDBRecordContext context, @Nonnull KeySpacePath basePath); @VisibleForTesting Subspace getAllocationSubspace(); CompletableFuture<Long> allocate(final String valueToStore); void setWindow(long count); void forceAllocate(@Nonnull String key, @Nonnull Long value); }
HighContentionAllocator { public CompletableFuture<Long> allocate(final String valueToStore) { final byte[] valueBytes = Tuple.from(valueToStore).pack(); return initialWindow() .thenCompose(initialWindow -> chooseWindow(initialWindow, false)) .thenCompose(window -> chooseCandidate(window, valueBytes)); } HighContentionAllocator(@Nonnull FDBRecordContext context,
                                   @Nonnull KeySpacePath basePath);  HighContentionAllocator(@Nonnull FDBRecordContext context,
                                   @Nonnull KeySpacePath basePath,
                                   @Nonnull Function<Long, CompletableFuture<Boolean>> candidateCheck);  HighContentionAllocator(@Nonnull FDBRecordContext context,
                                   @Nonnull Subspace basePathSubspace,
                                   @Nonnull Function<Long, CompletableFuture<Boolean>> candidateCheck);  HighContentionAllocator(@Nonnull FDBRecordContext context,
                                   @Nonnull Subspace counterSubspace,
                                   @Nonnull Subspace allocationSubspace); protected  HighContentionAllocator(@Nonnull FDBRecordContext context,
                                      @Nonnull Subspace counterSubspace,
                                      @Nonnull Subspace allocationSubspace,
                                      @Nonnull Function<Long, CompletableFuture<Boolean>> candidateCheck); static HighContentionAllocator forRoot(@Nonnull FDBRecordContext context,
                                                  @Nonnull Subspace counterSubspace,
                                                  @Nonnull Subspace allocationSubspace); static HighContentionAllocator forRoot(@Nonnull FDBRecordContext context, @Nonnull KeySpacePath basePath); @VisibleForTesting Subspace getAllocationSubspace(); CompletableFuture<Long> allocate(final String valueToStore); void setWindow(long count); void forceAllocate(@Nonnull String key, @Nonnull Long value);  }