@Test public void testCopyWithConcurrentAccess() throws Exception { Map<String, ResolverResult> dirLayerMappings; try (FDBRecordContext context = database.openContext()) { dirLayerMappings = seedDirectoryLayer(context, primary, 50); } List<CompletableFuture<Void>> work = new ArrayList<>(); ResolverMappingReplicator replicator = new ResolverMappingReplicator(primary, 10); work.add(replicator.copyToAsync(replica)); Map<String, ResolverResult> concurrentlyAddedMappings = new ConcurrentHashMap<>(); for (int i = 0; i < 50; i++) { final String key = randomLetters(25); work.add(CompletableFuture.supplyAsync(() -> database.openContext()) .thenCompose(context -> primary.resolveWithMetadata(context.getTimer(), key, ResolverCreateHooks.getDefault()) .thenCompose(resolved -> { context.addAfterCommit(() -> concurrentlyAddedMappings.put(key, resolved)); return context.commitAsync(); }) ) ); } CompletableFuture.allOf(work.toArray(new CompletableFuture<?>[0])).join(); assertContainsMappings(replica, dirLayerMappings); assertContainsMappings(primary, concurrentlyAddedMappings); }
public CompletableFuture<Void> copyToAsync(@Nonnull final LocatableResolver replica) { if (!replica.getDatabase().equals(runner.getDatabase())) { throw new IllegalArgumentException("copy must be within same database"); } final LongAccumulator maxAccumulator = new LongAccumulator(Long::max, 0L); final AtomicInteger counter = new AtomicInteger(); return copyInternal(replica, maxAccumulator, counter) .thenCompose(ignore -> replica.setWindow(maxAccumulator.get())); }
ResolverMappingReplicator implements AutoCloseable { public CompletableFuture<Void> copyToAsync(@Nonnull final LocatableResolver replica) { if (!replica.getDatabase().equals(runner.getDatabase())) { throw new IllegalArgumentException("copy must be within same database"); } final LongAccumulator maxAccumulator = new LongAccumulator(Long::max, 0L); final AtomicInteger counter = new AtomicInteger(); return copyInternal(replica, maxAccumulator, counter) .thenCompose(ignore -> replica.setWindow(maxAccumulator.get())); } }
ResolverMappingReplicator implements AutoCloseable { public CompletableFuture<Void> copyToAsync(@Nonnull final LocatableResolver replica) { if (!replica.getDatabase().equals(runner.getDatabase())) { throw new IllegalArgumentException("copy must be within same database"); } final LongAccumulator maxAccumulator = new LongAccumulator(Long::max, 0L); final AtomicInteger counter = new AtomicInteger(); return copyInternal(replica, maxAccumulator, counter) .thenCompose(ignore -> replica.setWindow(maxAccumulator.get())); } ResolverMappingReplicator(@Nonnull LocatableResolver primary);  ResolverMappingReplicator(@Nonnull LocatableResolver primary,
                                     final int transactionRowLimit);  ResolverMappingReplicator(@Nonnull LocatableResolver primary,
                                     final int transactionRowLimit,
                                     final long transactionTimeLimitMillis); }
ResolverMappingReplicator implements AutoCloseable { public CompletableFuture<Void> copyToAsync(@Nonnull final LocatableResolver replica) { if (!replica.getDatabase().equals(runner.getDatabase())) { throw new IllegalArgumentException("copy must be within same database"); } final LongAccumulator maxAccumulator = new LongAccumulator(Long::max, 0L); final AtomicInteger counter = new AtomicInteger(); return copyInternal(replica, maxAccumulator, counter) .thenCompose(ignore -> replica.setWindow(maxAccumulator.get())); } ResolverMappingReplicator(@Nonnull LocatableResolver primary);  ResolverMappingReplicator(@Nonnull LocatableResolver primary,
                                     final int transactionRowLimit);  ResolverMappingReplicator(@Nonnull LocatableResolver primary,
                                     final int transactionRowLimit,
                                     final long transactionTimeLimitMillis); @Override void close(); void copyTo(LocatableResolver replica); CompletableFuture<Void> copyToAsync(@Nonnull final LocatableResolver replica); @Override String toString(); }
ResolverMappingReplicator implements AutoCloseable { public CompletableFuture<Void> copyToAsync(@Nonnull final LocatableResolver replica) { if (!replica.getDatabase().equals(runner.getDatabase())) { throw new IllegalArgumentException("copy must be within same database"); } final LongAccumulator maxAccumulator = new LongAccumulator(Long::max, 0L); final AtomicInteger counter = new AtomicInteger(); return copyInternal(replica, maxAccumulator, counter) .thenCompose(ignore -> replica.setWindow(maxAccumulator.get())); } ResolverMappingReplicator(@Nonnull LocatableResolver primary);  ResolverMappingReplicator(@Nonnull LocatableResolver primary,
                                     final int transactionRowLimit);  ResolverMappingReplicator(@Nonnull LocatableResolver primary,
                                     final int transactionRowLimit,
                                     final long transactionTimeLimitMillis); @Override void close(); void copyTo(LocatableResolver replica); CompletableFuture<Void> copyToAsync(@Nonnull final LocatableResolver replica); @Override String toString();  }