From 154000e2c35a0868593c2df2dca59a85fd27578d Mon Sep 17 00:00:00 2001 From: Alec Grieser Date: Mon, 11 Dec 2017 08:54:35 -0800 Subject: [PATCH 01/10] move most old-style closures to Java 8-style closures --- .../main/com/apple/foundationdb/Database.java | 8 +- .../main/com/apple/foundationdb/FDB.java | 78 +- .../com/apple/foundationdb/FDBDatabase.java | 10 +- .../apple/foundationdb/FDBTransaction.java | 6 +- .../com/apple/foundationdb/LocalityUtil.java | 11 +- .../com/apple/foundationdb/RangeQuery.java | 4 +- .../foundationdb/ReadTransactionContext.java | 2 +- .../com/apple/foundationdb/Transaction.java | 2 +- .../foundationdb/TransactionContext.java | 2 +- .../apple/foundationdb/async/AsyncUtil.java | 80 +- .../directory/DirectoryLayer.java | 740 +++++++----------- .../test/AsyncDirectoryExtension.java | 440 +++-------- .../foundationdb/test/AsyncStackTester.java | 42 +- 13 files changed, 521 insertions(+), 904 deletions(-) diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/Database.java b/bindings/java/src-completable/main/com/apple/foundationdb/Database.java index 7a7aeeda9d..03eaa52196 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/Database.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/Database.java @@ -117,7 +117,7 @@ public interface Database extends Disposable, TransactionContext { */ @Override default CompletableFuture readAsync( - Function> retryable) { + Function> retryable) { return readAsync(retryable, getExecutor()); } @@ -133,7 +133,7 @@ public interface Database extends Disposable, TransactionContext { * @see #readAsync(Function) */ CompletableFuture readAsync( - Function> retryable, Executor e); + Function> retryable, Executor e); /** * Runs a transactional function against this {@code Database} with retry logic. @@ -195,7 +195,7 @@ public interface Database extends Disposable, TransactionContext { */ @Override default CompletableFuture runAsync( - Function> retryable) { + Function> retryable) { return runAsync(retryable, getExecutor()); } @@ -211,5 +211,5 @@ public interface Database extends Disposable, TransactionContext { * @see #run(Function) */ CompletableFuture runAsync( - Function> retryable, Executor e); + Function> retryable, Executor e); } diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/FDB.java b/bindings/java/src-completable/main/com/apple/foundationdb/FDB.java index 42ac857eab..cfa12036a6 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/FDB.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/FDB.java @@ -103,21 +103,8 @@ public class FDB { private FDB(int apiVersion) { this.apiVersion = apiVersion; - options = new NetworkOptions(new OptionConsumer() { - @Override - public void setOption(int code, byte[] parameter) { - Network_setOption(code, parameter); - } - }); - - Runtime.getRuntime().addShutdownHook(new Thread( - new Runnable(){ - @Override - public void run() { - FDB.this.stopNetwork(); - } - } - )); + options = new NetworkOptions(this::Network_setOption); + Runtime.getRuntime().addShutdownHook(new Thread(this::stopNetwork)); } /** @@ -345,39 +332,38 @@ public class FDB { Network_setup(); netStarted = true; - e.execute(new Runnable() { - @Override - public void run() { - boolean acquired = false; - try { - while(!acquired) { - try { - // make attempt to avoid a needless deadlock - synchronized (FDB.this) { - if(netStopped) { - return; - } - } + e.execute(() -> { + boolean acquired = false; + try { + while(!acquired) { + try { + // make attempt to avoid a needless deadlock + synchronized (FDB.this) { + if(netStopped) { + return; + } + } - netRunning.acquire(); - acquired = true; - } catch(InterruptedException e) {} + netRunning.acquire(); + acquired = true; + } catch(InterruptedException err) { + // Swallow thread interruption } - try { - Network_run(); - } catch (Throwable t) { - System.err.println("Unhandled error in FoundationDB network thread: " + t.getMessage()); - // eat this error. we have nowhere to send it. - } - } finally { - if(acquired) { - netRunning.release(); - } - synchronized (FDB.this) { - netStopped = true; - } - } - } + } + try { + Network_run(); + } catch (Throwable t) { + System.err.println("Unhandled error in FoundationDB network thread: " + t.getMessage()); + // eat this error. we have nowhere to send it. + } + } finally { + if(acquired) { + netRunning.release(); + } + synchronized (FDB.this) { + netStopped = true; + } + } }); } diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/FDBDatabase.java b/bindings/java/src-completable/main/com/apple/foundationdb/FDBDatabase.java index a1b65c51d3..dc23e93703 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/FDBDatabase.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/FDBDatabase.java @@ -67,18 +67,18 @@ class FDBDatabase extends DefaultDisposableImpl implements Database, Disposable, } @Override - public CompletableFuture runAsync(final Function> retryable, Executor e) { + public CompletableFuture runAsync(final Function> retryable, Executor e) { final AtomicReference trRef = new AtomicReference<>(createTransaction(e)); final AtomicReference returnValue = new AtomicReference<>(); return AsyncUtil.whileTrue(() -> { CompletableFuture process = AsyncUtil.applySafely(retryable, trRef.get()); - return process.thenComposeAsync(returnVal -> + return AsyncUtil.composeHandleAsync(process.thenComposeAsync(returnVal -> trRef.get().commit().thenApply(o -> { returnValue.set(returnVal); return false; }) - , e).handleAsync((value, t) -> { + , e), (value, t) -> { if(t == null) return CompletableFuture.completedFuture(value); if(!(t instanceof RuntimeException)) @@ -87,7 +87,7 @@ class FDBDatabase extends DefaultDisposableImpl implements Database, Disposable, trRef.set(newTr); return true; }); - }, e).thenCompose(x -> x); + }, e); }, e) .thenApply(o -> returnValue.get()) .whenComplete((v, t) -> trRef.get().dispose()); @@ -95,7 +95,7 @@ class FDBDatabase extends DefaultDisposableImpl implements Database, Disposable, @Override public CompletableFuture readAsync( - Function> retryable, Executor e) { + Function> retryable, Executor e) { return this.runAsync(retryable, e); } diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/FDBTransaction.java b/bindings/java/src-completable/main/com/apple/foundationdb/FDBTransaction.java index 8c490aba8f..1576eade78 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/FDBTransaction.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/FDBTransaction.java @@ -137,7 +137,7 @@ class FDBTransaction extends DefaultDisposableImpl implements Disposable, Transa @Override public CompletableFuture readAsync( - Function> retryable) { + Function> retryable) { return AsyncUtil.applySafely(retryable, this); } @@ -356,7 +356,7 @@ class FDBTransaction extends DefaultDisposableImpl implements Disposable, Transa @Override public CompletableFuture runAsync( - Function> retryable) { + Function> retryable) { return AsyncUtil.applySafely(retryable, this); } @@ -367,7 +367,7 @@ class FDBTransaction extends DefaultDisposableImpl implements Disposable, Transa @Override public CompletableFuture readAsync( - Function> retryable) { + Function> retryable) { return AsyncUtil.applySafely(retryable, this); } diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/LocalityUtil.java b/bindings/java/src-completable/main/com/apple/foundationdb/LocalityUtil.java index 6e2784eb32..b4bc7d9859 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/LocalityUtil.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/LocalityUtil.java @@ -24,10 +24,12 @@ import java.nio.charset.Charset; import java.util.Arrays; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; +import java.util.concurrent.Executor; import java.util.function.BiFunction; import com.apple.foundationdb.async.AsyncIterable; import com.apple.foundationdb.async.AsyncIterator; +import com.apple.foundationdb.async.AsyncUtil; import com.apple.foundationdb.async.DisposableAsyncIterator; import com.apple.foundationdb.tuple.ByteArrayUtil; @@ -137,7 +139,7 @@ public class LocalityUtil { firstGet = tr.getRange(keyServersForKey(begin), keyServersForKey(end)); block = firstGet.iterator(); - nextFuture = block.onHasNext().handleAsync(handler, tr.getExecutor()).thenCompose(x -> x); + nextFuture = AsyncUtil.composeHandleAsync(block.onHasNext(), handler, tr.getExecutor()); disposed = false; } @@ -161,7 +163,7 @@ public class LocalityUtil { block = tr.getRange( keyServersForKey(begin), keyServersForKey(end)).iterator(); - nextFuture = block.onHasNext().handleAsync(handler, tr.getExecutor()).thenCompose(x -> x); + nextFuture = AsyncUtil.composeHandleAsync(block.onHasNext(), handler, tr.getExecutor()); return nextFuture; } @@ -174,8 +176,9 @@ public class LocalityUtil { if(o instanceof FDBException) { FDBException err = (FDBException) o; if(err.getCode() == 1007 && !Arrays.equals(begin, lastBegin)) { + Executor executor = BoundaryIterator.this.tr.getExecutor(); BoundaryIterator.this.tr.dispose(); - BoundaryIterator.this.tr = BoundaryIterator.this.tr.getDatabase().createTransaction(); + BoundaryIterator.this.tr = BoundaryIterator.this.tr.getDatabase().createTransaction(executor); return restartGet(); } } @@ -200,7 +203,7 @@ public class LocalityUtil { byte[] key = o.getKey(); byte[] suffix = Arrays.copyOfRange(key, 13, key.length); BoundaryIterator.this.begin = ByteArrayUtil.join(suffix, new byte[] { (byte)0 }); - nextFuture = block.onHasNext().handleAsync(handler, tr.getExecutor()).thenCompose(x -> x); + nextFuture = AsyncUtil.composeHandleAsync(block.onHasNext(), handler, tr.getExecutor()); return suffix; } diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/RangeQuery.java b/bindings/java/src-completable/main/com/apple/foundationdb/RangeQuery.java index addf385afe..8cd693b7a2 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/RangeQuery.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/RangeQuery.java @@ -234,14 +234,14 @@ class RangeQuery implements AsyncIterable, Iterable { // We have a chunk and are still working though it if(index < chunk.values.size()) { - return CompletableFuture.completedFuture(true); + return AsyncUtil.READY_TRUE; } // If we are at the end of the current chunk there is either: // - no more data -or- // - we are already fetching the next block return mainChunkIsTheLast() ? - CompletableFuture.completedFuture(false) : + AsyncUtil.READY_FALSE : nextFuture; } diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/ReadTransactionContext.java b/bindings/java/src-completable/main/com/apple/foundationdb/ReadTransactionContext.java index 187525350f..3213977e02 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/ReadTransactionContext.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/ReadTransactionContext.java @@ -62,7 +62,7 @@ public interface ReadTransactionContext { * to {@code retryable} */ CompletableFuture readAsync( - Function> retryable); + Function> retryable); /** * Retrieves the {@link Executor} used by this {@code TransactionContext} when running diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/Transaction.java b/bindings/java/src-completable/main/com/apple/foundationdb/Transaction.java index de41c3aad4..56ec473821 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/Transaction.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/Transaction.java @@ -367,6 +367,6 @@ public interface Transaction extends Disposable, ReadTransaction, TransactionCon */ @Override CompletableFuture runAsync( - Function> retryable); + Function> retryable); } diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/TransactionContext.java b/bindings/java/src-completable/main/com/apple/foundationdb/TransactionContext.java index 91ecf16789..8cd5e0c45e 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/TransactionContext.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/TransactionContext.java @@ -59,5 +59,5 @@ public interface TransactionContext extends ReadTransactionContext { * @return a {@code CompletableFuture} that will be set to the value returned by the last call * to {@code retryable} */ - CompletableFuture runAsync(Function> retryable); + CompletableFuture runAsync(Function> retryable); } \ No newline at end of file diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/async/AsyncUtil.java b/bindings/java/src-completable/main/com/apple/foundationdb/async/AsyncUtil.java index 27da073c66..1149041090 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/async/AsyncUtil.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/async/AsyncUtil.java @@ -29,6 +29,7 @@ import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; import java.util.function.BiFunction; +import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; @@ -36,6 +37,10 @@ import java.util.function.Supplier; * Provided utilities for using and manipulating {@link CompletableFuture}s. */ public class AsyncUtil { + public static final CompletableFuture DONE = CompletableFuture.completedFuture(null); + public static final CompletableFuture READY_TRUE = CompletableFuture.completedFuture(true); + public static final CompletableFuture READY_FALSE = CompletableFuture.completedFuture(false); + /** * Run {@code Function} {@code func}, returning all caught exceptions as a * {@code CompletableFuture} in an error state. @@ -46,7 +51,7 @@ public class AsyncUtil { * @return the output of {@code func}, or a {@code CompletableFuture} carrying any exception * caught in the process. */ - public static CompletableFuture applySafely( Function> func, I value ) { + public static CompletableFuture applySafely( Function> func, I value ) { try { return func.apply(value); } catch (RuntimeException e) { @@ -56,6 +61,31 @@ public class AsyncUtil { } } + public static CompletableFuture forEach(final AsyncIterable iterable, final Consumer consumer) { + return forEach(iterable.iterator(), consumer); + } + + public static CompletableFuture forEach(final AsyncIterable iterable, final Consumer consumer, final Executor executor) { + return forEach(iterable.iterator(), consumer, executor); + } + + public static CompletableFuture forEach(final AsyncIterator iterator, final Consumer consumer) { + return forEach(iterator, consumer, DEFAULT_EXECUTOR); + } + + public static CompletableFuture forEach(final AsyncIterator iterator, final Consumer consumer, final Executor executor) { + return iterator.onHasNext().thenComposeAsync(hasAny -> { + if (hasAny) { + return whileTrue(() -> { + consumer.accept(iterator.next()); + return iterator.onHasNext(); + }, executor); + } else { + return DONE; + } + }, executor); + } + /** * Iterates over a set of items and returns the result as a list. * @@ -104,18 +134,11 @@ public class AsyncUtil { */ public static CompletableFuture> collect(final AsyncIterator iterator, final Executor executor) { final List accumulator = new LinkedList<>(); + return forEach(iterator, accumulator::add, executor).thenApply(ignore -> accumulator); + } - // The condition of the while loop is simply "onHasNext()" returning true - Supplier> condition = () -> - iterator.onHasNext().thenApply(hasNext -> { - if(hasNext) { - accumulator.add(iterator.next()); - } - return hasNext; - }); - - CompletableFuture complete = whileTrue(condition, executor); - return tag(complete, accumulator); + public static AsyncIterable mapIterable(final AsyncIterable iterable, final Function func) { + return mapIterable(iterable, func, DEFAULT_EXECUTOR); } /** @@ -127,7 +150,7 @@ public class AsyncUtil { * @return a new iterable with each element mapped to a different value */ public static AsyncIterable mapIterable(final AsyncIterable iterable, - final Function func) { + final Function func, final Executor executor) { return new AsyncIterable() { @Override public AsyncIterator iterator() { @@ -136,12 +159,8 @@ public class AsyncUtil { @Override public CompletableFuture> asList() { - return iterable.asList().thenApply(result -> { - ArrayList out = new ArrayList<>(result.size()); - for(V in : result) - out.add(func.apply(in)); - return out; - }); + final List accumulator = new LinkedList<>(); + return tag(AsyncUtil.forEach(iterable, value -> accumulator.add(func.apply(value))), accumulator); } }; } @@ -354,8 +373,7 @@ public class AsyncUtil { * @return a new {@link CompletableFuture} that is set when {@code task} is ready. */ public static CompletableFuture whenReady(CompletableFuture task) { - return task.thenApply(o -> (Void)null) - .exceptionally(o -> null); + return task.handle((v, t) -> null); } public static CompletableFuture composeExceptionally(CompletableFuture task, Function> fn) { @@ -369,6 +387,18 @@ public class AsyncUtil { }); } + public static CompletableFuture composeHandle(CompletableFuture future, BiFunction> fn) { + return future.handle(fn).thenCompose(Function.identity()); + } + + public static CompletableFuture composeHandleAsync(CompletableFuture future, BiFunction> fn) { + return composeHandleAsync(future, fn, DEFAULT_EXECUTOR); + } + + public static CompletableFuture composeHandleAsync(CompletableFuture future, BiFunction> fn, Executor executor) { + return future.handleAsync(fn, executor).thenCompose(Function.identity()); + } + /** * Collects the results of many asynchronous processes into one asynchronous output. If * any of the tasks returns an error, the output is set to that error. @@ -379,7 +409,7 @@ public class AsyncUtil { */ public static CompletableFuture> getAll(final Collection> tasks) { return whenAll(tasks).thenApply(unused -> { - List result = new ArrayList<>(); + List result = new ArrayList<>(tasks.size()); for(CompletableFuture f : tasks) { assert(f.isDone()); result.add(f.getNow(null)); @@ -411,8 +441,7 @@ public class AsyncUtil { * @return a signal that will be set when any of the {@code CompletableFuture}s are done */ public static CompletableFuture whenAny(final Collection> input) { - @SuppressWarnings("unchecked") - CompletableFuture[] array = (CompletableFuture[]) input.toArray(new CompletableFuture[input.size()]); + CompletableFuture[] array = input.toArray(new CompletableFuture[input.size()]); CompletableFuture anyOf = CompletableFuture.anyOf(array); return success(anyOf); } @@ -427,8 +456,7 @@ public class AsyncUtil { * @return a signal that will be set when all of the {@code CompletableFuture}s are done */ public static CompletableFuture whenAll(final Collection> input) { - @SuppressWarnings("unchecked") - CompletableFuture[] array = (CompletableFuture[]) input.toArray(new CompletableFuture[input.size()]); + CompletableFuture[] array = input.toArray(new CompletableFuture[input.size()]); return CompletableFuture.allOf(array); } diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/directory/DirectoryLayer.java b/bindings/java/src-completable/main/com/apple/foundationdb/directory/DirectoryLayer.java index d6ea090237..ef078b8a97 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/directory/DirectoryLayer.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/directory/DirectoryLayer.java @@ -30,7 +30,6 @@ import java.util.List; import java.util.Random; import java.util.concurrent.CompletableFuture; import java.util.function.Function; -import java.util.function.Supplier; import com.apple.foundationdb.KeyValue; import com.apple.foundationdb.MutationType; @@ -308,12 +307,7 @@ public class DirectoryLayer implements Directory */ @Override public CompletableFuture createOrOpen(TransactionContext tcx, final List path, final byte[] layer) { - return tcx.runAsync(new Function>() { - @Override - public CompletableFuture apply(Transaction tr) { - return createOrOpenInternal(tr, tr, path, layer, null, true, true); - } - }); + return tcx.runAsync(tr -> createOrOpenInternal(tr, tr, path, layer, null, true, true)); } /** @@ -334,12 +328,7 @@ public class DirectoryLayer implements Directory */ @Override public CompletableFuture open(ReadTransactionContext tcx, final List path, final byte[] layer) { - return tcx.readAsync(new Function>() { - @Override - public CompletableFuture apply(ReadTransaction rtr) { - return createOrOpenInternal(rtr, null, path, layer, null, false, true); - } - }); + return tcx.readAsync(rtr -> createOrOpenInternal(rtr, null, path, layer, null, false, true)); } /** @@ -361,12 +350,7 @@ public class DirectoryLayer implements Directory */ @Override public CompletableFuture create(TransactionContext tcx, final List path, final byte[] layer, final byte[] prefix) { - return tcx.runAsync(new Function>() { - @Override - public CompletableFuture apply(Transaction tr) { - return createOrOpenInternal(tr, tr, path, layer, prefix, true, false); - } - }); + return tcx.runAsync(tr -> createOrOpenInternal(tr, tr, path, layer, prefix, true, false)); } /** @@ -384,7 +368,7 @@ public class DirectoryLayer implements Directory */ @Override public CompletableFuture moveTo(TransactionContext tcx, List newAbsolutePath) { - CompletableFuture future = new CompletableFuture(); + CompletableFuture future = new CompletableFuture<>(); future.completeExceptionally(new DirectoryMoveException("The root directory cannot be moved.", path, newAbsolutePath)); return future; } @@ -422,71 +406,51 @@ public class DirectoryLayer implements Directory */ @Override public CompletableFuture move(final TransactionContext tcx, final List oldPath, final List newPath) { - final List oldPathCopy = new ArrayList(oldPath); - final List newPathCopy = new ArrayList(newPath); + final List oldPathCopy = new ArrayList<>(oldPath); + final List newPathCopy = new ArrayList<>(newPath); - return tcx.runAsync(new Function>() { - @Override - public CompletableFuture apply(final Transaction tr) { - return checkOrWriteVersion(tr) - .thenComposeAsync(new Function>>() { - @Override - public CompletableFuture> apply(Void ignore) { - if(oldPathCopy.size() <= newPathCopy.size() && oldPathCopy.equals(newPathCopy.subList(0, oldPathCopy.size()))) - throw new DirectoryMoveException("The destination directory cannot be a subdirectory of the source directory.", toAbsolutePath(oldPathCopy), toAbsolutePath(newPathCopy)); + return tcx.runAsync(tr -> checkOrWriteVersion(tr).thenComposeAsync(ignore -> { + if(oldPathCopy.size() <= newPathCopy.size() && oldPathCopy.equals(newPathCopy.subList(0, oldPathCopy.size()))) + throw new DirectoryMoveException("The destination directory cannot be a subdirectory of the source directory.", toAbsolutePath(oldPathCopy), toAbsolutePath(newPathCopy)); - ArrayList> futures = new ArrayList>(); - futures.add(new NodeFinder(oldPathCopy).find(tr).thenComposeAsync(new NodeMetadataLoader(tr), tr.getExecutor())); - futures.add(new NodeFinder(newPathCopy).find(tr).thenComposeAsync(new NodeMetadataLoader(tr), tr.getExecutor())); + ArrayList> futures = new ArrayList<>(); + futures.add(new NodeFinder(oldPathCopy).find(tr).thenComposeAsync(new NodeMetadataLoader(tr), tr.getExecutor())); + futures.add(new NodeFinder(newPathCopy).find(tr).thenComposeAsync(new NodeMetadataLoader(tr), tr.getExecutor())); - return AsyncUtil.getAll(futures); - } - }, tr.getExecutor()) - .thenCompose(new Function, CompletableFuture>() { - @Override - public CompletableFuture apply(List nodes) { - final Node oldNode = nodes.get(0); - final Node newNode = nodes.get(1); + return AsyncUtil.getAll(futures); + }, tr.getExecutor()) + .thenComposeAsync(nodes -> { + final Node oldNode = nodes.get(0); + final Node newNode = nodes.get(1); - if(!oldNode.exists()) - throw new NoSuchDirectoryException(toAbsolutePath(oldPathCopy)); + if(!oldNode.exists()) + throw new NoSuchDirectoryException(toAbsolutePath(oldPathCopy)); - if(oldNode.isInPartition(false) || newNode.isInPartition(false)) { - if(!oldNode.isInPartition(false) || !newNode.isInPartition(false) || !oldNode.path.equals(newNode.path)) - throw new DirectoryMoveException("Cannot move between partitions.", toAbsolutePath(oldPathCopy), toAbsolutePath(newPathCopy)); + if(oldNode.isInPartition(false) || newNode.isInPartition(false)) { + if(!oldNode.isInPartition(false) || !newNode.isInPartition(false) || !oldNode.path.equals(newNode.path)) + throw new DirectoryMoveException("Cannot move between partitions.", toAbsolutePath(oldPathCopy), toAbsolutePath(newPathCopy)); - return newNode.getContents().move(tr, oldNode.getPartitionSubpath(), newNode.getPartitionSubpath()); - } + return newNode.getContents().move(tr, oldNode.getPartitionSubpath(), newNode.getPartitionSubpath()); + } - if(newNode.exists()) - throw new DirectoryAlreadyExistsException(toAbsolutePath(newPathCopy)); + if(newNode.exists()) + throw new DirectoryAlreadyExistsException(toAbsolutePath(newPathCopy)); - final List parentPath = PathUtil.popBack(newPathCopy); - return new NodeFinder(parentPath).find(tr) - .thenComposeAsync(new Function>() { - @Override - public CompletableFuture apply(Node parentNode) { - if(!parentNode.exists()) - throw new NoSuchDirectoryException(toAbsolutePath(parentPath)); + final List parentPath = PathUtil.popBack(newPathCopy); + return new NodeFinder(parentPath).find(tr).thenComposeAsync(parentNode -> { + if(!parentNode.exists()) + throw new NoSuchDirectoryException(toAbsolutePath(parentPath)); - tr.set( - parentNode.subspace.get(SUB_DIR_KEY).get(getLast(newPathCopy)).getKey(), - contentsOfNode(oldNode.subspace, EMPTY_PATH, EMPTY_BYTES).getKey() - ); + tr.set( + parentNode.subspace.get(SUB_DIR_KEY).get(getLast(newPathCopy)).getKey(), + contentsOfNode(oldNode.subspace, EMPTY_PATH, EMPTY_BYTES).getKey() + ); - return removeFromParent(tr, oldPathCopy) - .thenApply(new Function() { - @Override - public DirectorySubspace apply(Void ignore) { - return contentsOfNode(oldNode.subspace, newPathCopy, oldNode.layer); - } - }); - } - }, tr.getExecutor()); - } - }); - } - }); + return removeFromParent(tr, oldPathCopy) + .thenApply(ignore -> contentsOfNode(oldNode.subspace, newPathCopy, oldNode.layer)); + }, tr.getExecutor()); + }, tr.getExecutor()) + ); } /** @@ -549,39 +513,27 @@ public class DirectoryLayer implements Directory public CompletableFuture> list(final ReadTransactionContext tcx, final List path) { final List pathCopy = new ArrayList(path); - return tcx.readAsync(new Function>>() { - @Override - public CompletableFuture> apply(final ReadTransaction tr) { - return checkVersion(tr) - .thenComposeAsync(new Function>() { - @Override - public CompletableFuture apply(Void ignore) { - return new NodeFinder(pathCopy).find(tr).thenComposeAsync(new NodeMetadataLoader(tr), tr.getExecutor()); - } - }, tr.getExecutor()) - .thenComposeAsync(new Function>>() { - @Override - public CompletableFuture> apply(Node node) { - if(!node.exists()) - throw new NoSuchDirectoryException(toAbsolutePath(pathCopy)); + return tcx.readAsync(tr -> checkVersion(tr) + .thenComposeAsync(ignore -> + new NodeFinder(pathCopy).find(tr).thenComposeAsync(new NodeMetadataLoader(tr), tr.getExecutor()), + tr.getExecutor()) + .thenComposeAsync(node -> { + if(!node.exists()) + throw new NoSuchDirectoryException(toAbsolutePath(pathCopy)); - if(node.isInPartition(true)) - return node.getContents().list(tr, node.getPartitionSubpath()); + if(node.isInPartition(true)) + return node.getContents().list(tr, node.getPartitionSubpath()); - final Subspace subdir = node.subspace.get(SUB_DIR_KEY); + final Subspace subdir = node.subspace.get(SUB_DIR_KEY); - return AsyncUtil.collect( - AsyncUtil.mapIterable(tr.getRange(subdir.range()), - new Function() { - @Override - public String apply(KeyValue o) { - return subdir.unpack(o.getKey()).getString(0); - } - }), tr.getExecutor()); - } - }, tr.getExecutor()); - } - }); + return AsyncUtil.collect( + AsyncUtil.mapIterable(tr.getRange(subdir.range()), + kv -> subdir.unpack(kv.getKey()).getString(0), + tr.getExecutor() + ) + ); + }, tr.getExecutor()) + ); } /** @@ -592,7 +544,7 @@ public class DirectoryLayer implements Directory */ @Override public CompletableFuture exists(ReadTransactionContext tcx) { - return CompletableFuture.completedFuture(true); + return AsyncUtil.READY_TRUE; } /** @@ -605,33 +557,20 @@ public class DirectoryLayer implements Directory */ @Override public CompletableFuture exists(final ReadTransactionContext tcx, final List path) { - final List pathCopy = new ArrayList(path); + final List pathCopy = new ArrayList<>(path); - return tcx.readAsync(new Function>() { - @Override - public CompletableFuture apply(final ReadTransaction tr) { - return checkVersion(tr) - .thenComposeAsync(new Function>() { - @Override - public CompletableFuture apply(Void ignore) { - return new NodeFinder(pathCopy).find(tr).thenComposeAsync(new NodeMetadataLoader(tr), tr.getExecutor()); - }; - }, tr.getExecutor()) - .thenComposeAsync(new Function>() { - @Override - public CompletableFuture apply(Node node) { - if(!node.exists()) - //return new ReadyFuture(false); - return CompletableFuture.completedFuture(false); - else if(node.isInPartition(false)) - return node.getContents().exists(tr, node.getPartitionSubpath()); + return tcx.readAsync(tr -> checkVersion(tr) + .thenComposeAsync(ignore -> + new NodeFinder(pathCopy).find(tr).thenComposeAsync(new NodeMetadataLoader(tr), tr.getExecutor()), + tr.getExecutor()) + .thenComposeAsync(node -> { + if(!node.exists()) + return AsyncUtil.READY_FALSE; + else if(node.isInPartition(false)) + return node.getContents().exists(tr, node.getPartitionSubpath()); - //return new ReadyFuture(true); - return CompletableFuture.completedFuture(true); - } - }, tr.getExecutor()); - } - }); + return AsyncUtil.READY_TRUE; + }, tr.getExecutor())); } // @@ -655,19 +594,16 @@ public class DirectoryLayer implements Directory return tr.getRange(nodeSubspace.range().begin, ByteArrayUtil.join(nodeSubspace.pack(key), new byte[]{0x00}), 1, true) .asList() - .thenApply(new Function, Subspace>() { - @Override - public Subspace apply(List results) { - if(results.size() > 0) { - byte[] resultKey = results.get(0).getKey(); - byte[] prevPrefix = nodeSubspace.unpack(resultKey).getBytes(0); - if(ByteArrayUtil.startsWith(key, prevPrefix)) { - return nodeWithPrefix(prevPrefix); - } - } + .thenApply(results -> { + if(results.size() > 0) { + byte[] resultKey = results.get(0).getKey(); + byte[] prevPrefix = nodeSubspace.unpack(resultKey).getBytes(0); + if(ByteArrayUtil.startsWith(key, prevPrefix)) { + return nodeWithPrefix(prevPrefix); + } + } - return null; - } + return null; }); } @@ -685,55 +621,37 @@ public class DirectoryLayer implements Directory } private CompletableFuture removeInternal(final TransactionContext tcx, final List path, final boolean mustExist) { - final List pathCopy = new ArrayList(path); + final List pathCopy = new ArrayList<>(path); - return tcx.runAsync(new Function>() { - @Override - public CompletableFuture apply(final Transaction tr) { - return checkOrWriteVersion(tr) - .thenComposeAsync(new Function>() { - @Override - public CompletableFuture apply(Void ignore) { - if(pathCopy.size() == 0) - throw new DirectoryException("The root directory cannot be removed.", toAbsolutePath(pathCopy)); + return tcx.runAsync(tr -> checkOrWriteVersion(tr).thenComposeAsync(ignore -> { + if(pathCopy.size() == 0) + throw new DirectoryException("The root directory cannot be removed.", toAbsolutePath(pathCopy)); - return new NodeFinder(pathCopy).find(tr).thenComposeAsync(new NodeMetadataLoader(tr), tr.getExecutor()); - } - }, tr.getExecutor()) - .thenComposeAsync(new Function>() { - @Override - public CompletableFuture apply(Node node) { - if(!node.exists()) { - if(mustExist) - throw new NoSuchDirectoryException(toAbsolutePath(pathCopy)); - else - return CompletableFuture.completedFuture(false); - } + return new NodeFinder(pathCopy).find(tr).thenComposeAsync(new NodeMetadataLoader(tr), tr.getExecutor()); + }, tr.getExecutor()) + .thenComposeAsync(node -> { + if(!node.exists()) { + if(mustExist) + throw new NoSuchDirectoryException(toAbsolutePath(pathCopy)); + else + return AsyncUtil.READY_FALSE; + } - if(node.isInPartition(false)) - return node.getContents().getDirectoryLayer().removeInternal(tr, node.getPartitionSubpath(), mustExist); - else { - ArrayList> futures = new ArrayList>(); - futures.add(removeRecursive(tr, node.subspace)); - futures.add(removeFromParent(tr, pathCopy)); - - return AsyncUtil.tag(AsyncUtil.whenAll(futures), true); - } - } - }, tr.getExecutor()); - } - }); + if(node.isInPartition(false)) + return node.getContents().getDirectoryLayer().removeInternal(tr, node.getPartitionSubpath(), mustExist); + else { + ArrayList> futures = new ArrayList<>(); + futures.add(removeRecursive(tr, node.subspace)); + futures.add(removeFromParent(tr, pathCopy)); + return AsyncUtil.tag(AsyncUtil.whenAll(futures), true); + } + }, tr.getExecutor()) + ); } private CompletableFuture removeFromParent(final Transaction tr, final List path) { return new NodeFinder(PathUtil.popBack(path)).find(tr) - .thenApply(new Function() { - @Override - public Void apply(Node parent) { - tr.clear(parent.subspace.get(SUB_DIR_KEY).get(getLast(path)).getKey()); - return null; - } - }); + .thenAccept(parent -> tr.clear(parent.subspace.get(SUB_DIR_KEY).get(getLast(path)).getKey())); } private CompletableFuture removeRecursive(final Transaction tr, final Subspace node) { @@ -743,23 +661,14 @@ public class DirectoryLayer implements Directory tr.clear(Range.startsWith(nodeSubspace.unpack(node.getKey()).getBytes(0))); tr.clear(node.range()); - return AsyncUtil.whileTrue(new Supplier>() { - @Override - public CompletableFuture get() { - CompletableFuture subdirRemoveFuture; - if(rangeItr.onHasNext().isDone() && rangeItr.hasNext()) - subdirRemoveFuture = removeRecursive(tr, nodeWithPrefix(rangeItr.next().getValue())); - else - subdirRemoveFuture = CompletableFuture.completedFuture(null); + return AsyncUtil.whileTrue(() -> { + CompletableFuture subdirRemoveFuture; + if(rangeItr.onHasNext().isDone() && rangeItr.hasNext()) + subdirRemoveFuture = removeRecursive(tr, nodeWithPrefix(rangeItr.next().getValue())); + else + subdirRemoveFuture = AsyncUtil.DONE; - return subdirRemoveFuture - .thenComposeAsync(new Function>() { - @Override - public CompletableFuture apply(Void ignore) { - return rangeItr.onHasNext(); - } - }, tr.getExecutor()); - } + return subdirRemoveFuture.thenCompose(ignore -> rangeItr.onHasNext()); }, tr.getExecutor()); } @@ -768,26 +677,14 @@ public class DirectoryLayer implements Directory // allocated prefix (including the root node). This means that it neither // contains any other prefix nor is contained by any other prefix. if(prefix == null || prefix.length == 0) - //return new ReadyFuture(false); - return CompletableFuture.completedFuture(false); + return AsyncUtil.READY_FALSE; - return nodeContainingKey(tr, prefix) - .thenComposeAsync(new Function>() { - @Override - public CompletableFuture apply(Subspace node) { - if(node != null) - //return new ReadyFuture(false); - return CompletableFuture.completedFuture(false); + return nodeContainingKey(tr, prefix).thenComposeAsync(node -> { + if(node != null) + return AsyncUtil.READY_FALSE; - final AsyncIterator it = tr.getRange(nodeSubspace.pack(prefix), nodeSubspace.pack(ByteArrayUtil.strinc(prefix)), 1).iterator(); - return it.onHasNext() - .thenApply(new Function() { - @Override - public Boolean apply(Boolean hasNext) { - return !hasNext; - } - }); - } + final AsyncIterator it = tr.getRange(nodeSubspace.pack(prefix), nodeSubspace.pack(ByteArrayUtil.strinc(prefix)), 1).iterator(); + return it.onHasNext().thenApply(hasNext -> !hasNext); }, tr.getExecutor()); } @@ -811,7 +708,7 @@ public class DirectoryLayer implements Directory final boolean allowCreate, final boolean allowOpen) { - final List pathCopy = new ArrayList(path); + final List pathCopy = new ArrayList<>(path); if(prefix != null && !allowManualPrefixes) { String errorMessage; @@ -820,40 +717,33 @@ public class DirectoryLayer implements Directory else errorMessage = "Cannot specify a prefix in a partition."; - CompletableFuture future = new CompletableFuture(); + CompletableFuture future = new CompletableFuture<>(); future.completeExceptionally(new IllegalArgumentException(errorMessage)); return future; } - return checkVersion(rtr) - .thenComposeAsync(new Function>() { - @Override - public CompletableFuture apply(Void ignore) { - // Root directory contains node metadata and so may not be opened. - if(pathCopy.size() == 0) { - throw new IllegalArgumentException("The root directory may not be opened."); - } + return checkVersion(rtr).thenComposeAsync(ignore -> { + // Root directory contains node metadata and so may not be opened. + if(pathCopy.size() == 0) { + throw new IllegalArgumentException("The root directory may not be opened."); + } - return new NodeFinder(pathCopy).find(rtr).thenComposeAsync(new NodeMetadataLoader(rtr), rtr.getExecutor()); - } + return new NodeFinder(pathCopy).find(rtr).thenComposeAsync(new NodeMetadataLoader(rtr), rtr.getExecutor()); }, rtr.getExecutor()) - .thenComposeAsync(new Function>() { - @Override - public CompletableFuture apply(final Node existingNode) { - if(existingNode.exists()) { - if(existingNode.isInPartition(false)) { - List subpath = existingNode.getPartitionSubpath(); - DirectoryLayer directoryLayer = existingNode.getContents().getDirectoryLayer(); - return directoryLayer.createOrOpenInternal( - rtr, tr, subpath, layer, prefix, allowCreate, allowOpen); - } + .thenComposeAsync(existingNode -> { + if(existingNode.exists()) { + if(existingNode.isInPartition(false)) { + List subpath = existingNode.getPartitionSubpath(); + DirectoryLayer directoryLayer = existingNode.getContents().getDirectoryLayer(); + return directoryLayer.createOrOpenInternal( + rtr, tr, subpath, layer, prefix, allowCreate, allowOpen); + } - DirectorySubspace opened = openInternal(pathCopy, layer, existingNode, allowOpen); - return CompletableFuture.completedFuture(opened); - } - else - return createInternal(tr, pathCopy, layer, prefix, allowCreate); - } + DirectorySubspace opened = openInternal(pathCopy, layer, existingNode, allowOpen); + return CompletableFuture.completedFuture(opened); + } + else + return createInternal(tr, pathCopy, layer, prefix, allowCreate); }, rtr.getExecutor()); } @@ -884,78 +774,47 @@ public class DirectoryLayer implements Directory throw new NoSuchDirectoryException(toAbsolutePath(path)); } - return checkOrWriteVersion(tr) - .thenComposeAsync(new Function>() { - @Override - public CompletableFuture apply(Void ignore) { - if(prefix == null) { - return allocator.allocate(tr) - .thenComposeAsync(new Function>() { - @Override - public CompletableFuture apply(byte[] allocated) { - final byte[] finalPrefix = ByteArrayUtil.join(contentSubspace.getKey(), allocated); - return tr.getRange(Range.startsWith(finalPrefix), 1) - .asList() - .thenApply(new Function, byte[]>() { - @Override - public byte[] apply(List results) { - if(results.size() > 0) { - throw new IllegalStateException("The database has keys stored at the prefix chosen by the automatic " + - "prefix allocator: " + ByteArrayUtil.printable(finalPrefix) + "."); - } - - return finalPrefix; - } - }); - } - }, tr.getExecutor()); - } - else - return CompletableFuture.completedFuture(prefix); - //return new ReadyFuture(prefix); - } + return checkOrWriteVersion(tr).thenComposeAsync(ignore -> { + if(prefix == null) { + return allocator.allocate(tr).thenComposeAsync(allocated -> { + final byte[] finalPrefix = ByteArrayUtil.join(contentSubspace.getKey(), allocated); + return tr.getRange(Range.startsWith(finalPrefix), 1).iterator().onHasNext().thenApply(hasAny -> { + if(hasAny) { + throw new IllegalStateException("The database has keys stored at the prefix chosen by the automatic " + + "prefix allocator: " + ByteArrayUtil.printable(finalPrefix) + "."); + } + return finalPrefix; + }); + }, tr.getExecutor()); + } + else + return CompletableFuture.completedFuture(prefix); }, tr.getExecutor()) - .thenComposeAsync(new Function>() { - @Override - public CompletableFuture apply(final byte[] actualPrefix) { - return isPrefixFree(prefix == null ? tr.snapshot() : tr, actualPrefix) - .thenComposeAsync(new Function>() { - @Override - public CompletableFuture apply(Boolean prefixFree) { - if(!prefixFree) { - if(prefix == null) { - throw new IllegalStateException("The directory layer has manually allocated prefixes that conflict " + - "with the automatic prefix allocator."); - } - else - throw new IllegalArgumentException("Prefix already in use: " + ByteArrayUtil.printable(actualPrefix) + "."); - } - else if(path.size() > 1) { - return createOrOpen(tr, PathUtil.popBack(path)) - .thenApply(new Function() { - @Override - public Subspace apply(DirectorySubspace dir) { - return nodeWithPrefix(dir.getKey()); - } - }); - } - else - return CompletableFuture.completedFuture(rootNode); - } - }, tr.getExecutor()) - .thenApply(new Function() { - @Override - public DirectorySubspace apply(Subspace parentNode) { - if(parentNode == null) - throw new IllegalStateException("The parent directory does not exist."); //Shouldn't happen - Subspace node = nodeWithPrefix(actualPrefix); - tr.set(parentNode.get(SUB_DIR_KEY).get(getLast(path)).getKey(), actualPrefix); - tr.set(node.get(LAYER_KEY).getKey(), layer); - return contentsOfNode(node, path, layer); - } - }); - } - }, tr.getExecutor()); + .thenComposeAsync(actualPrefix -> isPrefixFree(prefix == null ? tr.snapshot() : tr, actualPrefix) + .thenComposeAsync(prefixFree -> { + if(!prefixFree) { + if(prefix == null) { + throw new IllegalStateException("The directory layer has manually allocated prefixes that conflict " + + "with the automatic prefix allocator."); + } + else + throw new IllegalArgumentException("Prefix already in use: " + ByteArrayUtil.printable(actualPrefix) + "."); + } + else if(path.size() > 1) { + return createOrOpen(tr, PathUtil.popBack(path)).thenApply(dir -> nodeWithPrefix(dir.getKey())); + } + else + return CompletableFuture.completedFuture(rootNode); + }, tr.getExecutor()) + .thenApplyAsync(parentNode -> { + if(parentNode == null) + throw new IllegalStateException("The parent directory does not exist."); //Shouldn't happen + Subspace node = nodeWithPrefix(actualPrefix); + tr.set(parentNode.get(SUB_DIR_KEY).get(getLast(path)).getKey(), actualPrefix); + tr.set(node.get(LAYER_KEY).getKey(), layer); + return contentsOfNode(node, path, layer); + }, tr.getExecutor()), + tr.getExecutor()); } // @@ -1050,42 +909,26 @@ public class DirectoryLayer implements Directory public CompletableFuture find(final ReadTransaction tr) { index = 0; node = new Node(rootNode, currentPath, path); - currentPath = new ArrayList(); + currentPath = new ArrayList<>(); - return AsyncUtil.whileTrue(new Supplier>() { - @Override - public CompletableFuture get() { - if(index == path.size()) - return CompletableFuture.completedFuture(false); + return AsyncUtil.whileTrue(() -> { + if(index == path.size()) + return CompletableFuture.completedFuture(false); - return tr.get(node.subspace.get(SUB_DIR_KEY).get(path.get(index)).getKey()) - .thenComposeAsync(new Function>() { - @Override - public CompletableFuture apply(byte[] key) { - currentPath.add(path.get(index)); - node = new Node(nodeWithPrefix(key), currentPath, path); + return tr.get(node.subspace.get(SUB_DIR_KEY).get(path.get(index)).getKey()).thenComposeAsync(key -> { + currentPath.add(path.get(index)); + node = new Node(nodeWithPrefix(key), currentPath, path); - if(!node.exists()) - return CompletableFuture.completedFuture(false); + if(!node.exists()) + return CompletableFuture.completedFuture(false); - return node.loadMetadata(tr) - .thenApply(new Function() { - @Override - public Boolean apply(Node ignore) { - ++index; - return !Arrays.equals(node.layer, DirectoryLayer.PARTITION_LAYER); - } - }); - } - }, tr.getExecutor()); - } + return node.loadMetadata(tr).thenApply(ignore -> { + ++index; + return !Arrays.equals(node.layer, DirectoryLayer.PARTITION_LAYER); + }); + }, tr.getExecutor()); }, tr.getExecutor()) - .thenApply(new Function() { - @Override - public Node apply(Void ignore) { - return node; - } - }); + .thenApply(ignore -> node); } } @@ -1130,13 +973,10 @@ public class DirectoryLayer implements Directory } return tr.get(subspace.pack(new Tuple().add(LAYER_KEY))) - .thenApply(new Function() { - @Override - public Node apply(byte[] value) { - layer = value; - loadedMetadata = true; - return Node.this; - } + .thenApply(value -> { + layer = value; + loadedMetadata = true; + return Node.this; }); } @@ -1176,146 +1016,100 @@ public class DirectoryLayer implements Directory } public CompletableFuture find(final Transaction tr, final HighContentionAllocator allocator) { - return AsyncUtil.whileTrue(new Supplier>() { - @Override - public CompletableFuture get() { - final AsyncIterator rangeItr = tr.snapshot().getRange(allocator.counters.range(), 1, true).iterator(); - return rangeItr.onHasNext() - .thenApply(new Function() { - @Override - public Void apply(Boolean hasNext) { - if(hasNext) { - KeyValue kv = rangeItr.next(); - windowStart = allocator.counters.unpack(kv.getKey()).getLong(0); - } + return AsyncUtil.whileTrue(() -> { + final AsyncIterator rangeItr = tr.snapshot().getRange(allocator.counters.range(), 1, true).iterator(); + return rangeItr.onHasNext().thenApply(hasNext -> { + if(hasNext) { + KeyValue kv = rangeItr.next(); + windowStart = allocator.counters.unpack(kv.getKey()).getLong(0); + } - return null; - } - }) - .thenComposeAsync(new Function>() { - @Override - public CompletableFuture apply(Void ignore) { - return chooseWindow(tr, allocator); - } - }, tr.getExecutor()) - .thenComposeAsync(new Function>() { - @Override - public CompletableFuture apply(Void ignore) { - return choosePrefix(tr, allocator); // false exits the loop (i.e. we have a valid prefix) - } - }, tr.getExecutor()); - } + return null; + }) + .thenComposeAsync(ignore -> chooseWindow(tr, allocator), tr.getExecutor()) + .thenComposeAsync(ignore -> choosePrefix(tr, allocator), tr.getExecutor()); }, tr.getExecutor()) - .thenApply(new Function() { - @Override - public byte[] apply(Void ignore) { - return Tuple.from(candidate).pack(); - } - }); + .thenApply(ignore -> Tuple.from(candidate).pack()); } public CompletableFuture chooseWindow(final Transaction tr, final HighContentionAllocator allocator) { final long initialWindowStart = windowStart; - return AsyncUtil.whileTrue(new Supplier>() { - @Override - public CompletableFuture get() { - final byte[] counterKey = allocator.counters.get(windowStart).getKey(); + return AsyncUtil.whileTrue(() -> { + final byte[] counterKey = allocator.counters.get(windowStart).getKey(); - Range oldCounters = new Range(allocator.counters.getKey(), counterKey); - Range oldAllocations = new Range(allocator.recent.getKey(), allocator.recent.get(windowStart).getKey()); + Range oldCounters = new Range(allocator.counters.getKey(), counterKey); + Range oldAllocations = new Range(allocator.recent.getKey(), allocator.recent.get(windowStart).getKey()); - CompletableFuture newCountRead; - // SOMEDAY: synchronize on something transaction local - synchronized(HighContentionAllocator.class) { - if(windowStart > initialWindowStart) { - tr.clear(oldCounters); - tr.options().setNextWriteNoWriteConflictRange(); - tr.clear(oldAllocations); - } + CompletableFuture newCountRead; + // SOMEDAY: synchronize on something transaction local + synchronized(HighContentionAllocator.class) { + if(windowStart > initialWindowStart) { + tr.clear(oldCounters); + tr.options().setNextWriteNoWriteConflictRange(); + tr.clear(oldAllocations); + } - tr.mutate(MutationType.ADD, counterKey, LITTLE_ENDIAN_LONG_ONE); - newCountRead = tr.snapshot().get(counterKey); - } + tr.mutate(MutationType.ADD, counterKey, LITTLE_ENDIAN_LONG_ONE); + newCountRead = tr.snapshot().get(counterKey); + } - return newCountRead - .thenApply(new Function() { - @Override - public Boolean apply(byte[] newCountBytes) { - long newCount = newCountBytes == null ? 0 : unpackLittleEndian(newCountBytes); - windowSize = getWindowSize(windowStart); - if(newCount * 2 >= windowSize) { - windowStart += windowSize; - return true; - } + return newCountRead.thenApply(newCountBytes -> { + long newCount = newCountBytes == null ? 0 : unpackLittleEndian(newCountBytes); + windowSize = getWindowSize(windowStart); + if(newCount * 2 >= windowSize) { + windowStart += windowSize; + return true; + } - return false; // exit the loop - } - }); - } + return false; // exit the loop + }); }, tr.getExecutor()); } public CompletableFuture choosePrefix(final Transaction tr, final HighContentionAllocator allocator) { restart = false; - return AsyncUtil.whileTrue(new Supplier>() { - @Override - public CompletableFuture get() { - // As of the snapshot being read from, the window is less than half - // full, so this should be expected to take 2 tries. Under high - // contention (and when the window advances), there is an additional - // subsequent risk of conflict for this transaction. - candidate = windowStart + random.nextInt(windowSize); - final byte[] allocationKey = allocator.recent.get(candidate).getKey(); - Range countersRange = allocator.counters.range(); + return AsyncUtil.whileTrue(() -> { + // As of the snapshot being read from, the window is less than half + // full, so this should be expected to take 2 tries. Under high + // contention (and when the window advances), there is an additional + // subsequent risk of conflict for this transaction. + candidate = windowStart + random.nextInt(windowSize); + final byte[] allocationKey = allocator.recent.get(candidate).getKey(); + Range countersRange = allocator.counters.range(); - AsyncIterable counterRange; - CompletableFuture allocationTemp; - // SOMEDAY: synchronize on something transaction local - synchronized(HighContentionAllocator.class) { - counterRange = tr.snapshot().getRange(countersRange, 1, true); - allocationTemp = tr.get(allocationKey); - tr.options().setNextWriteNoWriteConflictRange(); - tr.set(allocationKey, EMPTY_BYTES); - } + AsyncIterable counterRange; + CompletableFuture allocationTemp; + // SOMEDAY: synchronize on something transaction local + synchronized(HighContentionAllocator.class) { + counterRange = tr.snapshot().getRange(countersRange, 1, true); + allocationTemp = tr.get(allocationKey); + tr.options().setNextWriteNoWriteConflictRange(); + tr.set(allocationKey, EMPTY_BYTES); + } - final CompletableFuture> lastCounter = counterRange.asList(); - final CompletableFuture allocation = allocationTemp; + final CompletableFuture> lastCounter = counterRange.asList(); + final CompletableFuture allocation = allocationTemp; - List> futures = new ArrayList>(); - futures.add(AsyncUtil.success(lastCounter)); - futures.add(AsyncUtil.success(allocation)); + return lastCounter.thenCombineAsync(allocation, (result, allocationValue) -> { + long currentWindowStart = 0; + if(!result.isEmpty()) { + currentWindowStart = allocator.counters.unpack(result.get(0).getKey()).getLong(0); + } - return AsyncUtil.whenAll(futures) - .thenApply(new Function() { - @Override - public Boolean apply(Void ignore) { - long currentWindowStart = 0; - List result = lastCounter.join(); - if(!result.isEmpty()) { - currentWindowStart = allocator.counters.unpack(result.get(0).getKey()).getLong(0); - } + if(currentWindowStart > windowStart) { + restart = true; + return false; // exit the loop and rerun the allocation from the beginning + } - if(currentWindowStart > windowStart) { - restart = true; - return false; // exit the loop and rerun the allocation from the beginning - } + if(allocationValue == null) { + tr.addWriteConflictKey(allocationKey); + return false; // exit the loop and return this candidate + } - if(allocation.join() == null) { - tr.addWriteConflictKey(allocationKey); - return false; // exit the loop and return this candidate - } - - return true; - } - }); - } + return true; + }, tr.getExecutor()); }, tr.getExecutor()) - .thenApply(new Function() { - @Override - public Boolean apply(Void ignore) { - return restart; - } - }); + .thenApply(ignore -> restart); } private static int getWindowSize(long start) { diff --git a/bindings/java/src-completable/test/com/apple/foundationdb/test/AsyncDirectoryExtension.java b/bindings/java/src-completable/test/com/apple/foundationdb/test/AsyncDirectoryExtension.java index 484a2f6a15..8c34cc35ef 100644 --- a/bindings/java/src-completable/test/com/apple/foundationdb/test/AsyncDirectoryExtension.java +++ b/bindings/java/src-completable/test/com/apple/foundationdb/test/AsyncDirectoryExtension.java @@ -22,13 +22,11 @@ package com.apple.foundationdb.test; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; - import java.util.concurrent.CompletableFuture; -import java.util.function.Function; import com.apple.foundationdb.Range; -import com.apple.foundationdb.Transaction; import com.apple.foundationdb.async.AsyncUtil; import com.apple.foundationdb.directory.Directory; import com.apple.foundationdb.directory.DirectoryLayer; @@ -37,7 +35,7 @@ import com.apple.foundationdb.subspace.Subspace; import com.apple.foundationdb.tuple.Tuple; class AsyncDirectoryExtension { - List dirList = new ArrayList(); + List dirList = new ArrayList<>(); int dirIndex = 0; int errorIndex = 0; @@ -54,13 +52,9 @@ class AsyncDirectoryExtension { } CompletableFuture processInstruction(final Instruction inst) { - return executeInstruction(inst) - .exceptionally(new Function() { - @Override - public Void apply(Throwable e) { - DirectoryUtil.pushError(inst, e, dirList); - return null; - } + return executeInstruction(inst).exceptionally(e -> { + DirectoryUtil.pushError(inst, e, dirList); + return null; }); } @@ -69,372 +63,184 @@ class AsyncDirectoryExtension { if(op == DirectoryOperation.DIRECTORY_CREATE_SUBSPACE) { return DirectoryUtil.popTuple(inst) - .thenComposeAsync(new Function>() { - @Override - public CompletableFuture apply(final Tuple prefix) { - return inst.popParam() - .thenApplyAsync(new Function() { - @Override - public Void apply(Object rawPrefix) { - dirList.add(new Subspace(prefix, (byte[])rawPrefix)); - return null; - } - }); - } - }); + .thenComposeAsync(prefix -> inst.popParam() + .thenAccept(rawPrefix -> dirList.add(new Subspace(prefix, (byte[])rawPrefix)))); } else if(op == DirectoryOperation.DIRECTORY_CREATE_LAYER) { - return inst.popParams(3) - .thenApplyAsync(new Function, Void>() { - @Override - public Void apply(List params) { - Subspace nodeSubspace = (Subspace)dirList.get(StackUtils.getInt(params.get(0))); - Subspace contentSubspace = (Subspace)dirList.get(StackUtils.getInt(params.get(1))); - boolean allowManualPrefixes = StackUtils.getInt(params.get(2)) == 1; + return inst.popParams(3).thenAcceptAsync(params -> { + Subspace nodeSubspace = (Subspace)dirList.get(StackUtils.getInt(params.get(0))); + Subspace contentSubspace = (Subspace)dirList.get(StackUtils.getInt(params.get(1))); + boolean allowManualPrefixes = StackUtils.getInt(params.get(2)) == 1; - if(nodeSubspace == null || contentSubspace == null) - dirList.add(null); - else - dirList.add(new DirectoryLayer(nodeSubspace, contentSubspace, allowManualPrefixes)); - - return null; - } + if(nodeSubspace == null || contentSubspace == null) + dirList.add(null); + else + dirList.add(new DirectoryLayer(nodeSubspace, contentSubspace, allowManualPrefixes)); }); } else if(op == DirectoryOperation.DIRECTORY_CHANGE) { - return inst.popParam() - .thenApplyAsync(new Function() { - @Override - public Void apply(Object index) { - dirIndex = StackUtils.getInt(index); - if(dirList.get(dirIndex) == null) - dirIndex = errorIndex; - - return null; - } + return inst.popParam().thenAcceptAsync(index -> { + dirIndex = StackUtils.getInt(index); + if(dirList.get(dirIndex) == null) + dirIndex = errorIndex; }); } else if(op == DirectoryOperation.DIRECTORY_SET_ERROR_INDEX) { - return inst.popParam() - .thenApplyAsync(new Function() { - @Override - public Void apply(Object index) { - errorIndex = StackUtils.getInt(index); - return null; - } - }); + return inst.popParam().thenAcceptAsync(index -> errorIndex = StackUtils.getInt(index)); } else if(op == DirectoryOperation.DIRECTORY_CREATE_OR_OPEN || op == DirectoryOperation.DIRECTORY_OPEN) { return DirectoryUtil.popPath(inst) - .thenComposeAsync(new Function, CompletableFuture>() { - @Override - public CompletableFuture apply(final List path) { - return inst.popParam() - .thenComposeAsync(new Function>() { - @Override - public CompletableFuture apply(Object layer) { - CompletableFuture dir; - if(layer == null) { - if(op == DirectoryOperation.DIRECTORY_CREATE_OR_OPEN) - dir = directory().createOrOpen(inst.tcx, path); - else - dir = directory().open(inst.readTcx, path); - } - else { - if(op == DirectoryOperation.DIRECTORY_CREATE_OR_OPEN) - dir = directory().createOrOpen(inst.tcx, path, (byte[])layer); - else - dir = directory().open(inst.readTcx, path, (byte[])layer); - } + .thenComposeAsync(path -> inst.popParam().thenComposeAsync(layer -> { + CompletableFuture dir; + if(layer == null) { + if(op == DirectoryOperation.DIRECTORY_CREATE_OR_OPEN) + dir = directory().createOrOpen(inst.tcx, path); + else + dir = directory().open(inst.readTcx, path); + } + else { + if(op == DirectoryOperation.DIRECTORY_CREATE_OR_OPEN) + dir = directory().createOrOpen(inst.tcx, path, (byte[])layer); + else + dir = directory().open(inst.readTcx, path, (byte[])layer); + } - return dir.thenApplyAsync(new Function() { - @Override - public Void apply(DirectorySubspace dirSubspace) { - dirList.add(dirSubspace); - return null; - } - }); - } - }); - } - }); + return dir.thenAccept(dirList::add); + })); } else if(op == DirectoryOperation.DIRECTORY_CREATE) { - return DirectoryUtil.popPath(inst) - .thenComposeAsync(new Function, CompletableFuture>() { - @Override - public CompletableFuture apply(final List path) { - return inst.popParams(2) - .thenComposeAsync(new Function, CompletableFuture>() { - @Override - public CompletableFuture apply(List params) { - byte[] layer = (byte[])params.get(0); - byte[] prefix = (byte[])params.get(1); + return DirectoryUtil.popPath(inst).thenComposeAsync(path -> inst.popParams(2).thenComposeAsync(params -> { + byte[] layer = (byte[])params.get(0); + byte[] prefix = (byte[])params.get(1); - CompletableFuture dir; - if(layer == null && prefix == null) - dir = directory().create(inst.tcx, path); - else if(prefix == null) - dir = directory().create(inst.tcx, path, layer); - else { - if(layer == null) - layer = new byte[0]; + CompletableFuture dir; + if(layer == null && prefix == null) + dir = directory().create(inst.tcx, path); + else if(prefix == null) + dir = directory().create(inst.tcx, path, layer); + else { + if(layer == null) + layer = new byte[0]; - dir = directory().create(inst.tcx, path, layer, prefix); - } + dir = directory().create(inst.tcx, path, layer, prefix); + } - return dir.thenApplyAsync(new Function() { - @Override - public Void apply(DirectorySubspace dirSubspace) { - dirList.add(dirSubspace); - return null; - } - }); - } - }); - } - }); + return dir.thenAccept(dirList::add); + })); } else if(op == DirectoryOperation.DIRECTORY_MOVE) { return DirectoryUtil.popPaths(inst, 2) - .thenComposeAsync(new Function>, CompletableFuture>() { - @Override - public CompletableFuture apply(List> paths) { - return directory().move(inst.tcx, paths.get(0), paths.get(1)); - } - }) - .thenApplyAsync(new Function() { - @Override - public Void apply(DirectorySubspace dirSubspace) { - dirList.add(dirSubspace); - return null; - } - }); + .thenComposeAsync(paths -> directory().move(inst.tcx, paths.get(0), paths.get(1))) + .thenAccept(dirList::add); } else if(op == DirectoryOperation.DIRECTORY_MOVE_TO) { return DirectoryUtil.popPath(inst) - .thenComposeAsync(new Function, CompletableFuture>() { - @Override - public CompletableFuture apply(List newAbsolutePath) { - return directory().moveTo(inst.tcx, newAbsolutePath); - } - }) - .thenApplyAsync(new Function() { - @Override - public Void apply(DirectorySubspace dirSubspace) { - dirList.add(dirSubspace); - return null; - } - }); + .thenComposeAsync(newAbsolutePath -> directory().moveTo(inst.tcx, newAbsolutePath)) + .thenAccept(dirList::add); } else if(op == DirectoryOperation.DIRECTORY_REMOVE) { return inst.popParam() - .thenComposeAsync(new Function>>>() { - @Override - public CompletableFuture>> apply(Object count) { - return DirectoryUtil.popPaths(inst, StackUtils.getInt(count)); - } - }) - .thenComposeAsync(new Function>, CompletableFuture>() { - @Override - public CompletableFuture apply(List> path) { - if(path.size() == 0) - return directory().remove(inst.tcx); - else - return directory().remove(inst.tcx, path.get(0)); - } + .thenComposeAsync(count -> DirectoryUtil.popPaths(inst, StackUtils.getInt(count))) + .thenComposeAsync(path -> { + if(path.size() == 0) + return directory().remove(inst.tcx); + else + return directory().remove(inst.tcx, path.get(0)); }); } else if(op == DirectoryOperation.DIRECTORY_REMOVE_IF_EXISTS) { return inst.popParam() - .thenComposeAsync(new Function>>>() { - @Override - public CompletableFuture>> apply(Object count) { - return DirectoryUtil.popPaths(inst, StackUtils.getInt(count)); - } - }) - .thenComposeAsync(new Function>, CompletableFuture>() { - @Override - public CompletableFuture apply(List> path) { - if(path.size() == 0) - return AsyncUtil.success(directory().removeIfExists(inst.tcx)); - else - return AsyncUtil.success(directory().removeIfExists(inst.tcx, path.get(0))); - } - }); + .thenComposeAsync(count -> DirectoryUtil.popPaths(inst, StackUtils.getInt(count))) + .thenComposeAsync(path -> { + if(path.size() == 0) + return AsyncUtil.success(directory().removeIfExists(inst.tcx)); + else + return AsyncUtil.success(directory().removeIfExists(inst.tcx, path.get(0))); + }); } else if(op == DirectoryOperation.DIRECTORY_LIST) { return inst.popParam() - .thenComposeAsync(new Function>>>() { - @Override - public CompletableFuture>> apply(Object count) { - return DirectoryUtil.popPaths(inst, StackUtils.getInt(count)); - } - }) - .thenComposeAsync(new Function>, CompletableFuture>>() { - @Override - public CompletableFuture> apply(List> path) { - if(path.size() == 0) - return directory().list(inst.readTcx); - else - return directory().list(inst.readTcx, path.get(0)); - } - }) - .thenApplyAsync(new Function, Void>() { - @Override - public Void apply(List children) { - inst.push(Tuple.fromItems(children).pack()); - return null; - } - }); + .thenComposeAsync(count -> DirectoryUtil.popPaths(inst, StackUtils.getInt(count))) + .thenComposeAsync(path -> { + if(path.size() == 0) + return directory().list(inst.readTcx); + else + return directory().list(inst.readTcx, path.get(0)); + }) + .thenAccept(children -> inst.push(Tuple.fromItems(children).pack())); } else if(op == DirectoryOperation.DIRECTORY_EXISTS) { return inst.popParam() - .thenComposeAsync(new Function>>>() { - @Override - public CompletableFuture>> apply(Object count) { - return DirectoryUtil.popPaths(inst, StackUtils.getInt(count)); - } + .thenComposeAsync(count -> DirectoryUtil.popPaths(inst, StackUtils.getInt(count))) + .thenComposeAsync(path -> { + if(path.size() == 0) + return directory().exists(inst.readTcx); + else + return directory().exists(inst.readTcx, path.get(0)); }) - .thenComposeAsync(new Function>, CompletableFuture>() { - @Override - public CompletableFuture apply(List> path) { - if(path.size() == 0) - return directory().exists(inst.readTcx); - else - return directory().exists(inst.readTcx, path.get(0)); - } - }) - .thenApplyAsync(new Function() { - @Override - public Void apply(Boolean exists){ - inst.push(exists ? 1 : 0); - return null; - } - }); + .thenAccept(exists -> inst.push(exists ? 1 : 0)); } else if(op == DirectoryOperation.DIRECTORY_PACK_KEY) { - return DirectoryUtil.popTuple(inst) - .thenApplyAsync(new Function() { - @Override - public Void apply(Tuple keyTuple) { - inst.push(subspace().pack(keyTuple)); - return null; - } - }); + return DirectoryUtil.popTuple(inst).thenAccept(keyTuple -> inst.push(subspace().pack(keyTuple))); } else if(op == DirectoryOperation.DIRECTORY_UNPACK_KEY) { - return inst.popParam() - .thenApplyAsync(new Function() { - @Override - public Void apply(Object key) { - Tuple tup = subspace().unpack((byte[])key); - for(Object o : tup) - inst.push(o); - - return null; - } + return inst.popParam().thenAcceptAsync(key -> { + Tuple tup = subspace().unpack((byte[])key); + for(Object o : tup) + inst.push(o); }); } else if(op == DirectoryOperation.DIRECTORY_RANGE) { - return DirectoryUtil.popTuple(inst) - .thenApplyAsync(new Function() { - @Override - public Void apply(Tuple tup) { - Range range = subspace().range(tup); - inst.push(range.begin); - inst.push(range.end); - return null; - } + return DirectoryUtil.popTuple(inst).thenAcceptAsync(tup -> { + Range range = subspace().range(tup); + inst.push(range.begin); + inst.push(range.end); }); } else if(op == DirectoryOperation.DIRECTORY_CONTAINS) { - return inst.popParam() - .thenApplyAsync(new Function() { - @Override - public Void apply(Object key) { - inst.push(subspace().contains((byte[])key) ? 1 : 0); - return null; - } - }); + return inst.popParam().thenAccept(key -> inst.push(subspace().contains((byte[])key) ? 1 : 0)); } else if(op == DirectoryOperation.DIRECTORY_OPEN_SUBSPACE) { - return DirectoryUtil.popTuple(inst) - .thenApplyAsync(new Function() { - @Override - public Void apply(Tuple prefix) { - dirList.add(subspace().subspace(prefix)); - return null; - } - }); + return DirectoryUtil.popTuple(inst).thenAcceptAsync(prefix -> dirList.add(subspace().subspace(prefix))); } else if(op == DirectoryOperation.DIRECTORY_LOG_SUBSPACE) { - return inst.popParam() - .thenComposeAsync(new Function>() { - @Override - public CompletableFuture apply(final Object prefix) { - return inst.tcx.runAsync(new Function>() { - @Override - public CompletableFuture apply(Transaction tr) { - tr.set(Tuple.from(dirIndex).pack((byte[])prefix), subspace().getKey()); - return CompletableFuture.completedFuture(null); - } - }); - } - }); + return inst.popParam().thenComposeAsync(prefix -> + inst.tcx.runAsync(tr -> { + tr.set(Tuple.from(dirIndex).pack((byte[])prefix), subspace().getKey()); + return AsyncUtil.DONE; + }) + ); } else if(op == DirectoryOperation.DIRECTORY_LOG_DIRECTORY) { - return inst.popParam() - .thenComposeAsync(new Function>() { - @Override - public CompletableFuture apply(Object prefix) { - final Subspace logSubspace = new Subspace(new Tuple().add(dirIndex), (byte[])prefix); - return inst.tcx.runAsync(new Function>() { - @Override - public CompletableFuture apply(final Transaction tr) { - return directory().exists(tr) - .thenComposeAsync(new Function>>() { - @Override - public CompletableFuture> apply(Boolean exists) { - tr.set(logSubspace.pack("path"), Tuple.fromItems(directory().getPath()).pack()); - tr.set(logSubspace.pack("layer"), new Tuple().add(directory().getLayer()).pack()); - tr.set(logSubspace.pack("exists"), new Tuple().add(exists ? 1 : 0).pack()); - if(exists) - return directory().list(tr); - else - return CompletableFuture.completedFuture(new ArrayList()); - } - }) - .thenApplyAsync(new Function, Void>() { - @Override - public Void apply(List children) { - tr.set(logSubspace.pack("children"), Tuple.fromItems(children).pack()); - return null; - } - }); - } - }); - } + return inst.popParam().thenComposeAsync(prefix -> { + final Subspace logSubspace = new Subspace(new Tuple().add(dirIndex), (byte[])prefix); + return inst.tcx.runAsync(tr -> directory().exists(tr) + .thenComposeAsync(exists -> { + tr.set(logSubspace.pack("path"), Tuple.fromItems(directory().getPath()).pack()); + tr.set(logSubspace.pack("layer"), new Tuple().add(directory().getLayer()).pack()); + tr.set(logSubspace.pack("exists"), new Tuple().add(exists ? 1 : 0).pack()); + if(exists) + return directory().list(tr); + else + return CompletableFuture.completedFuture(Collections.emptyList()); + }) + .thenAcceptAsync(children -> tr.set(logSubspace.pack("children"), Tuple.fromItems(children).pack())) + ); }); } else if(op == DirectoryOperation.DIRECTORY_STRIP_PREFIX) { - return inst.popParam() - .thenApplyAsync(new Function() { - @Override - public Void apply(Object param) { - byte[] str = (byte[])param; - byte[] rawPrefix = subspace().getKey(); + return inst.popParam().thenAcceptAsync(param -> { + byte[] str = (byte[])param; + byte[] rawPrefix = subspace().getKey(); - if(str.length < rawPrefix.length) - throw new RuntimeException("String does not start with raw prefix"); + if(str.length < rawPrefix.length) + throw new RuntimeException("String does not start with raw prefix"); - for(int i = 0; i < rawPrefix.length; ++i) - if(str[i] != rawPrefix[i]) - throw new RuntimeException("String does not start with raw prefix"); + for(int i = 0; i < rawPrefix.length; ++i) + if(str[i] != rawPrefix[i]) + throw new RuntimeException("String does not start with raw prefix"); - inst.push(Arrays.copyOfRange(str, rawPrefix.length, str.length)); - return null; - } + inst.push(Arrays.copyOfRange(str, rawPrefix.length, str.length)); }); } else { diff --git a/bindings/java/src-completable/test/com/apple/foundationdb/test/AsyncStackTester.java b/bindings/java/src-completable/test/com/apple/foundationdb/test/AsyncStackTester.java index 332d960811..3ae2f247e7 100644 --- a/bindings/java/src-completable/test/com/apple/foundationdb/test/AsyncStackTester.java +++ b/bindings/java/src-completable/test/com/apple/foundationdb/test/AsyncStackTester.java @@ -81,11 +81,11 @@ public class AsyncStackTester { System.out.println(inst.context.preStr + " - " + "Pushing null"); else System.out.println(inst.context.preStr + " - " + "Pushing item of type " + item.getClass().getName());*/ - return CompletableFuture.completedFuture(null); + return AsyncUtil.DONE; } else if(op == StackOperation.POP) { inst.pop(); - return CompletableFuture.completedFuture(null); + return AsyncUtil.DONE; } else if(op == StackOperation.DUP) { if(inst.size() == 0) @@ -93,11 +93,11 @@ public class AsyncStackTester { StackEntry e = inst.pop(); inst.push(e); inst.push(e); - return CompletableFuture.completedFuture(null); + return AsyncUtil.DONE; } else if(op == StackOperation.EMPTY_STACK) { inst.clear(); - return CompletableFuture.completedFuture(null); + return AsyncUtil.DONE; } else if(op == StackOperation.SWAP) { return inst.popParam() @@ -152,7 +152,7 @@ public class AsyncStackTester { } else if(op == StackOperation.NEW_TRANSACTION) { inst.context.newTransaction(); - return CompletableFuture.completedFuture(null); + return AsyncUtil.DONE; } else if(op == StackOperation.USE_TRANSACTION) { return inst.popParam() @@ -173,7 +173,7 @@ public class AsyncStackTester { @Override public CompletableFuture apply(Transaction tr) { tr.set((byte[])params.get(0), (byte[])params.get(1)); - return CompletableFuture.completedFuture(null); + return AsyncUtil.DONE; } }); } @@ -188,7 +188,7 @@ public class AsyncStackTester { @Override public CompletableFuture apply(Transaction tr) { tr.clear((byte[])param); - return CompletableFuture.completedFuture(null); + return AsyncUtil.DONE; } }); } @@ -202,7 +202,7 @@ public class AsyncStackTester { @Override public CompletableFuture apply(Transaction tr) { tr.clear((byte[])params.get(0), (byte[])params.get(1)); - return CompletableFuture.completedFuture(null); + return AsyncUtil.DONE; } }); } @@ -216,7 +216,7 @@ public class AsyncStackTester { @Override public CompletableFuture apply(Transaction tr) { tr.clear(Range.startsWith((byte[])param)); - return CompletableFuture.completedFuture(null); + return AsyncUtil.DONE; } }); } @@ -232,7 +232,7 @@ public class AsyncStackTester { @Override public CompletableFuture apply(Transaction tr) { tr.mutate(optype, (byte[])params.get(1), (byte[])params.get(2)); - return CompletableFuture.completedFuture(null); + return AsyncUtil.DONE; } } ); @@ -241,15 +241,15 @@ public class AsyncStackTester { } else if(op == StackOperation.COMMIT) { inst.push(inst.tr.commit()); - return CompletableFuture.completedFuture(null); + return AsyncUtil.DONE; } else if(op == StackOperation.RESET) { inst.context.newTransaction(); - return CompletableFuture.completedFuture(null); + return AsyncUtil.DONE; } else if(op == StackOperation.CANCEL) { inst.tr.cancel(); - return CompletableFuture.completedFuture(null); + return AsyncUtil.DONE; } else if(op == StackOperation.READ_CONFLICT_RANGE) { return inst.popParams(2).thenApplyAsync(new Function, Void>() { @@ -293,7 +293,7 @@ public class AsyncStackTester { } else if(op == StackOperation.DISABLE_WRITE_CONFLICT) { inst.tr.options().setNextWriteNoWriteConflictRange(); - return CompletableFuture.completedFuture(null); + return AsyncUtil.DONE; } else if(op == StackOperation.GET) { return inst.popParam().thenApplyAsync(new Function() { @@ -378,7 +378,7 @@ public class AsyncStackTester { StackUtils.pushError(inst, e); } - return CompletableFuture.completedFuture(null); + return AsyncUtil.DONE; } else if(op == StackOperation.GET_VERSIONSTAMP) { try { @@ -388,13 +388,13 @@ public class AsyncStackTester { StackUtils.pushError(inst, e); } - return CompletableFuture.completedFuture(null); + return AsyncUtil.DONE; } else if(op == StackOperation.SET_READ_VERSION) { if(inst.context.lastVersion == null) throw new IllegalArgumentException("Read version has not been read"); inst.tr.setReadVersion(inst.context.lastVersion); - return CompletableFuture.completedFuture(null); + return AsyncUtil.DONE; } else if(op == StackOperation.ON_ERROR) { return inst.popParam().thenComposeAsync(new Function>() { @@ -429,7 +429,7 @@ public class AsyncStackTester { } inst.push(f); - return CompletableFuture.completedFuture(null); + return AsyncUtil.DONE; } }); } @@ -693,7 +693,7 @@ public class AsyncStackTester { tr.set(pk, pv.length < 40000 ? pv : Arrays.copyOfRange(pv, 0, 40000)); } - return CompletableFuture.completedFuture(null); + return AsyncUtil.DONE; }); } private static CompletableFuture logStack(final Instruction inst, final byte[] prefix, int i) { @@ -794,7 +794,7 @@ public class AsyncStackTester { FDBException ex = StackUtils.getRootFDBException(e); if(ex != null) { StackUtils.pushError(inst, ex); - return CompletableFuture.completedFuture(null); + return AsyncUtil.DONE; } else { CompletableFuture f = new CompletableFuture<>(); @@ -829,7 +829,7 @@ public class AsyncStackTester { public CompletableFuture apply(List next) { if(next.size() < 1) { //System.out.println("No key found after: " + ByteArrayUtil.printable(nextKey.getKey())); - return CompletableFuture.completedFuture(null); + return AsyncUtil.DONE; } operations = next; From 33f8b2f7cf142f758e6a43488b3fe151d49d8f7f Mon Sep 17 00:00:00 2001 From: Alec Grieser Date: Wed, 13 Dec 2017 16:16:31 -0800 Subject: [PATCH 02/10] added a style guide ; fixed errors found from the style guide ; updated tests to use java 8 closures --- bindings/java/fdb-java-style.xml | 148 ++++ .../foundationdb/tuple/ArrayUtilTests.java | 1 - .../main/com/apple/foundationdb/Cluster.java | 4 +- .../main/com/apple/foundationdb/FDB.java | 13 +- .../com/apple/foundationdb/FDBDatabase.java | 22 +- .../apple/foundationdb/FDBTransaction.java | 9 +- .../main/com/apple/foundationdb/JNIUtil.java | 2 + .../com/apple/foundationdb/KeySelector.java | 20 +- .../com/apple/foundationdb/LocalityUtil.java | 6 +- .../com/apple/foundationdb/NativeFuture.java | 4 +- .../foundationdb/NativeObjectWrapper.java | 9 +- .../com/apple/foundationdb/OptionsSet.java | 8 +- .../main/com/apple/foundationdb/Range.java | 6 +- .../foundationdb/ReadTransactionContext.java | 1 - .../com/apple/foundationdb/Transaction.java | 1 + .../apple/foundationdb/async/AsyncUtil.java | 119 ++- .../directory/DirectoryLayer.java | 182 +++-- .../directory/DirectoryPartition.java | 127 +-- .../directory/DirectorySubspace.java | 156 ++-- .../foundationdb/directory/DirectoryUtil.java | 2 + .../directory/MismatchedLayerException.java | 4 +- .../foundationdb/directory/PathUtil.java | 2 + .../apple/foundationdb/subspace/Subspace.java | 5 +- .../foundationdb/tuple/ByteArrayUtil.java | 18 +- .../com/apple/foundationdb/tuple/Tuple.java | 7 +- .../apple/foundationdb/tuple/TupleUtil.java | 18 +- .../foundationdb/test/AbstractTester.java | 6 +- .../test/AsyncPerformanceTester.java | 28 - .../foundationdb/test/AsyncStackTester.java | 744 +++++++----------- .../foundationdb/test/BlockingBenchmark.java | 89 +-- .../test/ConcurrentGetSetGet.java | 89 +-- .../com/apple/foundationdb/test/Context.java | 15 +- .../foundationdb/test/ContinuousSample.java | 41 +- .../foundationdb/test/DirectoryTest.java | 46 +- .../foundationdb/test/DirectoryUtil.java | 79 +- .../com/apple/foundationdb/test/Example.java | 38 +- .../apple/foundationdb/test/Instruction.java | 6 +- .../apple/foundationdb/test/IterableTest.java | 15 +- .../foundationdb/test/LocalityTests.java | 15 +- .../foundationdb/test/ParallelRandomScan.java | 50 +- .../foundationdb/test/PerformanceTester.java | 14 +- .../apple/foundationdb/test/RYWBenchmark.java | 13 +- .../apple/foundationdb/test/RangeTest.java | 31 +- .../foundationdb/test/SerialInsertion.java | 1 + .../foundationdb/test/SerialIteration.java | 2 + .../apple/foundationdb/test/SerialTest.java | 20 +- .../apple/foundationdb/test/StackTester.java | 75 +- .../apple/foundationdb/test/StackUtils.java | 3 +- .../apple/foundationdb/test/TesterArgs.java | 25 +- .../apple/foundationdb/test/TupleTest.java | 26 +- .../test/VersionstampSmokeTest.java | 26 +- .../apple/foundationdb/test/WatchTest.java | 29 +- .../foundationdb/test/WhileTrueTest.java | 5 +- bindings/java/suppressions.xml | 14 + 54 files changed, 1218 insertions(+), 1221 deletions(-) create mode 100644 bindings/java/fdb-java-style.xml delete mode 100644 bindings/java/src-completable/test/com/apple/foundationdb/test/AsyncPerformanceTester.java create mode 100644 bindings/java/suppressions.xml diff --git a/bindings/java/fdb-java-style.xml b/bindings/java/fdb-java-style.xml new file mode 100644 index 0000000000..15cacc6fe2 --- /dev/null +++ b/bindings/java/fdb-java-style.xml @@ -0,0 +1,148 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bindings/java/src-completable/junit/com/apple/foundationdb/tuple/ArrayUtilTests.java b/bindings/java/src-completable/junit/com/apple/foundationdb/tuple/ArrayUtilTests.java index 5f6400fad9..a94a1ba8e7 100644 --- a/bindings/java/src-completable/junit/com/apple/foundationdb/tuple/ArrayUtilTests.java +++ b/bindings/java/src-completable/junit/com/apple/foundationdb/tuple/ArrayUtilTests.java @@ -29,7 +29,6 @@ import static org.junit.Assert.fail; import java.util.ArrayList; import java.util.List; -import com.apple.foundationdb.tuple.ByteArrayUtil; import org.junit.Test; /** diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/Cluster.java b/bindings/java/src-completable/main/com/apple/foundationdb/Cluster.java index cf3664a7bd..a44ea494a4 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/Cluster.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/Cluster.java @@ -55,7 +55,9 @@ public class Cluster extends NativeObjectWrapper { * * @return a set of cluster-specific options affecting this {@code Cluster} */ - public ClusterOptions options() { return options; } + public ClusterOptions options() { + return options; + } @Override protected void finalize() throws Throwable { diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/FDB.java b/bindings/java/src-completable/main/com/apple/foundationdb/FDB.java index 41b8e47d18..1f80cbd4ff 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/FDB.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/FDB.java @@ -82,7 +82,7 @@ public class FDB { private volatile boolean netStarted = false; private volatile boolean netStopped = false; volatile boolean warnOnUnclosed = true; - final private Semaphore netRunning = new Semaphore(1); + private final Semaphore netRunning = new Semaphore(1); private final NetworkOptions options; static { @@ -116,7 +116,9 @@ public class FDB { * * @return a set of options affecting this instance of the FoundationDB API */ - public NetworkOptions options() { return options; } + public NetworkOptions options() { + return options; + } /** * Select the version for the client API. An exception will be thrown if the @@ -135,7 +137,7 @@ public class FDB { * * @return the FoundationDB API object */ - public synchronized static FDB selectAPIVersion(final int version) throws FDBException { + public static synchronized FDB selectAPIVersion(final int version) throws FDBException { if(singleton != null) { if(version != singleton.apiVersion) { throw new IllegalArgumentException( @@ -398,7 +400,10 @@ public class FDB { // that we will never again be able to call runNetwork() netRunning.acquire(); return; - } catch (InterruptedException e) {} + } catch (InterruptedException e) { + // If the thread is interrupted while trying to acquire + // the semaphore, we just want to try again. + } } } diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/FDBDatabase.java b/bindings/java/src-completable/main/com/apple/foundationdb/FDBDatabase.java index b719eaad07..50c648a6de 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/FDBDatabase.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/FDBDatabase.java @@ -77,17 +77,17 @@ class FDBDatabase extends NativeObjectWrapper implements Database, OptionConsume trRef.get().commit().thenApply(o -> { returnValue.set(returnVal); return false; - }) - , e), (value, t) -> { - if(t == null) - return CompletableFuture.completedFuture(value); - if(!(t instanceof RuntimeException)) - throw new CompletionException(t); - return trRef.get().onError(t).thenApply(newTr -> { - trRef.set(newTr); - return true; - }); - }, e); + }), e), + (value, t) -> { + if(t == null) + return CompletableFuture.completedFuture(value); + if(!(t instanceof RuntimeException)) + throw new CompletionException(t); + return trRef.get().onError(t).thenApply(newTr -> { + trRef.set(newTr); + return true; + }); + }, e); }, e) .thenApply(o -> returnValue.get()) .whenComplete((v, t) -> trRef.get().close()); diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/FDBTransaction.java b/bindings/java/src-completable/main/com/apple/foundationdb/FDBTransaction.java index 26d203aeb8..73631331e6 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/FDBTransaction.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/FDBTransaction.java @@ -26,7 +26,8 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; import java.util.function.Function; -import com.apple.foundationdb.async.*; +import com.apple.foundationdb.async.AsyncIterable; +import com.apple.foundationdb.async.AsyncUtil; import com.apple.foundationdb.tuple.ByteArrayUtil; class FDBTransaction extends NativeObjectWrapper implements Transaction, OptionConsumer { @@ -183,7 +184,7 @@ class FDBTransaction extends NativeObjectWrapper implements Transaction, OptionC public CompletableFuture getReadVersion() { pointerReadLock.lock(); try { - return new FutureVersion( Transaction_getReadVersion(getPtr()), executor); + return new FutureVersion(Transaction_getReadVersion(getPtr()), executor); } finally { pointerReadLock.unlock(); } @@ -200,7 +201,7 @@ class FDBTransaction extends NativeObjectWrapper implements Transaction, OptionC private CompletableFuture get_internal(byte[] key, boolean isSnapshot) { pointerReadLock.lock(); try { - return new FutureResult( Transaction_get(getPtr(), key, isSnapshot), executor); + return new FutureResult(Transaction_get(getPtr(), key, isSnapshot), executor); } finally { pointerReadLock.unlock(); } @@ -217,7 +218,7 @@ class FDBTransaction extends NativeObjectWrapper implements Transaction, OptionC private CompletableFuture getKey_internal(KeySelector selector, boolean isSnapshot) { pointerReadLock.lock(); try { - return new FutureKey( Transaction_getKey(getPtr(), + return new FutureKey(Transaction_getKey(getPtr(), selector.getKey(), selector.orEqual(), selector.getOffset(), isSnapshot), executor); } finally { pointerReadLock.unlock(); diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/JNIUtil.java b/bindings/java/src-completable/main/com/apple/foundationdb/JNIUtil.java index cdb9d377ff..b7398eb727 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/JNIUtil.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/JNIUtil.java @@ -179,4 +179,6 @@ class JNIUtil { return OS.OSX; throw new IllegalStateException("Unknown or unsupported OS: " + osname); } + + private JNIUtil() {} } diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/KeySelector.java b/bindings/java/src-completable/main/com/apple/foundationdb/KeySelector.java index 7607d4888c..4a5b1c052b 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/KeySelector.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/KeySelector.java @@ -71,8 +71,8 @@ public class KeySelector { * * @return a newly created {@code KeySelector} */ - public static KeySelector lastLessThan( byte[] key ) { - return new KeySelector( key, false, 0 ); + public static KeySelector lastLessThan(byte[] key) { + return new KeySelector(key, false, 0); } /** @@ -82,8 +82,8 @@ public class KeySelector { * * @return a newly created {@code KeySelector} */ - public static KeySelector lastLessOrEqual( byte[] key ) { - return new KeySelector( key, true, 0 ); + public static KeySelector lastLessOrEqual(byte[] key) { + return new KeySelector(key, true, 0); } /** @@ -93,8 +93,8 @@ public class KeySelector { * * @return a newly created {@code KeySelector} */ - public static KeySelector firstGreaterThan( byte[] key ) { - return new KeySelector( key, true, +1 ); + public static KeySelector firstGreaterThan(byte[] key) { + return new KeySelector(key, true, +1); } /** @@ -104,8 +104,8 @@ public class KeySelector { * * @return a newly created {@code KeySelector} */ - public static KeySelector firstGreaterOrEqual( byte[] key ) { - return new KeySelector( key, false, +1 ); + public static KeySelector firstGreaterOrEqual(byte[] key) { + return new KeySelector(key, false, +1); } /** @@ -126,8 +126,8 @@ public class KeySelector { * * @return a newly created {@code KeySelector} that is offset by a number of keys. */ - public KeySelector add( int offset ) { - return new KeySelector( getKey(), orEqual(), getOffset() + offset ); + public KeySelector add(int offset) { + return new KeySelector(getKey(), orEqual(), getOffset() + offset); } /** diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/LocalityUtil.java b/bindings/java/src-completable/main/com/apple/foundationdb/LocalityUtil.java index 40e5f25180..55cd594af4 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/LocalityUtil.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/LocalityUtil.java @@ -209,8 +209,8 @@ public class LocalityUtil { @Override public void remove() { - throw new UnsupportedOperationException("Boundary keys are read-only"); - } + throw new UnsupportedOperationException("Boundary keys are read-only"); + } @Override public void close() { @@ -232,7 +232,7 @@ public class LocalityUtil { } } - private static Charset ASCII = Charset.forName("US-ASCII"); + private static final Charset ASCII = Charset.forName("US-ASCII"); static byte[] keyServersForKey(byte[] key) { return ByteArrayUtil.join(new byte[] { (byte)255 }, "/keyServers/".getBytes(ASCII), diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/NativeFuture.java b/bindings/java/src-completable/main/com/apple/foundationdb/NativeFuture.java index b63c115b13..b17629eab9 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/NativeFuture.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/NativeFuture.java @@ -82,7 +82,7 @@ abstract class NativeFuture extends CompletableFuture implements AutoClose close(); } - abstract protected T getIfDone_internal(long cPtr) throws FDBException; + protected abstract T getIfDone_internal(long cPtr) throws FDBException; @Override public void close() { @@ -122,7 +122,7 @@ abstract class NativeFuture extends CompletableFuture implements AutoClose // we must have a read lock for this function to make sense, however it // does not make sense to take the lock here, since the code that uses // the result must inherently have the read lock itself. - assert( rwl.getReadHoldCount() > 0 ); + assert(rwl.getReadHoldCount() > 0); if(cPtr == 0) throw new IllegalStateException("Cannot access closed object"); diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/NativeObjectWrapper.java b/bindings/java/src-completable/main/com/apple/foundationdb/NativeObjectWrapper.java index b2e89dbfbf..9366d37c0a 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/NativeObjectWrapper.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/NativeObjectWrapper.java @@ -40,7 +40,7 @@ abstract class NativeObjectWrapper implements AutoCloseable { // we must have a read lock for this function to make sense, however it // does not make sense to take the lock here, since the code that uses // the result must inherently have the read lock itself. - assert( rwl.getReadHoldCount() > 0 ); + assert(rwl.getReadHoldCount() > 0); return closed; } @@ -51,7 +51,10 @@ abstract class NativeObjectWrapper implements AutoCloseable { System.err.println(context + " not closed"); } } - catch(Exception e) {} + catch(Exception e) { + // Eat this error. This is called from the finalizer, + // so there isn't much we can do. + } } @Override @@ -76,7 +79,7 @@ abstract class NativeObjectWrapper implements AutoCloseable { // we must have a read lock for this function to make sense, however it // does not make sense to take the lock here, since the code that uses // the result must inherently have the read lock itself. - assert( rwl.getReadHoldCount() > 0 ); + assert(rwl.getReadHoldCount() > 0); if(this.closed) throw new IllegalStateException("Cannot access closed object"); diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/OptionsSet.java b/bindings/java/src-completable/main/com/apple/foundationdb/OptionsSet.java index abe2d93455..638a64e1c8 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/OptionsSet.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/OptionsSet.java @@ -25,7 +25,7 @@ import java.nio.ByteOrder; import java.nio.charset.Charset; abstract class OptionsSet { - private final static Charset CHARSET_UTF8 = Charset.forName("UTF-8"); + private static final Charset CHARSET_UTF8 = Charset.forName("UTF-8"); OptionConsumer consumer; public OptionsSet(OptionConsumer provider) { @@ -39,7 +39,9 @@ abstract class OptionsSet { * * @return target of option set calls */ - public OptionConsumer getOptionConsumer() { return consumer; } + public OptionConsumer getOptionConsumer() { + return consumer; + } protected void setOption(int code) { consumer.setOption(code, null); @@ -57,6 +59,6 @@ abstract class OptionsSet { ByteBuffer b = ByteBuffer.allocate(8); b.order(ByteOrder.LITTLE_ENDIAN); b.putLong(param); - consumer.setOption(code, b.array() ); + consumer.setOption(code, b.array()); } } diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/Range.java b/bindings/java/src-completable/main/com/apple/foundationdb/Range.java index bb2c460bd3..a718ede600 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/Range.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/Range.java @@ -64,7 +64,7 @@ public class Range { public static Range startsWith(byte[] prefix) { if(prefix == null) throw new NullPointerException("prefix cannot be null"); - return new Range( prefix, ByteArrayUtil.strinc(prefix) ); + return new Range(prefix, ByteArrayUtil.strinc(prefix)); } /** @@ -113,7 +113,7 @@ public class Range { */ @Override public String toString() { - return "Range(" + (begin == null ? "null" : "\"" + ByteArrayUtil.printable(begin) + "\"") - + ", " + (end == null ? "null" : "\"" + ByteArrayUtil.printable(end) + "\"") + ")"; + return "Range(" + (begin == null ? "null" : "\"" + ByteArrayUtil.printable(begin) + "\"") + + ", " + (end == null ? "null" : "\"" + ByteArrayUtil.printable(end) + "\"") + ")"; } } \ No newline at end of file diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/ReadTransactionContext.java b/bindings/java/src-completable/main/com/apple/foundationdb/ReadTransactionContext.java index 3213977e02..fcb145bc9c 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/ReadTransactionContext.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/ReadTransactionContext.java @@ -21,7 +21,6 @@ package com.apple.foundationdb; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; import java.util.function.Function; diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/Transaction.java b/bindings/java/src-completable/main/com/apple/foundationdb/Transaction.java index 79291b5862..4d2459aa8b 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/Transaction.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/Transaction.java @@ -22,6 +22,7 @@ package com.apple.foundationdb; import java.util.concurrent.CompletableFuture; import java.util.function.Function; + import com.apple.foundationdb.tuple.Tuple; /** diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/async/AsyncUtil.java b/bindings/java/src-completable/main/com/apple/foundationdb/async/AsyncUtil.java index 3bf4d106e6..5a45f614a3 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/async/AsyncUtil.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/async/AsyncUtil.java @@ -51,7 +51,7 @@ public class AsyncUtil { * @return the output of {@code func}, or a {@code CompletableFuture} carrying any exception * caught in the process. */ - public static CompletableFuture applySafely( Function> func, I value ) { + public static CompletableFuture applySafely(Function> func, I value) { try { return func.apply(value); } catch (RuntimeException e) { @@ -61,18 +61,74 @@ public class AsyncUtil { } } + /** + * Run the {@code consumer} on each element of the iterable in order. The future will + * complete with either the first error encountered by either the iterable itself + * or by the consumer provided or with {@code null} if the future completes + * successfully. Items are processed in order from the iterable, and each item + * will be processed only after the item before it has finished processing. + * + * @param iterable the source of data over from which to consume + * @param consumer operation to apply to each item + * @param type of the items returned by the iterable + * + * @return a future that is ready once the asynchronous operation completes + */ public static CompletableFuture forEach(final AsyncIterable iterable, final Consumer consumer) { return forEach(iterable.iterator(), consumer); } + /** + * Run the {@code consumer} on each element of the iterable in order. The future will + * complete with either the first error encountered by either the iterable itself + * or by the consumer provided or with {@code null} if the future completes + * successfully. Items are processed in order from the iterable, and each item + * will be processed only after the item before it has finished processing. Asynchronous + * tasks needed to complete this operation are scheduled on the provided executor. + * + * @param iterable the source of data over from which to consume + * @param consumer operation to apply to each item + * @param executor executor on which to schedule asynchronous tasks + * @param type of the items returned by the iterable + * + * @return a future that is ready once the asynchronous operation completes + */ public static CompletableFuture forEach(final AsyncIterable iterable, final Consumer consumer, final Executor executor) { return forEach(iterable.iterator(), consumer, executor); } + /** + * Run the {@code consumer} on each element of the iterator in order. The future will + * complete with either the first error encountered by either the iterator itself + * or by the consumer provided or with {@code null} if the future completes + * successfully. Items are processed in order from the iterator, and each item + * will be processed only after the item before it has finished processing. + * + * @param iterator the source of data over from which to consume + * @param consumer operation to apply to each item + * @param type of the items returned by the iterator + * + * @return a future that is ready once the asynchronous operation completes + */ public static CompletableFuture forEach(final AsyncIterator iterator, final Consumer consumer) { return forEach(iterator, consumer, DEFAULT_EXECUTOR); } + /** + * Run the {@code consumer} on each element of the iterator in order. The future will + * complete with either the first error encountered by either the iterator itself + * or by the consumer provided or with {@code null} if the future completes + * successfully. Items are processed in order from the iterator, and each item + * will be processed only after the item before it has finished processing. Asynchronous + * tasks needed to complete this operation are scheduled on the provided executor. + * + * @param iterator the source of data over from which to consume + * @param consumer operation to apply to each item + * @param executor executor on which to schedule asynchronous tasks + * @param type of the items returned by the iterator + * + * @return a future that is ready once the asynchronous operation completes + */ public static CompletableFuture forEach(final AsyncIterator iterator, final Consumer consumer, final Executor executor) { return iterator.onHasNext().thenComposeAsync(hasAny -> { if (hasAny) { @@ -387,16 +443,65 @@ public class AsyncUtil { }); } - public static CompletableFuture composeHandle(CompletableFuture future, BiFunction> fn) { - return future.handle(fn).thenCompose(Function.identity()); + /** + * Compose a handler bi-function to the result of a future. Unlike the + * {@link CompletableFuture#handle(BiFunction) CompletableFuture.handle()} + * function, which requires that the handler return a regular value, this + * method requires that the handler return a {@link CompletableFuture}. + * The returned future will then be ready with the result of the + * handler's future (or an error if that future completes exceptionally). + * + * @param future future to compose the handler onto + * @param handler handler bi-function to compose onto the passed future + * @param return type of original future + * @param return type of final future + * + * @return future with same completion properties as the future returned by the handler + */ + public static CompletableFuture composeHandle(CompletableFuture future, BiFunction> handler) { + return future.handle(handler).thenCompose(Function.identity()); } - public static CompletableFuture composeHandleAsync(CompletableFuture future, BiFunction> fn) { - return composeHandleAsync(future, fn, DEFAULT_EXECUTOR); + /** + * Compose a handler bi-function to the result of a future. Unlike the + * {@link CompletableFuture#handle(BiFunction) CompletableFuture.handle()} + * function, which requires that the handler return a regular value, this + * method requires that the handler return a {@link CompletableFuture}. + * The returned future will then be ready with the result of the + * handler's future (or an error if that future completes exceptionally). + * The handler will execute on the {@link com.apple.foundationdb.FDB#DEFAULT_EXECUTOR default executor} + * used for asychronous tasks. + * + * @param future future to compose the handler onto + * @param handler handler bi-function to compose onto the passed future + * @param return type of original future + * @param return type of final future + * + * @return future with same completion properties as the future returned by the handler + */ + public static CompletableFuture composeHandleAsync(CompletableFuture future, BiFunction> handler) { + return composeHandleAsync(future, handler, DEFAULT_EXECUTOR); } - public static CompletableFuture composeHandleAsync(CompletableFuture future, BiFunction> fn, Executor executor) { - return future.handleAsync(fn, executor).thenCompose(Function.identity()); + /** + * Compose a handler bi-function to the result of a future. Unlike the + * {@link CompletableFuture#handle(BiFunction) CompletableFuture.handle()} + * function, which requires that the handler return a regular value, this + * method requires that the handler return a {@link CompletableFuture}. + * The returned future will then be ready with the result of the + * handler's future (or an error if that future completes excpetionally). + * The handler will execute on the passed {@link Executor}. + * + * @param future future to compose the handler onto + * @param handler handler bi-function to compose onto the passed future + * @param executor executor on which to execute the handler function + * @param return type of original future + * @param return type of final future + * + * @return future with same completion properties as the future returned by the handler + */ + public static CompletableFuture composeHandleAsync(CompletableFuture future, BiFunction> handler, Executor executor) { + return future.handleAsync(handler, executor).thenCompose(Function.identity()); } /** diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/directory/DirectoryLayer.java b/bindings/java/src-completable/main/com/apple/foundationdb/directory/DirectoryLayer.java index ef078b8a97..1d7aeba10d 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/directory/DirectoryLayer.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/directory/DirectoryLayer.java @@ -66,8 +66,7 @@ import com.apple.foundationdb.tuple.Tuple; * access to subspaces. *

*/ -public class DirectoryLayer implements Directory -{ +public class DirectoryLayer implements Directory { private static final Charset UTF_8 = Charset.forName("UTF-8"); private static final byte[] LITTLE_ENDIAN_LONG_ONE = { 1, 0, 0, 0, 0, 0, 0, 0 }; private static final byte[] HIGH_CONTENTION_KEY = "hca".getBytes(UTF_8); @@ -181,22 +180,22 @@ public class DirectoryLayer implements Directory * Creates a new {@code DirectoryLayer} formed with a specified node subspace and default content subspace. * Prefixes can not be specified in calls to {@link Directory#create(TransactionContext, List, byte[], byte[])}. * - * @param node_subspace a {@link Subspace} used to store directory metadata - * @return a {@code DirectoryLayer} formed with {@code node_subspace} and a default content subspace + * @param nodeSubspace a {@link Subspace} used to store directory metadata + * @return a {@code DirectoryLayer} formed with {@code nodeSubspace} and a default content subspace */ - public static Directory createWithNodeSubspace(Subspace node_subspace) { - return new DirectoryLayer(node_subspace, DEFAULT_CONTENT_SUBSPACE); + public static Directory createWithNodeSubspace(Subspace nodeSubspace) { + return new DirectoryLayer(nodeSubspace, DEFAULT_CONTENT_SUBSPACE); } /** * Creates a new {@code DirectoryLayer} formed with a default node subspace and specified content subspace. * Prefixes can not be specified in calls to {@link Directory#create(TransactionContext, List, byte[], byte[])}. * - * @param content_subspace a {@link Subspace} used to store directory content - * @return a {@code DirectoryLayer} formed with a {@code content_subspace} and a default node subspace + * @param contentSubspace a {@link Subspace} used to store directory content + * @return a {@code DirectoryLayer} formed with a {@code contentSubspace} and a default node subspace */ - public static Directory createWithContentSubspace(Subspace content_subspace) { - return new DirectoryLayer(DEFAULT_NODE_SUBSPACE, content_subspace); + public static Directory createWithContentSubspace(Subspace contentSubspace) { + return new DirectoryLayer(DEFAULT_NODE_SUBSPACE, contentSubspace); } /** @@ -229,9 +228,9 @@ public class DirectoryLayer implements Directory } DirectoryLayer other = (DirectoryLayer)rhs; - return (path == other.path || path.equals(other.path)) - && nodeSubspace.equals(other.nodeSubspace) - && contentSubspace.equals(other.contentSubspace); + return (path == other.path || path.equals(other.path)) && + nodeSubspace.equals(other.nodeSubspace) && + contentSubspace.equals(other.contentSubspace); } /** @@ -410,47 +409,46 @@ public class DirectoryLayer implements Directory final List newPathCopy = new ArrayList<>(newPath); return tcx.runAsync(tr -> checkOrWriteVersion(tr).thenComposeAsync(ignore -> { - if(oldPathCopy.size() <= newPathCopy.size() && oldPathCopy.equals(newPathCopy.subList(0, oldPathCopy.size()))) - throw new DirectoryMoveException("The destination directory cannot be a subdirectory of the source directory.", toAbsolutePath(oldPathCopy), toAbsolutePath(newPathCopy)); + if(oldPathCopy.size() <= newPathCopy.size() && oldPathCopy.equals(newPathCopy.subList(0, oldPathCopy.size()))) + throw new DirectoryMoveException("The destination directory cannot be a subdirectory of the source directory.", toAbsolutePath(oldPathCopy), toAbsolutePath(newPathCopy)); - ArrayList> futures = new ArrayList<>(); - futures.add(new NodeFinder(oldPathCopy).find(tr).thenComposeAsync(new NodeMetadataLoader(tr), tr.getExecutor())); - futures.add(new NodeFinder(newPathCopy).find(tr).thenComposeAsync(new NodeMetadataLoader(tr), tr.getExecutor())); + ArrayList> futures = new ArrayList<>(); + futures.add(new NodeFinder(oldPathCopy).find(tr).thenComposeAsync(new NodeMetadataLoader(tr), tr.getExecutor())); + futures.add(new NodeFinder(newPathCopy).find(tr).thenComposeAsync(new NodeMetadataLoader(tr), tr.getExecutor())); - return AsyncUtil.getAll(futures); - }, tr.getExecutor()) - .thenComposeAsync(nodes -> { - final Node oldNode = nodes.get(0); - final Node newNode = nodes.get(1); + return AsyncUtil.getAll(futures); + }, tr.getExecutor()) + .thenComposeAsync(nodes -> { + final Node oldNode = nodes.get(0); + final Node newNode = nodes.get(1); - if(!oldNode.exists()) - throw new NoSuchDirectoryException(toAbsolutePath(oldPathCopy)); + if(!oldNode.exists()) + throw new NoSuchDirectoryException(toAbsolutePath(oldPathCopy)); - if(oldNode.isInPartition(false) || newNode.isInPartition(false)) { - if(!oldNode.isInPartition(false) || !newNode.isInPartition(false) || !oldNode.path.equals(newNode.path)) - throw new DirectoryMoveException("Cannot move between partitions.", toAbsolutePath(oldPathCopy), toAbsolutePath(newPathCopy)); + if(oldNode.isInPartition(false) || newNode.isInPartition(false)) { + if(!oldNode.isInPartition(false) || !newNode.isInPartition(false) || !oldNode.path.equals(newNode.path)) + throw new DirectoryMoveException("Cannot move between partitions.", toAbsolutePath(oldPathCopy), toAbsolutePath(newPathCopy)); - return newNode.getContents().move(tr, oldNode.getPartitionSubpath(), newNode.getPartitionSubpath()); - } + return newNode.getContents().move(tr, oldNode.getPartitionSubpath(), newNode.getPartitionSubpath()); + } - if(newNode.exists()) - throw new DirectoryAlreadyExistsException(toAbsolutePath(newPathCopy)); + if(newNode.exists()) + throw new DirectoryAlreadyExistsException(toAbsolutePath(newPathCopy)); - final List parentPath = PathUtil.popBack(newPathCopy); - return new NodeFinder(parentPath).find(tr).thenComposeAsync(parentNode -> { - if(!parentNode.exists()) - throw new NoSuchDirectoryException(toAbsolutePath(parentPath)); + final List parentPath = PathUtil.popBack(newPathCopy); + return new NodeFinder(parentPath).find(tr).thenComposeAsync(parentNode -> { + if(!parentNode.exists()) + throw new NoSuchDirectoryException(toAbsolutePath(parentPath)); - tr.set( - parentNode.subspace.get(SUB_DIR_KEY).get(getLast(newPathCopy)).getKey(), - contentsOfNode(oldNode.subspace, EMPTY_PATH, EMPTY_BYTES).getKey() - ); + tr.set( + parentNode.subspace.get(SUB_DIR_KEY).get(getLast(newPathCopy)).getKey(), + contentsOfNode(oldNode.subspace, EMPTY_PATH, EMPTY_BYTES).getKey() + ); - return removeFromParent(tr, oldPathCopy) + return removeFromParent(tr, oldPathCopy) .thenApply(ignore -> contentsOfNode(oldNode.subspace, newPathCopy, oldNode.layer)); - }, tr.getExecutor()); - }, tr.getExecutor()) - ); + }, tr.getExecutor()); + }, tr.getExecutor())); } /** @@ -528,8 +526,8 @@ public class DirectoryLayer implements Directory return AsyncUtil.collect( AsyncUtil.mapIterable(tr.getRange(subdir.range()), - kv -> subdir.unpack(kv.getKey()).getString(0), - tr.getExecutor() + kv -> subdir.unpack(kv.getKey()).getString(0), + tr.getExecutor() ) ); }, tr.getExecutor()) @@ -624,29 +622,28 @@ public class DirectoryLayer implements Directory final List pathCopy = new ArrayList<>(path); return tcx.runAsync(tr -> checkOrWriteVersion(tr).thenComposeAsync(ignore -> { - if(pathCopy.size() == 0) - throw new DirectoryException("The root directory cannot be removed.", toAbsolutePath(pathCopy)); + if(pathCopy.size() == 0) + throw new DirectoryException("The root directory cannot be removed.", toAbsolutePath(pathCopy)); - return new NodeFinder(pathCopy).find(tr).thenComposeAsync(new NodeMetadataLoader(tr), tr.getExecutor()); - }, tr.getExecutor()) - .thenComposeAsync(node -> { - if(!node.exists()) { - if(mustExist) - throw new NoSuchDirectoryException(toAbsolutePath(pathCopy)); - else - return AsyncUtil.READY_FALSE; - } + return new NodeFinder(pathCopy).find(tr).thenComposeAsync(new NodeMetadataLoader(tr), tr.getExecutor()); + }, tr.getExecutor()) + .thenComposeAsync(node -> { + if(!node.exists()) { + if(mustExist) + throw new NoSuchDirectoryException(toAbsolutePath(pathCopy)); + else + return AsyncUtil.READY_FALSE; + } - if(node.isInPartition(false)) - return node.getContents().getDirectoryLayer().removeInternal(tr, node.getPartitionSubpath(), mustExist); - else { - ArrayList> futures = new ArrayList<>(); - futures.add(removeRecursive(tr, node.subspace)); - futures.add(removeFromParent(tr, pathCopy)); - return AsyncUtil.tag(AsyncUtil.whenAll(futures), true); - } - }, tr.getExecutor()) - ); + if(node.isInPartition(false)) + return node.getContents().getDirectoryLayer().removeInternal(tr, node.getPartitionSubpath(), mustExist); + else { + ArrayList> futures = new ArrayList<>(); + futures.add(removeRecursive(tr, node.subspace)); + futures.add(removeFromParent(tr, pathCopy)); + return AsyncUtil.tag(AsyncUtil.whenAll(futures), true); + } + }, tr.getExecutor())); } private CompletableFuture removeFromParent(final Transaction tr, final List path) { @@ -706,8 +703,7 @@ public class DirectoryLayer implements Directory final byte[] layer, final byte[] prefix, final boolean allowCreate, - final boolean allowOpen) - { + final boolean allowOpen) { final List pathCopy = new ArrayList<>(path); if(prefix != null && !allowManualPrefixes) { @@ -723,35 +719,34 @@ public class DirectoryLayer implements Directory } return checkVersion(rtr).thenComposeAsync(ignore -> { - // Root directory contains node metadata and so may not be opened. - if(pathCopy.size() == 0) { - throw new IllegalArgumentException("The root directory may not be opened."); - } + // Root directory contains node metadata and so may not be opened. + if(pathCopy.size() == 0) { + throw new IllegalArgumentException("The root directory may not be opened."); + } - return new NodeFinder(pathCopy).find(rtr).thenComposeAsync(new NodeMetadataLoader(rtr), rtr.getExecutor()); - }, rtr.getExecutor()) - .thenComposeAsync(existingNode -> { - if(existingNode.exists()) { - if(existingNode.isInPartition(false)) { - List subpath = existingNode.getPartitionSubpath(); - DirectoryLayer directoryLayer = existingNode.getContents().getDirectoryLayer(); - return directoryLayer.createOrOpenInternal( - rtr, tr, subpath, layer, prefix, allowCreate, allowOpen); - } + return new NodeFinder(pathCopy).find(rtr).thenComposeAsync(new NodeMetadataLoader(rtr), rtr.getExecutor()); + }, rtr.getExecutor()) + .thenComposeAsync(existingNode -> { + if(existingNode.exists()) { + if(existingNode.isInPartition(false)) { + List subpath = existingNode.getPartitionSubpath(); + DirectoryLayer directoryLayer = existingNode.getContents().getDirectoryLayer(); + return directoryLayer.createOrOpenInternal( + rtr, tr, subpath, layer, prefix, allowCreate, allowOpen); + } - DirectorySubspace opened = openInternal(pathCopy, layer, existingNode, allowOpen); - return CompletableFuture.completedFuture(opened); - } - else - return createInternal(tr, pathCopy, layer, prefix, allowCreate); - }, rtr.getExecutor()); + DirectorySubspace opened = openInternal(pathCopy, layer, existingNode, allowOpen); + return CompletableFuture.completedFuture(opened); + } + else + return createInternal(tr, pathCopy, layer, prefix, allowCreate); + }, rtr.getExecutor()); } private DirectorySubspace openInternal(final List path, final byte[] layer, final Node existingNode, - final boolean allowOpen) - { + final boolean allowOpen) { if(!allowOpen) { throw new DirectoryAlreadyExistsException(toAbsolutePath(path)); } @@ -768,8 +763,7 @@ public class DirectoryLayer implements Directory final List path, final byte[] layer, final byte[] prefix, - final boolean allowCreate) - { + final boolean allowCreate) { if(!allowCreate) { throw new NoSuchDirectoryException(toAbsolutePath(path)); } @@ -845,7 +839,7 @@ public class DirectoryLayer implements Directory ByteBuffer versionBuf = ByteBuffer.wrap(versionBytes); versionBuf.order(ByteOrder.LITTLE_ENDIAN); - Integer version[] = new Integer[3]; + Integer[] version = new Integer[3]; for(int i = 0; i < version.length; ++i) version[i] = versionBuf.getInt(); diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/directory/DirectoryPartition.java b/bindings/java/src-completable/main/com/apple/foundationdb/directory/DirectoryPartition.java index c42147921b..06c27960a5 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/directory/DirectoryPartition.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/directory/DirectoryPartition.java @@ -54,21 +54,21 @@ class DirectoryPartition extends DirectorySubspace { this.parentDirectoryLayer = parentDirectoryLayer; } - /** - * Raises an exception because DirectoryPartition cannot be used as a Subspace. - * - * @throws UnsupportedOperationException - */ + /** + * Raises an exception because DirectoryPartition cannot be used as a Subspace. + * + * @throws UnsupportedOperationException + */ @Override public Subspace get(Object o) { throw new UnsupportedOperationException("Cannot open subspace in the root of a directory partition."); } - /** - * Raises an exception because DirectoryPartition cannot be used as a Subspace. - * - * @throws UnsupportedOperationException - */ + /** + * Raises an exception because DirectoryPartition cannot be used as a Subspace. + * + * @throws UnsupportedOperationException + */ @Override public Subspace get(Tuple name) { throw new UnsupportedOperationException("Cannot open subspace in the root of a directory partition."); @@ -84,61 +84,61 @@ class DirectoryPartition extends DirectorySubspace { throw new UnsupportedOperationException("Cannot get key for the root of a directory partition."); } - /** - * Raises an exception because DirectoryPartition cannot be used as a Subspace. - * - * @throws UnsupportedOperationException - */ + /** + * Raises an exception because DirectoryPartition cannot be used as a Subspace. + * + * @throws UnsupportedOperationException + */ @Override public byte[] pack() { throw new UnsupportedOperationException("Cannot pack keys using the root of a directory partition."); } - /** - * Raises an exception because DirectoryPartition cannot be used as a Subspace. - * - * @throws UnsupportedOperationException - */ + /** + * Raises an exception because DirectoryPartition cannot be used as a Subspace. + * + * @throws UnsupportedOperationException + */ @Override public byte[] pack(Object o) { throw new UnsupportedOperationException("Cannot pack keys using the root of a directory partition."); } - /** - * Raises an exception because DirectoryPartition cannot be used as a Subspace. - * - * @throws UnsupportedOperationException - */ + /** + * Raises an exception because DirectoryPartition cannot be used as a Subspace. + * + * @throws UnsupportedOperationException + */ @Override public byte[] pack(Tuple tuple) { throw new UnsupportedOperationException("Cannot pack keys using the root of a directory partition."); } - /** - * Raises an exception because DirectoryPartition cannot be used as a Subspace. - * - * @throws UnsupportedOperationException - */ + /** + * Raises an exception because DirectoryPartition cannot be used as a Subspace. + * + * @throws UnsupportedOperationException + */ @Override public Tuple unpack(byte[] key) { throw new UnsupportedOperationException("Cannot unpack keys using the root of a directory partition."); } - /** - * Raises an exception because DirectoryPartition cannot be used as a Subspace. - * - * @throws UnsupportedOperationException - */ + /** + * Raises an exception because DirectoryPartition cannot be used as a Subspace. + * + * @throws UnsupportedOperationException + */ @Override public Range range() { throw new UnsupportedOperationException("Cannot get range for the root of a directory partition."); } - /** - * Raises an exception because DirectoryPartition cannot be used as a Subspace. - * - * @throws UnsupportedOperationException - */ + /** + * Raises an exception because DirectoryPartition cannot be used as a Subspace. + * + * @throws UnsupportedOperationException + */ @Override public Range range(Tuple tuple) { throw new UnsupportedOperationException("Cannot get range for the root of a directory partition."); @@ -154,11 +154,11 @@ class DirectoryPartition extends DirectorySubspace { throw new UnsupportedOperationException("Cannot check whether a key belongs to the root of a directory partition."); } - /** - * Raises an exception because DirectoryPartition cannot be used as a Subspace. - * - * @throws UnsupportedOperationException - */ + /** + * Raises an exception because DirectoryPartition cannot be used as a Subspace. + * + * @throws UnsupportedOperationException + */ @Override public Subspace subspace(Tuple tuple) { throw new UnsupportedOperationException("Cannot open subspace in the root of a directory partition."); @@ -180,18 +180,33 @@ class DirectoryPartition extends DirectorySubspace { * @param rhs the {@code} Object to test for equality * @return true if this is equal to {@code rhs} */ - @Override - public boolean equals(Object rhs) { - if(this == rhs) { - return true; - } - if(rhs == null || getClass() != rhs.getClass()) { - return false; - } + @Override + public boolean equals(Object rhs) { + if(this == rhs) { + return true; + } + if(rhs == null || getClass() != rhs.getClass()) { + return false; + } - DirectoryPartition other = (DirectoryPartition)rhs; - return (getPath() == other.getPath() || getPath() == other.getPath()) && + DirectoryPartition other = (DirectoryPartition)rhs; + return (getPath() == other.getPath() || getPath().equals(other.getPath())) && parentDirectoryLayer.equals(other.parentDirectoryLayer) && super.equals(rhs); - } + } + + /** + * Computes a hash code compatible with this class's {@link #equals(Object) equals()} + * method. In particular, it computes a hash that is based off of the + * hash of the parent {@link DirectoryLayer} and this partition's + * path, layer, and subspace prefix. + * + * @return a hash compatible with this class's {@code equals()} method + */ + @Override + public int hashCode() { + // The path, layer, and subspace prefix information comes from the super + // class's hash code method. + return parentDirectoryLayer.hashCode() ^ (super.hashCode() * 3209); + } } diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/directory/DirectorySubspace.java b/bindings/java/src-completable/main/com/apple/foundationdb/directory/DirectorySubspace.java index 1a8aed73b1..cb0004995c 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/directory/DirectorySubspace.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/directory/DirectorySubspace.java @@ -45,28 +45,28 @@ import com.apple.foundationdb.subspace.Subspace; *

*/ public class DirectorySubspace extends Subspace implements Directory { - private final List path; - private final byte[] layer; - private final DirectoryLayer directoryLayer; + private final List path; + private final byte[] layer; + private final DirectoryLayer directoryLayer; - DirectorySubspace(List path, byte[] prefix, DirectoryLayer directoryLayer) { - this(path, prefix, directoryLayer, EMPTY_BYTES); - } + DirectorySubspace(List path, byte[] prefix, DirectoryLayer directoryLayer) { + this(path, prefix, directoryLayer, EMPTY_BYTES); + } - DirectorySubspace(List path, byte[] prefix, DirectoryLayer directoryLayer, byte[] layer) { - super(prefix); - this.path = path; - this.layer = layer; - this.directoryLayer = directoryLayer; - } + DirectorySubspace(List path, byte[] prefix, DirectoryLayer directoryLayer, byte[] layer) { + super(prefix); + this.path = path; + this.layer = layer; + this.directoryLayer = directoryLayer; + } /** * @return a printable representation of this {@code DirectorySubspace} */ - @Override - public String toString() { - return getClass().getSimpleName() + '(' + DirectoryUtil.pathStr(path) + ", " + printable(getKey()) + ')'; - } + @Override + public String toString() { + return getClass().getSimpleName() + '(' + DirectoryUtil.pathStr(path) + ", " + printable(getKey()) + ')'; + } /** * Returns whether this {@code DirectorySubspace} is equal to {@code rhs}. @@ -76,91 +76,103 @@ public class DirectorySubspace extends Subspace implements Directory { * @param rhs the {@code} Object to test for equality * @return true if this is equal to {@code rhs} */ - @Override - public boolean equals(Object rhs) { - if(this == rhs) { - return true; - } - if(rhs == null || getClass() != rhs.getClass()) { - return false; - } - DirectorySubspace other = (DirectorySubspace)rhs; - return (path == other.path || path.equals(other.path)) && - Arrays.equals(layer, other.layer) && + @Override + public boolean equals(Object rhs) { + if(this == rhs) { + return true; + } + if(rhs == null || getClass() != rhs.getClass()) { + return false; + } + DirectorySubspace other = (DirectorySubspace)rhs; + return (path == other.path || path.equals(other.path)) && + Arrays.equals(layer, other.layer) && directoryLayer.equals(other.directoryLayer) && super.equals(rhs); - } + } - @Override - public List getPath() { - return Collections.unmodifiableList(path); - } + /** + * Computes a hash code compatible with the {@link #equals(Object) equals()} method of + * this class. In particular, it will produce a hash code that is based off of the hashes + * of its path, its layer, and its subspace prefix. + * + * @return a hash compatible with this class's {@code equals()} method + */ + @Override + public int hashCode() { + return path.hashCode() ^ (Arrays.hashCode(layer) * 1153) ^ (directoryLayer.hashCode() * 929) ^ (super.hashCode() * 419); + } - @Override - public byte[] getLayer() { - return Arrays.copyOf(layer, layer.length); - } + @Override + public List getPath() { + return Collections.unmodifiableList(path); + } + + @Override + public byte[] getLayer() { + return Arrays.copyOf(layer, layer.length); + } @Override public DirectoryLayer getDirectoryLayer() { return directoryLayer; } - @Override - public CompletableFuture createOrOpen(TransactionContext tcx, List subpath, byte[] otherLayer) { - return directoryLayer.createOrOpen(tcx, getPartitionSubpath(subpath), otherLayer); - } + @Override + public CompletableFuture createOrOpen(TransactionContext tcx, List subpath, byte[] otherLayer) { + return directoryLayer.createOrOpen(tcx, getPartitionSubpath(subpath), otherLayer); + } - @Override - public CompletableFuture open(ReadTransactionContext tcx, List subpath, byte[] otherLayer) { - return directoryLayer.open(tcx, getPartitionSubpath(subpath), otherLayer); - } + @Override + public CompletableFuture open(ReadTransactionContext tcx, List subpath, byte[] otherLayer) { + return directoryLayer.open(tcx, getPartitionSubpath(subpath), otherLayer); + } - @Override - public CompletableFuture create(TransactionContext tcx, List subpath, byte[] otherLayer, byte[] prefix) { - return directoryLayer.create(tcx, getPartitionSubpath(subpath), otherLayer, prefix); - } + @Override + public CompletableFuture create(TransactionContext tcx, List subpath, byte[] otherLayer, byte[] prefix) { + return directoryLayer.create(tcx, getPartitionSubpath(subpath), otherLayer, prefix); + } - @Override - public CompletableFuture> list(ReadTransactionContext tcx, List subpath) { - return directoryLayer.list(tcx, getPartitionSubpath(subpath)); - } + @Override + public CompletableFuture> list(ReadTransactionContext tcx, List subpath) { + return directoryLayer.list(tcx, getPartitionSubpath(subpath)); + } - @Override - public CompletableFuture move(TransactionContext tcx, List oldSubpath, List newSubpath) { - return directoryLayer.move(tcx, getPartitionSubpath(oldSubpath), getPartitionSubpath(newSubpath)); - } + @Override + public CompletableFuture move(TransactionContext tcx, List oldSubpath, List newSubpath) { + return directoryLayer.move(tcx, getPartitionSubpath(oldSubpath), getPartitionSubpath(newSubpath)); + } - @Override - public CompletableFuture moveTo(TransactionContext tcx, List newAbsolutePath) { + @Override + public CompletableFuture moveTo(TransactionContext tcx, List newAbsolutePath) { DirectoryLayer dir = getLayerForPath(EMPTY_PATH); int partitionLen = dir.getPath().size(); List partitionPath = newAbsolutePath.subList(0, Math.min(newAbsolutePath.size(), partitionLen)); if(!partitionPath.equals(dir.getPath())) throw new DirectoryMoveException("Cannot move between partitions", path, newAbsolutePath); - return dir.move(tcx, + return dir.move(tcx, getPartitionSubpath(EMPTY_PATH, dir), newAbsolutePath.subList(partitionLen, newAbsolutePath.size())); - } + } - @Override - public CompletableFuture remove(TransactionContext tcx, List subpath) { + @Override + public CompletableFuture remove(TransactionContext tcx, List subpath) { DirectoryLayer dir = getLayerForPath(subpath); - return dir.remove(tcx, getPartitionSubpath(subpath, dir)); - } + return dir.remove(tcx, getPartitionSubpath(subpath, dir)); + } - @Override - public CompletableFuture removeIfExists(TransactionContext tcx, List subpath) { + @Override + public CompletableFuture removeIfExists(TransactionContext tcx, List subpath) { DirectoryLayer dir = getLayerForPath(subpath); - return dir.removeIfExists(tcx, getPartitionSubpath(subpath, dir)); - } + return dir.removeIfExists(tcx, getPartitionSubpath(subpath, dir)); + } - @Override - public CompletableFuture exists(ReadTransactionContext tcx, List subpath) { + @Override + public CompletableFuture exists(ReadTransactionContext tcx, List subpath) { DirectoryLayer dir = getLayerForPath(subpath); - return dir.exists(tcx, getPartitionSubpath(subpath, dir)); - } + return dir.exists(tcx, getPartitionSubpath(subpath, dir)); + } private List getPartitionSubpath(List path) { return getPartitionSubpath(path, directoryLayer); diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/directory/DirectoryUtil.java b/bindings/java/src-completable/main/com/apple/foundationdb/directory/DirectoryUtil.java index 6433fe6607..ff600ecccb 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/directory/DirectoryUtil.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/directory/DirectoryUtil.java @@ -42,4 +42,6 @@ class DirectoryUtil { sb.append(')'); return sb.toString(); } + + private DirectoryUtil() {} } diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/directory/MismatchedLayerException.java b/bindings/java/src-completable/main/com/apple/foundationdb/directory/MismatchedLayerException.java index 73fe153c34..86fef063b6 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/directory/MismatchedLayerException.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/directory/MismatchedLayerException.java @@ -20,10 +20,10 @@ package com.apple.foundationdb.directory; -import com.apple.foundationdb.tuple.ByteArrayUtil; - import java.util.List; +import com.apple.foundationdb.tuple.ByteArrayUtil; + /** * A {@link DirectoryException} that is thrown when a directory is opened with an incompatible layer. */ diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/directory/PathUtil.java b/bindings/java/src-completable/main/com/apple/foundationdb/directory/PathUtil.java index f11d9d47ee..1972b19728 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/directory/PathUtil.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/directory/PathUtil.java @@ -92,4 +92,6 @@ public class PathUtil { return new LinkedList(path.subList(0, path.size() - 1)); } + + private PathUtil() {} } diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/subspace/Subspace.java b/bindings/java/src-completable/main/com/apple/foundationdb/subspace/Subspace.java index 71cbdbb0d9..ab735b8695 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/subspace/Subspace.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/subspace/Subspace.java @@ -45,8 +45,7 @@ import com.apple.foundationdb.tuple.Versionstamp; * As a best practice, API clients should use at least one subspace for application data. *

*/ -public class Subspace -{ +public class Subspace { static final Tuple EMPTY_TUPLE = Tuple.from(); static final byte[] EMPTY_BYTES = new byte[0]; @@ -112,7 +111,7 @@ public class Subspace return false; } Subspace other = (Subspace)rhs; - return Arrays.equals(rawPrefix, other.rawPrefix) ; + return Arrays.equals(rawPrefix, other.rawPrefix); } /** diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/tuple/ByteArrayUtil.java b/bindings/java/src-completable/main/com/apple/foundationdb/tuple/ByteArrayUtil.java index 0770d1284b..db92be74ec 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/tuple/ByteArrayUtil.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/tuple/ByteArrayUtil.java @@ -59,29 +59,29 @@ public class ByteArrayUtil { if(interlude == null) interlude = new byte[0]; - int element_totals = 0; + int elementTotals = 0; int interludeSize = interlude.length; for(byte[] e : parts) { - element_totals += e.length; + elementTotals += e.length; } - byte[] dest = new byte[(interludeSize * (partCount - 1)) + element_totals]; + byte[] dest = new byte[(interludeSize * (partCount - 1)) + elementTotals]; //System.out.println(" interlude -> " + ArrayUtils.printable(interlude)); - int start_byte = 0; + int startByte = 0; int index = 0; for(byte[] part : parts) { //System.out.println(" section -> " + ArrayUtils.printable(parts.get(i))); int length = part.length; if(length > 0) { - System.arraycopy(part, 0, dest, start_byte, length); - start_byte += length; + System.arraycopy(part, 0, dest, startByte, length); + startByte += length; } if(index < partCount - 1 && interludeSize > 0) { // If this is not the last element, append the interlude - System.arraycopy(interlude, 0, dest, start_byte, interludeSize); - start_byte += interludeSize; + System.arraycopy(interlude, 0, dest, startByte, interludeSize); + startByte += interludeSize; } index++; } @@ -97,7 +97,7 @@ public class ByteArrayUtil { * * @return a newly created concatenation of the input */ - public static byte[] join(byte[] ... parts) { + public static byte[] join(byte[]... parts) { return join(null, Arrays.asList(parts)); } diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/tuple/Tuple.java b/bindings/java/src-completable/main/com/apple/foundationdb/tuple/Tuple.java index 2f5b2c2e4e..c819ed3a9f 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/tuple/Tuple.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/tuple/Tuple.java @@ -21,11 +21,8 @@ package com.apple.foundationdb.tuple; import java.math.BigInteger; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.LinkedList; @@ -852,12 +849,12 @@ public class Tuple implements Comparable, Iterable { * * @return a newly created {@code Tuple} */ - public static Tuple from(Object ... items) { + public static Tuple from(Object... items) { return fromList(Arrays.asList(items)); } static void main(String[] args) { - for( int i : new int[] {10, 100, 1000, 10000, 100000, 1000000} ) { + for(int i : new int[] {10, 100, 1000, 10000, 100000, 1000000}) { createTuple(i); } diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/tuple/TupleUtil.java b/bindings/java/src-completable/main/com/apple/foundationdb/tuple/TupleUtil.java index b22fdea743..54762e93b5 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/tuple/TupleUtil.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/tuple/TupleUtil.java @@ -421,10 +421,10 @@ class TupleUtil { // Convert to long if in range -- otherwise, leave as BigInteger. if (val.compareTo(BigInteger.valueOf(Long.MIN_VALUE))<0|| - val.compareTo(BigInteger.valueOf(Long.MAX_VALUE))>0) { - // This can occur if the thing can be represented with 8 bytes but not - // the right sign information. - return new DecodeResult(end, val); + val.compareTo(BigInteger.valueOf(Long.MAX_VALUE))>0) { + // This can occur if the thing can be represented with 8 bytes but not + // the right sign information. + return new DecodeResult(end, val); } return new DecodeResult(end, val.longValue()); } @@ -610,18 +610,18 @@ class TupleUtil { public static void main(String[] args) { try { - byte[] bytes = pack(Collections.singletonList(4), null ); - assert 4 == (Integer)(decode( bytes, 0, bytes.length ).o); + byte[] bytes = pack(Collections.singletonList(4), null); + assert 4 == (Integer)(decode(bytes, 0, bytes.length).o); } catch (Exception e) { e.printStackTrace(); System.out.println("Error " + e.getMessage()); } try { - byte[] bytes = pack( Collections.singletonList("\u021Aest \u0218tring"), null ); - String string = (String)(decode( bytes, 0, bytes.length ).o); + byte[] bytes = pack(Collections.singletonList("\u021Aest \u0218tring"), null); + String string = (String)(decode(bytes, 0, bytes.length).o); System.out.println("contents -> " + string); - assert "\u021Aest \u0218tring" == string; + assert "\u021Aest \u0218tring".equals(string); } catch (Exception e) { e.printStackTrace(); System.out.println("Error " + e.getMessage()); diff --git a/bindings/java/src-completable/test/com/apple/foundationdb/test/AbstractTester.java b/bindings/java/src-completable/test/com/apple/foundationdb/test/AbstractTester.java index 4a7f3f393a..4f209dbe6d 100644 --- a/bindings/java/src-completable/test/com/apple/foundationdb/test/AbstractTester.java +++ b/bindings/java/src-completable/test/com/apple/foundationdb/test/AbstractTester.java @@ -20,12 +20,12 @@ package com.apple.foundationdb.test; -import com.apple.foundationdb.Database; -import com.apple.foundationdb.FDB; - import java.nio.charset.Charset; import java.util.Random; +import com.apple.foundationdb.Database; +import com.apple.foundationdb.FDB; + public abstract class AbstractTester { public static final int API_VERSION = 510; protected static final int NUM_RUNS = 25; diff --git a/bindings/java/src-completable/test/com/apple/foundationdb/test/AsyncPerformanceTester.java b/bindings/java/src-completable/test/com/apple/foundationdb/test/AsyncPerformanceTester.java deleted file mode 100644 index dcecfdeff1..0000000000 --- a/bindings/java/src-completable/test/com/apple/foundationdb/test/AsyncPerformanceTester.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * AsyncPerformanceTester.java - * - * This source file is part of the FoundationDB open source project - * - * Copyright 2013-2018 Apple Inc. and the FoundationDB project authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.apple.foundationdb.test; - -public class AsyncPerformanceTester { - - public static void main(String[] args) { - System.out.println("Running Java async performance test on Java version " + System.getProperty("java.version")); - } -} diff --git a/bindings/java/src-completable/test/com/apple/foundationdb/test/AsyncStackTester.java b/bindings/java/src-completable/test/com/apple/foundationdb/test/AsyncStackTester.java index 123139a5bf..5d33931f74 100644 --- a/bindings/java/src-completable/test/com/apple/foundationdb/test/AsyncStackTester.java +++ b/bindings/java/src-completable/test/com/apple/foundationdb/test/AsyncStackTester.java @@ -21,10 +21,15 @@ package com.apple.foundationdb.test; import java.math.BigInteger; -import java.util.*; - import java.nio.ByteBuffer; import java.nio.ByteOrder; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.function.Function; @@ -53,16 +58,12 @@ public class AsyncStackTester { @Override public CompletableFuture apply(Transaction tr) { - return tr.getRange(Range.startsWith(prefix)).asList().thenApplyAsync(new Function, Void>() { - @Override - public Void apply(List list) { - if(list.size() > 0) { - //System.out.println(" - Throwing new fake commit error..."); - throw new FDBException("ERROR: Fake commit conflict", 1020); - } - return null; + return tr.getRange(Range.startsWith(prefix)).asList().thenAcceptAsync(list -> { + if(list.size() > 0) { + //System.out.println(" - Throwing new fake commit error..."); + throw new FDBException("ERROR: Fake commit conflict", 1020); } - }); + }, FDB.DEFAULT_EXECUTOR); } } @@ -100,144 +101,83 @@ public class AsyncStackTester { return AsyncUtil.DONE; } else if(op == StackOperation.SWAP) { - return inst.popParam() - .thenApplyAsync(new Function() { - @Override - public Void apply(Object param) { - int index = StackUtils.getInt(param); - if(index >= inst.size()) - throw new IllegalArgumentException("Stack index not valid"); + return inst.popParam().thenAcceptAsync(param -> { + int index = StackUtils.getInt(param); + if(index >= inst.size()) + throw new IllegalArgumentException("Stack index not valid"); - inst.swap(index); - return null; - } - }); + inst.swap(index); + }, FDB.DEFAULT_EXECUTOR); } else if(op == StackOperation.WAIT_FUTURE) { - return popAndWait(inst) - .thenApplyAsync(new Function() { - @Override - public Void apply(StackEntry e) { - inst.push(e); - return null; - } - }); + return popAndWait(inst).thenAccept(inst::push); } else if(op == StackOperation.WAIT_EMPTY) { - return inst.popParam() - .thenComposeAsync(new Function>() { - @Override - public CompletableFuture apply(Object param) { - WaitEmpty retryable = new WaitEmpty((byte[])param); - return inst.context.db.runAsync(retryable).thenApply(new Function() { - @Override - public Void apply(Void o) { - inst.push( "WAITED_FOR_EMPTY".getBytes()); - return null; - } - }); - } - }); + return inst.popParam().thenComposeAsync(param -> { + WaitEmpty retryable = new WaitEmpty((byte[])param); + return inst.context.db.runAsync(retryable).thenRun(() -> inst.push("WAITED_FOR_EMPTY".getBytes())); + }, FDB.DEFAULT_EXECUTOR); } else if(op == StackOperation.START_THREAD) { - return inst.popParam() - .thenApplyAsync(new Function() { - @Override - public Void apply(Object param) { - //System.out.println(inst.context.preStr + " - " + "Starting new thread at prefix: " + ByteArrayUtil.printable((byte[]) params.get(0))); - inst.context.addContext((byte[])param); - return null; - } - }); + return inst.popParam().thenAcceptAsync(param -> { + //System.out.println(inst.context.preStr + " - " + "Starting new thread at prefix: " + ByteArrayUtil.printable((byte[]) params.get(0))); + inst.context.addContext((byte[])param); + }, FDB.DEFAULT_EXECUTOR); } else if(op == StackOperation.NEW_TRANSACTION) { inst.context.newTransaction(); return AsyncUtil.DONE; } else if(op == StackOperation.USE_TRANSACTION) { - return inst.popParam() - .thenApplyAsync(new Function() { - public Void apply(Object param) { - inst.context.switchTransaction((byte[])param); - return null; - } - }); + return inst.popParam().thenAcceptAsync(param -> { + inst.context.switchTransaction((byte[])param); + }, FDB.DEFAULT_EXECUTOR); } else if(op == StackOperation.SET) { - return inst.popParams(2).thenComposeAsync(new Function, CompletableFuture>() { - @Override - public CompletableFuture apply(final List params) { - /*System.out.println(inst.context.preStr + " - " + "Setting '" + ByteArrayUtil.printable((byte[]) params.get(0)) + - "' to '" + ByteArrayUtil.printable((byte[]) params.get(1)) + "'"); */ - return executeMutation(inst, new Function>() { - @Override - public CompletableFuture apply(Transaction tr) { - tr.set((byte[])params.get(0), (byte[])params.get(1)); - return AsyncUtil.DONE; - } - }); - } - }); + return inst.popParams(2).thenComposeAsync(params -> { + /*System.out.println(inst.context.preStr + " - " + "Setting '" + ByteArrayUtil.printable((byte[]) params.get(0)) + + "' to '" + ByteArrayUtil.printable((byte[]) params.get(1)) + "'"); */ + return executeMutation(inst, tr -> { + tr.set((byte[])params.get(0), (byte[])params.get(1)); + return AsyncUtil.DONE; + }); + }, FDB.DEFAULT_EXECUTOR); } else if(op == StackOperation.CLEAR) { - return inst.popParam().thenComposeAsync(new Function>() { - @Override - public CompletableFuture apply(final Object param) { - //System.out.println(inst.context.preStr + " - " + "Clearing: '" + ByteArrayUtil.printable((byte[])param) + "'"); - return executeMutation(inst, new Function>() { - @Override - public CompletableFuture apply(Transaction tr) { - tr.clear((byte[])param); - return AsyncUtil.DONE; - } - }); - } - }); + return inst.popParam().thenComposeAsync(param -> { + //System.out.println(inst.context.preStr + " - " + "Clearing: '" + ByteArrayUtil.printable((byte[])param) + "'"); + return executeMutation(inst, tr -> { + tr.clear((byte[])param); + return AsyncUtil.DONE; + }); + }, FDB.DEFAULT_EXECUTOR); } else if(op == StackOperation.CLEAR_RANGE) { - return inst.popParams(2).thenComposeAsync(new Function, CompletableFuture>() { - @Override - public CompletableFuture apply(final List params) { - return executeMutation(inst, new Function>() { - @Override - public CompletableFuture apply(Transaction tr) { - tr.clear((byte[])params.get(0), (byte[])params.get(1)); - return AsyncUtil.DONE; - } - }); - } - }); + return inst.popParams(2).thenComposeAsync(params -> + executeMutation(inst, tr -> { + tr.clear((byte[])params.get(0), (byte[])params.get(1)); + return AsyncUtil.DONE; + }), + FDB.DEFAULT_EXECUTOR + ); } else if(op == StackOperation.CLEAR_RANGE_STARTS_WITH) { - return inst.popParam().thenComposeAsync(new Function>() { - @Override - public CompletableFuture apply(final Object param) { - return executeMutation(inst, new Function>() { - @Override - public CompletableFuture apply(Transaction tr) { - tr.clear(Range.startsWith((byte[])param)); - return AsyncUtil.DONE; - } - }); - } - }); + return inst.popParam().thenComposeAsync(param -> + executeMutation(inst, tr -> { + tr.clear(Range.startsWith((byte[])param)); + return AsyncUtil.DONE; + }), + FDB.DEFAULT_EXECUTOR + ); } else if(op == StackOperation.ATOMIC_OP) { - return inst.popParams(3).thenComposeAsync(new Function, CompletableFuture>() { - @Override - public CompletableFuture apply(final List params) { - final MutationType optype = MutationType.valueOf((String)params.get(0)); - return executeMutation(inst, - new Function>() { - @Override - public CompletableFuture apply(Transaction tr) { - tr.mutate(optype, (byte[])params.get(1), (byte[])params.get(2)); - return AsyncUtil.DONE; - } - } - ); - } - }); + return inst.popParams(3).thenComposeAsync(params -> { + final MutationType optype = MutationType.valueOf((String)params.get(0)); + return executeMutation(inst, tr -> { + tr.mutate(optype, (byte[])params.get(1), (byte[])params.get(2)); + return AsyncUtil.DONE; + }); + }, FDB.DEFAULT_EXECUTOR); } else if(op == StackOperation.COMMIT) { inst.push(inst.tr.commit()); @@ -252,43 +192,27 @@ public class AsyncStackTester { return AsyncUtil.DONE; } else if(op == StackOperation.READ_CONFLICT_RANGE) { - return inst.popParams(2).thenApplyAsync(new Function, Void>() { - @Override - public Void apply(List params) { - inst.tr.addReadConflictRange((byte[])params.get(0), (byte[])params.get(1)); - inst.push("SET_CONFLICT_RANGE".getBytes()); - return null; - } - }); + return inst.popParams(2).thenAcceptAsync(params -> { + inst.tr.addReadConflictRange((byte[])params.get(0), (byte[])params.get(1)); + inst.push("SET_CONFLICT_RANGE".getBytes()); + }, FDB.DEFAULT_EXECUTOR); } else if(op == StackOperation.WRITE_CONFLICT_RANGE) { - return inst.popParams(2).thenApplyAsync(new Function, Void>() { - @Override - public Void apply(List params) { - inst.tr.addWriteConflictRange((byte[])params.get(0), (byte[])params.get(1)); - inst.push("SET_CONFLICT_RANGE".getBytes()); - return null; - } - }); + return inst.popParams(2).thenAcceptAsync(params -> { + inst.tr.addWriteConflictRange((byte[])params.get(0), (byte[])params.get(1)); + inst.push("SET_CONFLICT_RANGE".getBytes()); + }, FDB.DEFAULT_EXECUTOR); } else if(op == StackOperation.READ_CONFLICT_KEY) { - return inst.popParam().thenApplyAsync(new Function() { - @Override - public Void apply(Object param) { - inst.tr.addReadConflictKey((byte[])param); - inst.push("SET_CONFLICT_KEY".getBytes()); - return null; - } - }); + return inst.popParam().thenAcceptAsync(param -> { + inst.tr.addReadConflictKey((byte[])param); + inst.push("SET_CONFLICT_KEY".getBytes()); + }, FDB.DEFAULT_EXECUTOR); } else if(op == StackOperation.WRITE_CONFLICT_KEY) { - return inst.popParam().thenApplyAsync(new Function() { - @Override - public Void apply(Object param) { - inst.tr.addWriteConflictKey((byte[])param); - inst.push("SET_CONFLICT_KEY".getBytes()); - return null; - } + return inst.popParam().thenAcceptAsync(param -> { + inst.tr.addWriteConflictKey((byte[])param); + inst.push("SET_CONFLICT_KEY".getBytes()); }); } else if(op == StackOperation.DISABLE_WRITE_CONFLICT) { @@ -296,78 +220,57 @@ public class AsyncStackTester { return AsyncUtil.DONE; } else if(op == StackOperation.GET) { - return inst.popParam().thenApplyAsync(new Function() { - @Override - public Void apply(Object param) { - inst.push(inst.readTcx.readAsync(readTr -> readTr.get((byte[]) param))); - return null; - } + return inst.popParam().thenAcceptAsync(param -> { + inst.push(inst.readTcx.readAsync(readTr -> readTr.get((byte[]) param))); }); } else if(op == StackOperation.GET_RANGE) { - return inst.popParams(5).thenComposeAsync(new Function, CompletableFuture>() { - @Override - public CompletableFuture apply(List params) { - int limit = StackUtils.getInt(params.get(2)); - boolean reverse = StackUtils.getBoolean(params.get(3)); - StreamingMode mode = inst.context.streamingModeFromCode( - StackUtils.getInt(params.get(4), StreamingMode.ITERATOR.code())); + return inst.popParams(5).thenComposeAsync(params -> { + int limit = StackUtils.getInt(params.get(2)); + boolean reverse = StackUtils.getBoolean(params.get(3)); + StreamingMode mode = inst.context.streamingModeFromCode( + StackUtils.getInt(params.get(4), StreamingMode.ITERATOR.code())); - CompletableFuture> range = inst.readTcx.readAsync(readTr -> readTr.getRange((byte[])params.get(0), (byte[])params.get(1), limit, reverse, mode).asList()); - return pushRange(inst, range); - } - }); + CompletableFuture> range = inst.readTcx.readAsync(readTr -> readTr.getRange((byte[])params.get(0), (byte[])params.get(1), limit, reverse, mode).asList()); + return pushRange(inst, range); + }, FDB.DEFAULT_EXECUTOR); } else if(op == StackOperation.GET_RANGE_SELECTOR) { - return inst.popParams(10).thenComposeAsync(new Function, CompletableFuture>() { - @Override - public CompletableFuture apply(List params) { - int limit = StackUtils.getInt(params.get(6)); - boolean reverse = StackUtils.getBoolean(params.get(7)); - StreamingMode mode = inst.context.streamingModeFromCode( - StackUtils.getInt(params.get(8), StreamingMode.ITERATOR.code())); + return inst.popParams(10).thenComposeAsync(params -> { + int limit = StackUtils.getInt(params.get(6)); + boolean reverse = StackUtils.getBoolean(params.get(7)); + StreamingMode mode = inst.context.streamingModeFromCode( + StackUtils.getInt(params.get(8), StreamingMode.ITERATOR.code())); - KeySelector start = StackUtils.createSelector(params.get(0),params.get(1), params.get(2)); - KeySelector end = StackUtils.createSelector(params.get(3), params.get(4), params.get(5)); + KeySelector start = StackUtils.createSelector(params.get(0),params.get(1), params.get(2)); + KeySelector end = StackUtils.createSelector(params.get(3), params.get(4), params.get(5)); - CompletableFuture> range = inst.readTcx.readAsync(readTr -> readTr.getRange(start, end, limit, reverse, mode).asList()); - return pushRange(inst, range, (byte[])params.get(9)); - } - }); + CompletableFuture> range = inst.readTcx.readAsync(readTr -> readTr.getRange(start, end, limit, reverse, mode).asList()); + return pushRange(inst, range, (byte[])params.get(9)); + }, FDB.DEFAULT_EXECUTOR); } else if(op == StackOperation.GET_RANGE_STARTS_WITH) { - return inst.popParams(4).thenComposeAsync(new Function, CompletableFuture>() { - @Override - public CompletableFuture apply(List params) { - int limit = StackUtils.getInt(params.get(1)); - boolean reverse = StackUtils.getBoolean(params.get(2)); - StreamingMode mode = inst.context.streamingModeFromCode( - StackUtils.getInt(params.get(3), StreamingMode.ITERATOR.code())); + return inst.popParams(4).thenComposeAsync(params -> { + int limit = StackUtils.getInt(params.get(1)); + boolean reverse = StackUtils.getBoolean(params.get(2)); + StreamingMode mode = inst.context.streamingModeFromCode( + StackUtils.getInt(params.get(3), StreamingMode.ITERATOR.code())); - CompletableFuture> range = inst.readTcx.readAsync(readTr -> readTr.getRange(Range.startsWith((byte[])params.get(0)), limit, reverse, mode).asList()); - return pushRange(inst, range); - } + CompletableFuture> range = inst.readTcx.readAsync(readTr -> readTr.getRange(Range.startsWith((byte[])params.get(0)), limit, reverse, mode).asList()); + return pushRange(inst, range); }); } else if(op == StackOperation.GET_KEY) { - return inst.popParams(4).thenApplyAsync(new Function, Void>() { - @Override - public Void apply(List params) { - KeySelector start = StackUtils.createSelector(params.get(0),params.get(1), params.get(2)); - inst.push(inst.readTcx.readAsync(readTr -> executeGetKey(readTr.getKey(start), (byte[])params.get(3)))); - return null; - } - }); + return inst.popParams(4).thenAcceptAsync(params -> { + KeySelector start = StackUtils.createSelector(params.get(0),params.get(1), params.get(2)); + inst.push(inst.readTcx.readAsync(readTr -> executeGetKey(readTr.getKey(start), (byte[])params.get(3)))); + }, FDB.DEFAULT_EXECUTOR); } else if(op == StackOperation.GET_READ_VERSION) { - return inst.readTr.getReadVersion().thenApplyAsync(new Function() { - @Override - public Void apply(Long readVersion) { - inst.context.lastVersion = readVersion; - inst.push("GOT_READ_VERSION".getBytes()); - return null; - } - }); + return inst.readTr.getReadVersion().thenAcceptAsync(readVersion -> { + inst.context.lastVersion = readVersion; + inst.push("GOT_READ_VERSION".getBytes()); + }, FDB.DEFAULT_EXECUTOR); } else if(op == StackOperation.GET_COMMITTED_VERSION) { try { @@ -397,215 +300,153 @@ public class AsyncStackTester { return AsyncUtil.DONE; } else if(op == StackOperation.ON_ERROR) { - return inst.popParam().thenComposeAsync(new Function>() { - @Override - public CompletableFuture apply(Object param) { - int errorCode = StackUtils.getInt(param); + return inst.popParam().thenComposeAsync(param -> { + int errorCode = StackUtils.getInt(param); - // 1102 (future_released) and 2015 (future_not_set) are not errors to Java. - // This is never encountered by user code, so we have to do something rather - // messy here to get compatibility with other languages. - // - // First, try on error with a retryable error. If it fails, then the transaction is in - // a failed state and we should rethrow the error. Otherwise, throw the original error. - boolean filteredError = errorCode == 1102 || errorCode == 2015; + // 1102 (future_released) and 2015 (future_not_set) are not errors to Java. + // This is never encountered by user code, so we have to do something rather + // messy here to get compatibility with other languages. + // + // First, try on error with a retryable error. If it fails, then the transaction is in + // a failed state and we should rethrow the error. Otherwise, throw the original error. + boolean filteredError = errorCode == 1102 || errorCode == 2015; - FDBException err = new FDBException("Fake testing error", filteredError ? 1020 : errorCode); - final Transaction oldTr = inst.tr; - CompletableFuture f = oldTr.onError(err) - .whenComplete((tr, t) -> { - if(t != null) { - inst.context.newTransaction(oldTr); // Other bindings allow reuse of non-retryable transactions, so we need to emulate that behavior. - } - else { - inst.setTransaction(oldTr, tr); - } - }) - .thenApply(v -> null); - - if(filteredError) { - f.join(); - throw new FDBException("Fake testing error", errorCode); + FDBException err = new FDBException("Fake testing error", filteredError ? 1020 : errorCode); + final Transaction oldTr = inst.tr; + CompletableFuture f = oldTr.onError(err).whenComplete((tr, t) -> { + if(t != null) { + inst.context.newTransaction(oldTr); // Other bindings allow reuse of non-retryable transactions, so we need to emulate that behavior. } + else { + inst.setTransaction(oldTr, tr); + } + }).thenApply(v -> null); - inst.push(f); - return AsyncUtil.DONE; + if(filteredError) { + f.join(); + throw new FDBException("Fake testing error", errorCode); } - }); + + inst.push(f); + return AsyncUtil.DONE; + }, FDB.DEFAULT_EXECUTOR); } else if(op == StackOperation.SUB) { - return inst.popParams(2).thenApplyAsync(new Function, Void>() { - @Override - public Void apply(List params) { - BigInteger result = StackUtils.getBigInteger(params.get(0)).subtract( - StackUtils.getBigInteger(params.get(1)) - ); - inst.push(result); - return null; - } + return inst.popParams(2).thenAcceptAsync(params -> { + BigInteger result = StackUtils.getBigInteger(params.get(0)).subtract( + StackUtils.getBigInteger(params.get(1)) + ); + inst.push(result); }); } else if(op == StackOperation.CONCAT) { - return inst.popParams(2).thenApplyAsync(new Function, Void>() { - @Override - public Void apply(List params) { - if(params.get(0) instanceof String) { - inst.push((String)params.get(0) + (String)params.get(1)); - } - else { - inst.push(ByteArrayUtil.join((byte[])params.get(0), (byte[])params.get(1))); - } - - return null; + return inst.popParams(2).thenAcceptAsync(params -> { + if(params.get(0) instanceof String) { + inst.push((String)params.get(0) + (String)params.get(1)); } - }); + else { + inst.push(ByteArrayUtil.join((byte[])params.get(0), (byte[])params.get(1))); + } + }, FDB.DEFAULT_EXECUTOR); } else if(op == StackOperation.TUPLE_PACK) { - return inst.popParam().thenComposeAsync(new Function>() { - @Override - public CompletableFuture apply(Object param) { - int tupleSize = StackUtils.getInt(param); - //System.out.println(inst.context.preStr + " - " + "Packing top " + tupleSize + " items from stack"); - return inst.popParams(tupleSize).thenApplyAsync(new Function, Void>() { - @Override - public Void apply(List elements) { - byte[] coded = Tuple.fromItems(elements).pack(); - //System.out.println(inst.context.preStr + " - " + " -> result '" + ByteArrayUtil.printable(coded) + "'"); - inst.push(coded); - return null; - } - }); - } - }); + return inst.popParam().thenComposeAsync(param -> { + int tupleSize = StackUtils.getInt(param); + //System.out.println(inst.context.preStr + " - " + "Packing top " + tupleSize + " items from stack"); + return inst.popParams(tupleSize).thenAcceptAsync(elements -> { + byte[] coded = Tuple.fromItems(elements).pack(); + //System.out.println(inst.context.preStr + " - " + " -> result '" + ByteArrayUtil.printable(coded) + "'"); + inst.push(coded); + }, FDB.DEFAULT_EXECUTOR); + }, FDB.DEFAULT_EXECUTOR); } else if(op == StackOperation.TUPLE_PACK_WITH_VERSIONSTAMP) { - return inst.popParams(2).thenComposeAsync(new Function, CompletableFuture>() { - @Override - public CompletableFuture apply(List params) { - byte[] prefix = (byte[])params.get(0); - int tupleSize = StackUtils.getInt(params.get(1)); - //System.out.println(inst.context.preStr + " - " + "Packing top " + tupleSize + " items from stack"); - return inst.popParams(tupleSize).thenApplyAsync(new Function, Void>() { - @Override - public Void apply(List elements) { - Tuple tuple = Tuple.fromItems(elements); - if(!tuple.hasIncompleteVersionstamp() && Math.random() < 0.5) { - inst.push("ERROR: NONE".getBytes()); - return null; - } - try { - byte[] coded = tuple.packWithVersionstamp(prefix); - inst.push("OK".getBytes()); - inst.push(coded); - } catch(IllegalArgumentException e) { - if(e.getMessage().startsWith("No incomplete")) { - inst.push("ERROR: NONE".getBytes()); - } else { - inst.push("ERROR: MULTIPLE".getBytes()); - } - } - return null; + return inst.popParams(2).thenComposeAsync(params -> { + byte[] prefix = (byte[])params.get(0); + int tupleSize = StackUtils.getInt(params.get(1)); + //System.out.println(inst.context.preStr + " - " + "Packing top " + tupleSize + " items from stack"); + return inst.popParams(tupleSize).thenAcceptAsync(elements -> { + Tuple tuple = Tuple.fromItems(elements); + if(!tuple.hasIncompleteVersionstamp() && Math.random() < 0.5) { + inst.push("ERROR: NONE".getBytes()); + return; + } + try { + byte[] coded = tuple.packWithVersionstamp(prefix); + inst.push("OK".getBytes()); + inst.push(coded); + } catch(IllegalArgumentException e) { + if(e.getMessage().startsWith("No incomplete")) { + inst.push("ERROR: NONE".getBytes()); + } else { + inst.push("ERROR: MULTIPLE".getBytes()); } - }); - } - }); + } + }, FDB.DEFAULT_EXECUTOR); + }, FDB.DEFAULT_EXECUTOR); } else if(op == StackOperation.TUPLE_UNPACK) { - return inst.popParam().thenApplyAsync(new Function() { - @Override - public Void apply(Object param) { - /*System.out.println(inst.context.preStr + " - " + "Unpacking tuple code: " + - ByteArrayUtil.printable((byte[]) param)); */ - Tuple t = Tuple.fromBytes((byte[])param); - for(Object o : t.getItems()) { - byte[] itemBytes = Tuple.from(o).pack(); - inst.push(itemBytes); - } - return null; + return inst.popParam().thenAcceptAsync(param -> { + /*System.out.println(inst.context.preStr + " - " + "Unpacking tuple code: " + + ByteArrayUtil.printable((byte[]) param)); */ + Tuple t = Tuple.fromBytes((byte[])param); + for(Object o : t.getItems()) { + byte[] itemBytes = Tuple.from(o).pack(); + inst.push(itemBytes); } - }); + }, FDB.DEFAULT_EXECUTOR); } else if(op == StackOperation.TUPLE_RANGE) { - return inst.popParam().thenComposeAsync(new Function>() { - @Override - public CompletableFuture apply(Object param) { - int tupleSize = StackUtils.getInt(param); - //System.out.println(inst.context.preStr + " - " + "Tuple range with top " + tupleSize + " items from stack"); - return inst.popParams(tupleSize).thenApplyAsync(new Function, Void>() { - @Override - public Void apply(List elements) { - Range range = Tuple.fromItems(elements).range(); - inst.push(range.begin); - inst.push(range.end); - return null; - } - }); - } - }); + return inst.popParam().thenComposeAsync(param -> { + int tupleSize = StackUtils.getInt(param); + //System.out.println(inst.context.preStr + " - " + "Tuple range with top " + tupleSize + " items from stack"); + return inst.popParams(tupleSize).thenAcceptAsync(elements -> { + Range range = Tuple.fromItems(elements).range(); + inst.push(range.begin); + inst.push(range.end); + }, FDB.DEFAULT_EXECUTOR); + }, FDB.DEFAULT_EXECUTOR); } else if(op == StackOperation.TUPLE_SORT) { - return inst.popParam().thenComposeAsync(new Function>() { - @Override - public CompletableFuture apply(Object param) { - final int listSize = StackUtils.getInt(param); - return inst.popParams(listSize).thenApply(new Function, Void>() { - @Override - public Void apply(List rawElements) { - List tuples = new ArrayList(listSize); - for(Object o : rawElements) { - tuples.add(Tuple.fromBytes((byte[])o)); - } - Collections.sort(tuples); - for(Tuple t : tuples) { - inst.push(t.pack()); - } - return null; - } - }); - } - }); + return inst.popParam().thenComposeAsync(param -> { + final int listSize = StackUtils.getInt(param); + return inst.popParams(listSize).thenAcceptAsync(rawElements -> { + List tuples = new ArrayList<>(listSize); + for(Object o : rawElements) { + tuples.add(Tuple.fromBytes((byte[])o)); + } + Collections.sort(tuples); + for(Tuple t : tuples) { + inst.push(t.pack()); + } + }, FDB.DEFAULT_EXECUTOR); + }, FDB.DEFAULT_EXECUTOR); } else if (op == StackOperation.ENCODE_FLOAT) { - return inst.popParam().thenApply(new Function() { - @Override - public Void apply(Object param) { - byte[] fBytes = (byte[])param; - float value = ByteBuffer.wrap(fBytes).order(ByteOrder.BIG_ENDIAN).getFloat(); - inst.push(value); - return null; - } - }); + return inst.popParam().thenAcceptAsync(param -> { + byte[] fBytes = (byte[])param; + float value = ByteBuffer.wrap(fBytes).order(ByteOrder.BIG_ENDIAN).getFloat(); + inst.push(value); + }, FDB.DEFAULT_EXECUTOR); } else if (op == StackOperation.ENCODE_DOUBLE) { - return inst.popParam().thenApply(new Function() { - @Override - public Void apply(Object param) { - byte[] dBytes = (byte[])param; - double value = ByteBuffer.wrap(dBytes).order(ByteOrder.BIG_ENDIAN).getDouble(); - inst.push(value); - return null; - } - }); + return inst.popParam().thenAcceptAsync(param -> { + byte[] dBytes = (byte[])param; + double value = ByteBuffer.wrap(dBytes).order(ByteOrder.BIG_ENDIAN).getDouble(); + inst.push(value); + }, FDB.DEFAULT_EXECUTOR); } else if (op == StackOperation.DECODE_FLOAT) { - return inst.popParam().thenApply(new Function() { - @Override - public Void apply(Object param) { - float value = ((Number)param).floatValue(); - inst.push(ByteBuffer.allocate(4).order(ByteOrder.BIG_ENDIAN).putFloat(value).array()); - return null; - } - }); + return inst.popParam().thenAcceptAsync(param -> { + float value = ((Number)param).floatValue(); + inst.push(ByteBuffer.allocate(4).order(ByteOrder.BIG_ENDIAN).putFloat(value).array()); + }, FDB.DEFAULT_EXECUTOR); } else if (op == StackOperation.DECODE_DOUBLE) { - return inst.popParam().thenApply(new Function() { - @Override - public Void apply(Object param) { - double value = ((Number)param).doubleValue(); - inst.push(ByteBuffer.allocate(8).order(ByteOrder.BIG_ENDIAN).putDouble(value).array()); - return null; - } - }); + return inst.popParam().thenAcceptAsync(param -> { + double value = ((Number)param).doubleValue(); + inst.push(ByteBuffer.allocate(8).order(ByteOrder.BIG_ENDIAN).putDouble(value).array()); + }, FDB.DEFAULT_EXECUTOR); } else if(op == StackOperation.UNIT_TESTS) { inst.context.db.options().setLocationCacheSize(100001); @@ -638,7 +479,7 @@ public class AsyncStackTester { }); } else if(op == StackOperation.LOG_STACK) { - return inst.popParam().thenComposeAsync(prefix -> doLogStack(inst, (byte[])prefix)); + return inst.popParam().thenComposeAsync(prefix -> doLogStack(inst, (byte[])prefix), FDB.DEFAULT_EXECUTOR); } throw new IllegalArgumentException("Unrecognized (or unimplemented) operation"); @@ -646,31 +487,24 @@ public class AsyncStackTester { private static CompletableFuture executeMutation(final Instruction inst, Function> r) { // run this with a retry loop - return inst.tcx.runAsync(r).thenApplyAsync(new Function() { - @Override - public Void apply(Void a) { - if(inst.isDatabase) - inst.push("RESULT_NOT_PRESENT".getBytes()); - return null; - } - }); + return inst.tcx.runAsync(r).thenRunAsync(() -> { + if(inst.isDatabase) + inst.push("RESULT_NOT_PRESENT".getBytes()); + }, FDB.DEFAULT_EXECUTOR); } private static CompletableFuture executeGetKey(final CompletableFuture keyFuture, final byte[] prefixFilter) { - return keyFuture.thenApplyAsync(new Function() { - @Override - public byte[] apply(byte[] key) { - if(ByteArrayUtil.startsWith(key, prefixFilter)) { - return key; - } - else if(ByteArrayUtil.compareUnsigned(key, prefixFilter) < 0) { - return prefixFilter; - } - else { - return ByteArrayUtil.strinc(prefixFilter); - } + return keyFuture.thenApplyAsync(key -> { + if(ByteArrayUtil.startsWith(key, prefixFilter)) { + return key; } - }); + else if(ByteArrayUtil.compareUnsigned(key, prefixFilter) < 0) { + return prefixFilter; + } + else { + return ByteArrayUtil.strinc(prefixFilter); + } + }, FDB.DEFAULT_EXECUTOR); } private static CompletableFuture doLogStack(final Instruction inst, final byte[] prefix) { @@ -678,7 +512,7 @@ public class AsyncStackTester { while(inst.size() > 0) { entries.put(inst.size() - 1, inst.pop()); if(entries.size() == 100) { - return logStack(inst.context.db, entries, prefix).thenComposeAsync(v -> doLogStack(inst, prefix)); + return logStack(inst.context.db, entries, prefix).thenComposeAsync(v -> doLogStack(inst, prefix), FDB.DEFAULT_EXECUTOR); } } @@ -719,7 +553,7 @@ public class AsyncStackTester { } @Override public Void apply(List list) { - List o = new LinkedList(); + List o = new LinkedList<>(); for(KeyValue kv : list) { if(prefixFilter == null || ByteArrayUtil.startsWith(kv.getKey(), prefixFilter)) { o.add(kv.getKey()); @@ -780,12 +614,9 @@ public class AsyncStackTester { } CompletableFuture executeRemainingOperations() { - final Function> processNext = new Function>() { - @Override - public CompletableFuture apply(Void ignore) { - instructionIndex++; - return executeRemainingOperations(); - } + final Function> processNext = ignore -> { + instructionIndex++; + return executeRemainingOperations(); }; if(operations == null || ++currentOp == operations.size()) { @@ -793,24 +624,21 @@ public class AsyncStackTester { return tr.getRange(nextKey, endKey, 1000).asList() .whenComplete((x, t) -> tr.close()) - .thenComposeAsync(new Function, CompletableFuture>() { - @Override - public CompletableFuture apply(List next) { - if(next.size() < 1) { - //System.out.println("No key found after: " + ByteArrayUtil.printable(nextKey.getKey())); - return AsyncUtil.DONE; - } - - operations = next; - currentOp = 0; - nextKey = KeySelector.firstGreaterThan(next.get(next.size()-1).getKey()); - - return processOp(next.get(0).getValue()).thenComposeAsync(processNext); + .thenComposeAsync(next -> { + if(next.size() < 1) { + //System.out.println("No key found after: " + ByteArrayUtil.printable(nextKey.getKey())); + return AsyncUtil.DONE; } - }); + + operations = next; + currentOp = 0; + nextKey = KeySelector.firstGreaterThan(next.get(next.size()-1).getKey()); + + return processOp(next.get(0).getValue()).thenComposeAsync(processNext); + }, FDB.DEFAULT_EXECUTOR); } - return processOp(operations.get(currentOp).getValue()).thenComposeAsync(processNext); + return processOp(operations.get(currentOp).getValue()).thenComposeAsync(processNext, FDB.DEFAULT_EXECUTOR); } } @@ -822,44 +650,31 @@ public class AsyncStackTester { } final int idx = entry.idx; - @SuppressWarnings("unchecked") - final CompletableFuture future = (CompletableFuture)item; + final CompletableFuture future = (CompletableFuture)item; CompletableFuture flattened = flatten(future); - return flattened.thenApplyAsync(new Function() { - @Override - public StackEntry apply(Object o) { - return new StackEntry(idx, o); - } - }); + return flattened.thenApplyAsync(o -> new StackEntry(idx, o)); } - private static CompletableFuture flatten(final CompletableFuture future) { - CompletableFuture f = future.thenApplyAsync(new Function() { - @Override - public Object apply(Object o) { - if(o == null) - return "RESULT_NOT_PRESENT".getBytes(); - return o; - } + private static CompletableFuture flatten(final CompletableFuture future) { + CompletableFuture f = future.thenApply(o -> { + if(o == null) + return "RESULT_NOT_PRESENT".getBytes(); + return o; }); - return AsyncUtil.composeExceptionally(f, new Function>() { - @Override - public CompletableFuture apply(Throwable t) { - FDBException e = StackUtils.getRootFDBException(t); - if(e != null) { - return CompletableFuture.completedFuture(StackUtils.getErrorBytes(e)); - } - - CompletableFuture error = new CompletableFuture(); - error.completeExceptionally(t); - return error; + return AsyncUtil.composeExceptionally(f, t -> { + FDBException e = StackUtils.getRootFDBException(t); + if(e != null) { + return CompletableFuture.completedFuture(StackUtils.getErrorBytes(e)); } + + CompletableFuture error = new CompletableFuture<>(); + error.completeExceptionally(t); + return error; }); } - /** * Run a stack-machine based test. */ @@ -893,4 +708,5 @@ public class AsyncStackTester { executor.shutdown();*/ } + private AsyncStackTester() {} } diff --git a/bindings/java/src-completable/test/com/apple/foundationdb/test/BlockingBenchmark.java b/bindings/java/src-completable/test/com/apple/foundationdb/test/BlockingBenchmark.java index 8196d059b1..1eebe3e338 100644 --- a/bindings/java/src-completable/test/com/apple/foundationdb/test/BlockingBenchmark.java +++ b/bindings/java/src-completable/test/com/apple/foundationdb/test/BlockingBenchmark.java @@ -44,78 +44,59 @@ public class BlockingBenchmark { Transaction tr = database.createTransaction(); tr.setReadVersion(100000); - final Function identity = new Function() { - @Override - public Long apply(Long o) { - return o; - } - }; - System.out.println("readVersion().join():"); - runTests(tr, new Function, Void>() { - @Override - public Void apply(CompletableFuture o) { - try { - o.join(); - } catch(Exception e) { } - - return null; + runTests(tr, o -> { + try { + o.join(); + } catch(Exception e) { + // Ignore } + return null; }); System.out.println("readVersion().get():"); - runTests(tr, new Function, Void>() { - @Override - public Void apply(CompletableFuture o) { - try { - o.get(); - } catch (InterruptedException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch(Exception e) { } - - return null; + runTests(tr, o -> { + try { + o.get(); + } catch(Exception e) { + // Ignore } + return null; }); System.out.println("readVersion().thenApplyAsync(identity).get():"); - runTests(tr, new Function, Void>() { - @Override - public Void apply(CompletableFuture o) { - try { - o.thenApplyAsync(identity).get(); - } catch(Exception e) { } - - return null; + runTests(tr, o -> { + try { + o.thenApplyAsync(Function.identity(), FDB.DEFAULT_EXECUTOR).get(); + } catch(Exception e) { + // Ignore } + return null; }); System.out.println("readVersion().thenApplyAsync^10(identity).get():"); - runTests(tr, new Function, Void>() { - @Override - public Void apply(CompletableFuture o) { - for(int i=0; i<10; i++) - o = o.thenApplyAsync(identity); - try { - o.get(); - } catch(Exception e) { } - - return null; + runTests(tr, o -> { + for(int i=0; i<10; i++) + o = o.thenApplyAsync(Function.identity(), FDB.DEFAULT_EXECUTOR); + try { + o.get(); + } catch(Exception e) { + // Ignore } + return null; }); System.out.println("readVersion().get^100():"); - runTests(tr, new Function, Void>() { - @Override - public Void apply(CompletableFuture o) { - for(int i=0; i<100; i++) { - try { - o.get(); - } catch(Exception e) { } + runTests(tr, o -> { + for(int i=0; i<100; i++) { + try { + o.get(); + } catch(Exception e) { + // Ignore } - return null; } + return null; }); } @@ -124,7 +105,7 @@ public class BlockingBenchmark { for(int r=0; r<4; r++) { long start = System.currentTimeMillis(); for(int i = 0; i < REPS; i++) { - blockMethod.apply( tr.getReadVersion() ); + blockMethod.apply(tr.getReadVersion()); } long taken = System.currentTimeMillis() - start; @@ -145,4 +126,6 @@ public class BlockingBenchmark { System.out.println(" " + REPS + " done in " + taken + "ms -> " + (REPS / (taken)) + " KHz"); } } + + private BlockingBenchmark() {} } diff --git a/bindings/java/src-completable/test/com/apple/foundationdb/test/ConcurrentGetSetGet.java b/bindings/java/src-completable/test/com/apple/foundationdb/test/ConcurrentGetSetGet.java index e8cb0fd602..94b908548f 100644 --- a/bindings/java/src-completable/test/com/apple/foundationdb/test/ConcurrentGetSetGet.java +++ b/bindings/java/src-completable/test/com/apple/foundationdb/test/ConcurrentGetSetGet.java @@ -23,14 +23,11 @@ package com.apple.foundationdb.test; import java.nio.charset.Charset; import java.security.SecureRandom; import java.util.Random; -import java.util.concurrent.CompletableFuture; import java.util.concurrent.Semaphore; import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Function; import com.apple.foundationdb.Database; import com.apple.foundationdb.FDB; -import com.apple.foundationdb.Transaction; public class ConcurrentGetSetGet { public static final Charset UTF8 = Charset.forName("UTF-8"); @@ -55,25 +52,22 @@ public class ConcurrentGetSetGet { new ConcurrentGetSetGet().apply(database); } - public void apply(Database d) { - new Thread(new Runnable() { - @Override - public void run() { - int loops = 0; - try { - Thread.sleep(5000); - System.out.println("Loop " + loops++ + ":"); - System.out.println(" attempts: " + attemptCount.get()); - System.out.println(" gets complete: " + getCompleteCount.get()); - System.out.println(" errors: " + errorCount.get()); - System.out.println(" sem: " + semaphore); - System.out.println(); - } catch (InterruptedException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - + public void apply(Database db) { + new Thread(() -> { + int loops = 0; + try { + Thread.sleep(5000); + System.out.println("Loop " + loops++ + ":"); + System.out.println(" attempts: " + attemptCount.get()); + System.out.println(" gets complete: " + getCompleteCount.get()); + System.out.println(" errors: " + errorCount.get()); + System.out.println(" sem: " + semaphore); + System.out.println(); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); } + }).start(); final Random random = new SecureRandom(); try { @@ -86,50 +80,37 @@ public class ConcurrentGetSetGet { System.out.println("Waited " + wait + "ms"); } current = System.currentTimeMillis(); - d.runAsync(new Function>() { - @Override - public CompletableFuture apply(final Transaction r) { - attemptCount.addAndGet(1); - final String key = "test:" + random.nextInt(); - return r.get($(key)).thenComposeAsync(new Function>() { - @Override - public CompletableFuture apply(byte[] o) { - r.set($(key), $("value")); - return r.get($(key)).thenApplyAsync(new Function() { - @Override - public Void apply(byte[] o) { - getCompleteCount.addAndGet(1); - semaphore.release(); - return null; - } - }); - } - }).exceptionally(new Function() { - @Override - public Void apply(Throwable o) { - errorCount.addAndGet(1); - System.err.println("Fail (" + o.getMessage() + ")"); - semaphore.release(); - return null; - } - }); - } + db.runAsync(tr -> { + attemptCount.addAndGet(1); + final String key = "test:" + random.nextInt(); + return tr.get($(key)).thenComposeAsync(ignore -> { + tr.set($(key), $("value")); + return tr.get($(key)).thenRunAsync(() -> { + getCompleteCount.addAndGet(1); + semaphore.release(); + }, FDB.DEFAULT_EXECUTOR); + }, FDB.DEFAULT_EXECUTOR).exceptionally(t -> { + errorCount.addAndGet(1); + System.err.println("Fail (" + t.getMessage() + ")"); + semaphore.release(); + return null; + }); }); } semaphore.acquire(CONCURRENCY); long diff = System.currentTimeMillis() - start; System.out.println("time taken (ms): " + diff); - System.out.println("tr/sec:" + COUNT * 1000l / diff); + System.out.println("tr/sec:" + COUNT * 1000L / diff); System.out.println("attempts: " + attemptCount.get()); System.out.println("gets complete: " + getCompleteCount.get()); System.out.println("errors: " + errorCount.get()); System.out.println(); // Can be enabled in Database.java - //System.out.println("db success: " + d.commitSuccessCount.get()); - //System.out.println("db errors: " + d.commitErrorCount.get()); + //System.out.println("db success: " + db.commitSuccessCount.get()); + //System.out.println("db errors: " + db.commitErrorCount.get()); System.exit(0); - } catch (Throwable throwable) { - throwable.printStackTrace(); + } catch (Throwable t) { + t.printStackTrace(); System.exit(1); } } diff --git a/bindings/java/src-completable/test/com/apple/foundationdb/test/Context.java b/bindings/java/src-completable/test/com/apple/foundationdb/test/Context.java index fb0f80f187..489cac7c5f 100644 --- a/bindings/java/src-completable/test/com/apple/foundationdb/test/Context.java +++ b/bindings/java/src-completable/test/com/apple/foundationdb/test/Context.java @@ -20,6 +20,7 @@ package com.apple.foundationdb.test; +import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; import java.util.List; @@ -29,6 +30,7 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.CompletableFuture; import com.apple.foundationdb.Database; +import com.apple.foundationdb.FDB; import com.apple.foundationdb.FDBException; import com.apple.foundationdb.KeySelector; import com.apple.foundationdb.Range; @@ -47,8 +49,8 @@ abstract class Context implements Runnable, AutoCloseable { private String trName; private List children = new LinkedList<>(); - static private Map transactionMap = new HashMap<>(); - static private Map transactionRefCounts = new HashMap<>(); + private static Map transactionMap = new HashMap<>(); + private static Map transactionRefCounts = new HashMap<>(); Context(Database db, byte[] prefix) { this.db = db; @@ -171,8 +173,7 @@ abstract class Context implements Runnable, AutoCloseable { while(num-- > 0) { Object item = stack.pop().value; if(item instanceof CompletableFuture) { - @SuppressWarnings("unchecked") - final CompletableFuture future = (CompletableFuture)item; + final CompletableFuture future = (CompletableFuture)item; final int nextNum = num; future.whenCompleteAsync((o, t) -> { if(t != null) { @@ -193,7 +194,7 @@ abstract class Context implements Runnable, AutoCloseable { popParams(nextNum, params, done); } - }); + }, FDB.DEFAULT_EXECUTOR); return; } @@ -205,11 +206,11 @@ abstract class Context implements Runnable, AutoCloseable { } CompletableFuture> popParams(int num) { - final List params = new LinkedList<>(); + final List params = new ArrayList<>(num); CompletableFuture done = new CompletableFuture<>(); popParams(num, params, done); - return done.thenApplyAsync((x) -> params); + return done.thenApply(x -> params); } @Override diff --git a/bindings/java/src-completable/test/com/apple/foundationdb/test/ContinuousSample.java b/bindings/java/src-completable/test/com/apple/foundationdb/test/ContinuousSample.java index 3602eb6e30..7eaf403d5c 100644 --- a/bindings/java/src-completable/test/com/apple/foundationdb/test/ContinuousSample.java +++ b/bindings/java/src-completable/test/com/apple/foundationdb/test/ContinuousSample.java @@ -25,54 +25,59 @@ import java.util.Collections; import java.util.List; import java.util.Random; -public class ContinuousSample > { - public ContinuousSample( int sampleSize ) { +public class ContinuousSample> { + public ContinuousSample(int sampleSize) { this.sampleSize = sampleSize; - this.samples = new ArrayList(sampleSize); + this.samples = new ArrayList<>(sampleSize); this.populationSize = 0; this.sorted = true; } public ContinuousSample addSample(T sample) { if(populationSize == 0) - _min = _max = sample; + min = max = sample; populationSize++; sorted = false; - if( populationSize <= sampleSize ) { - samples.add( sample ); - } else if( random.nextDouble() < ( (double)sampleSize / populationSize ) ) { + if(populationSize <= sampleSize) { + samples.add(sample); + } else if(random.nextDouble() < ((double)sampleSize / populationSize)) { samples.add(random.nextInt(sampleSize), sample); } - _max = sample.compareTo(_max) > 0 ? sample : _max; - _min = sample.compareTo(_min) < 0 ? sample : _min; + max = sample.compareTo(max) > 0 ? sample : max; + min = sample.compareTo(min) < 0 ? sample : min; return this; } public double mean() { if (samples.size() == 0) return 0; double sum = 0; - for( int c = 0; c < samples.size(); c++ ) { + for(int c = 0; c < samples.size(); c++) { sum += samples.get(c).doubleValue(); } return sum / samples.size(); } public T median() { - return percentile( 0.5 ); + return percentile(0.5); } - public T percentile( double percentile ) { - if( samples.size() == 0 || percentile < 0.0 || percentile > 1.0 ) + public T percentile(double percentile) { + if(samples.size() == 0 || percentile < 0.0 || percentile > 1.0) return null; sort(); - int idx = (int)Math.floor( ( samples.size() - 1 ) * percentile ); + int idx = (int)Math.floor((samples.size() - 1) * percentile); return samples.get(idx); } - public T min() { return _min; } - public T max() { return _max; } + public T min() { + return min; + } + + public T max() { + return max; + } @Override public String toString() { @@ -85,10 +90,10 @@ public class ContinuousSample > { private long populationSize; private boolean sorted; private List samples; - private T _min, _max; + private T min, max; private void sort() { - if( !sorted && samples.size() > 1 ) + if(!sorted && samples.size() > 1) Collections.sort(samples); sorted = true; } diff --git a/bindings/java/src-completable/test/com/apple/foundationdb/test/DirectoryTest.java b/bindings/java/src-completable/test/com/apple/foundationdb/test/DirectoryTest.java index 0832fcc9ce..9fcfc4cb82 100644 --- a/bindings/java/src-completable/test/com/apple/foundationdb/test/DirectoryTest.java +++ b/bindings/java/src-completable/test/com/apple/foundationdb/test/DirectoryTest.java @@ -24,12 +24,9 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.function.Function; - import com.apple.foundationdb.Cluster; import com.apple.foundationdb.Database; import com.apple.foundationdb.FDB; -import com.apple.foundationdb.Transaction; import com.apple.foundationdb.TransactionContext; import com.apple.foundationdb.directory.DirectoryLayer; import com.apple.foundationdb.directory.DirectorySubspace; @@ -52,33 +49,30 @@ public class DirectoryTest { final DirectoryLayer dir = new DirectoryLayer(); try { - db.run(new Function() { - @Override - public Void apply(Transaction tr) { - List path = new ArrayList<>(); - path.add("foo"); - DirectorySubspace foo = dir.create(tr, path).join();//, "partition".getBytes("UTF-8")).get(); - System.out.println(foo.getPath()); - path.add("bar"); - DirectorySubspace bar = dir.create(tr, path).join();//, "partition".getBytes("UTF-8")).get(); - System.out.println(foo.getPath()); - path.add("baz"); - DirectorySubspace baz = dir.create(tr, path).join(); - System.out.println(foo.getPath()); - System.out.println("Created foo: " + foo.exists(tr).join()); - System.out.println("Created bar: " + bar.exists(tr).join()); - System.out.println("Created baz: " + baz.exists(tr).join()); + db.run(tr -> { + List path = new ArrayList<>(); + path.add("foo"); + DirectorySubspace foo = dir.create(tr, path).join(); //, "partition".getBytes("UTF-8")).get(); + System.out.println(foo.getPath()); + path.add("bar"); + DirectorySubspace bar = dir.create(tr, path).join(); //, "partition".getBytes("UTF-8")).get(); + System.out.println(foo.getPath()); + path.add("baz"); + DirectorySubspace baz = dir.create(tr, path).join(); + System.out.println(foo.getPath()); + System.out.println("Created foo: " + foo.exists(tr).join()); + System.out.println("Created bar: " + bar.exists(tr).join()); + System.out.println("Created baz: " + baz.exists(tr).join()); - DirectorySubspace bat = baz.moveTo(tr, Arrays.asList("foo", "bar", "bat")).join(); + DirectorySubspace bat = baz.moveTo(tr, Arrays.asList("foo", "bar", "bat")).join(); - System.out.println("Moved baz to bat: " + bat.exists(tr).join()); + System.out.println("Moved baz to bat: " + bat.exists(tr).join()); - foo.removeIfExists(tr).join(); + foo.removeIfExists(tr).join(); - System.out.println("Removed foo: " + foo.exists(tr).join()); + System.out.println("Removed foo: " + foo.exists(tr).join()); - return null; - } + return null; }); } catch (Throwable e) { e.printStackTrace(); @@ -86,4 +80,6 @@ public class DirectoryTest { System.exit(0); } + + private DirectoryTest() {} } diff --git a/bindings/java/src-completable/test/com/apple/foundationdb/test/DirectoryUtil.java b/bindings/java/src-completable/test/com/apple/foundationdb/test/DirectoryUtil.java index 21cdca0b87..824b3e415d 100644 --- a/bindings/java/src-completable/test/com/apple/foundationdb/test/DirectoryUtil.java +++ b/bindings/java/src-completable/test/com/apple/foundationdb/test/DirectoryUtil.java @@ -23,9 +23,8 @@ package com.apple.foundationdb.test; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CompletableFuture; -import java.util.function.Function; -import java.util.function.Supplier; +import com.apple.foundationdb.FDB; import com.apple.foundationdb.async.AsyncUtil; import com.apple.foundationdb.tuple.Tuple; @@ -41,34 +40,18 @@ class DirectoryUtil { } CompletableFuture> pop() { - return AsyncUtil.whileTrue(new Supplier>() { - @Override - public CompletableFuture get() { - if(num-- == 0) { - return CompletableFuture.completedFuture(false); - } - return inst.popParam() - .thenComposeAsync(new Function>>() { - @Override - public CompletableFuture> apply(Object count) { - return inst.popParams(StackUtils.getInt(count)); - } - }) - .thenApplyAsync(new Function, Boolean>() { - @Override - public Boolean apply(List elements) { + return AsyncUtil.whileTrue(() -> { + if(num-- == 0) { + return AsyncUtil.READY_FALSE; + } + return inst.popParam() + .thenComposeAsync(count -> inst.popParams(StackUtils.getInt(count)), FDB.DEFAULT_EXECUTOR) + .thenApplyAsync(elements -> { tuples.add(Tuple.fromItems(elements)); return num > 0; - } - }); - } + }, FDB.DEFAULT_EXECUTOR); }) - .thenApplyAsync(new Function>() { - @Override - public List apply(Void ignore) { - return tuples; - } - }); + .thenApply(ignore -> tuples); } } @@ -77,42 +60,26 @@ class DirectoryUtil { } static CompletableFuture popTuple(Instruction inst) { - return popTuples(inst, 1) - .thenApplyAsync(new Function, Tuple>() { - @Override - public Tuple apply(List tuples) { - return tuples.get(0); - } - }); + return popTuples(inst, 1).thenApply(tuples -> tuples.get(0)); } static CompletableFuture>> popPaths(Instruction inst, int num) { - return popTuples(inst, num) - .thenApplyAsync(new Function, List>>() { - @Override - public List> apply(List tuples) { - List> paths = new ArrayList>(); - for(Tuple t : tuples) { - List path = new ArrayList(); - for(int i = 0; i < t.size(); ++i) - path.add(t.getString(i)); + return popTuples(inst, num).thenApplyAsync(tuples -> { + List> paths = new ArrayList<>(tuples.size()); + for(Tuple t : tuples) { + List path = new ArrayList<>(t.size()); + for(int i = 0; i < t.size(); ++i) + path.add(t.getString(i)); - paths.add(path); - } - - return paths; + paths.add(path); } - }); + + return paths; + }, FDB.DEFAULT_EXECUTOR); } static CompletableFuture> popPath(Instruction inst) { - return popPaths(inst, 1) - .thenApplyAsync(new Function>, List>() { - @Override - public List apply(List> paths) { - return paths.get(0); - } - }); + return popPaths(inst, 1).thenApply(paths -> paths.get(0)); } static void pushError(Instruction inst, Throwable t, List dirList) { @@ -123,4 +90,6 @@ class DirectoryUtil { if(op.createsDirectory) dirList.add(null); } + + private DirectoryUtil() {} } diff --git a/bindings/java/src-completable/test/com/apple/foundationdb/test/Example.java b/bindings/java/src-completable/test/com/apple/foundationdb/test/Example.java index eb7d648bf6..f78f0eea05 100644 --- a/bindings/java/src-completable/test/com/apple/foundationdb/test/Example.java +++ b/bindings/java/src-completable/test/com/apple/foundationdb/test/Example.java @@ -29,27 +29,23 @@ import com.apple.foundationdb.Transaction; import com.apple.foundationdb.tuple.Tuple; public class Example { - public static void main(String[] args) throws ExecutionException, InterruptedException { - FDB fdb = FDB.selectAPIVersion(510); - Database db = fdb.open(); + public static void main(String[] args) throws ExecutionException, InterruptedException { + FDB fdb = FDB.selectAPIVersion(510); + Database db = fdb.open(); - // Run an operation on the database - db.run(new Function() { - @Override - public Void apply(Transaction tr) { - tr.set(Tuple.from("hello").pack(), Tuple.from("world").pack()); - return null; - } - }); + // Run an operation on the database + db.run((Function) tr -> { + tr.set(Tuple.from("hello").pack(), Tuple.from("world").pack()); + return null; + }); - // Get the value of 'hello' from the database - String hello = db.run(new Function() { - @Override - public String apply(Transaction tr) { - byte[] result = tr.get(Tuple.from("hello").pack()).join(); - return Tuple.fromBytes(result).getString(0); - } - }); - System.out.println("Hello " + hello); - } + // Get the value of 'hello' from the database + String hello = db.run(tr -> { + byte[] result = tr.get(Tuple.from("hello").pack()).join(); + return Tuple.fromBytes(result).getString(0); + }); + System.out.println("Hello " + hello); + } + + private Example() {} } diff --git a/bindings/java/src-completable/test/com/apple/foundationdb/test/Instruction.java b/bindings/java/src-completable/test/com/apple/foundationdb/test/Instruction.java index 82792f041b..a16bda49e9 100644 --- a/bindings/java/src-completable/test/com/apple/foundationdb/test/Instruction.java +++ b/bindings/java/src-completable/test/com/apple/foundationdb/test/Instruction.java @@ -21,6 +21,7 @@ package com.apple.foundationdb.test; import java.util.concurrent.CompletableFuture; +import java.util.List; import com.apple.foundationdb.ReadTransaction; import com.apple.foundationdb.ReadTransactionContext; @@ -28,11 +29,10 @@ import com.apple.foundationdb.Transaction; import com.apple.foundationdb.TransactionContext; import com.apple.foundationdb.tuple.Tuple; -import java.util.List; class Instruction extends Stack { - private final static String SUFFIX_SNAPSHOT = "_SNAPSHOT"; - private final static String SUFFIX_DATABASE = "_DATABASE"; + private static final String SUFFIX_SNAPSHOT = "_SNAPSHOT"; + private static final String SUFFIX_DATABASE = "_DATABASE"; final String op; final Tuple tokens; diff --git a/bindings/java/src-completable/test/com/apple/foundationdb/test/IterableTest.java b/bindings/java/src-completable/test/com/apple/foundationdb/test/IterableTest.java index f3cf2c2d65..9bbb780b0e 100644 --- a/bindings/java/src-completable/test/com/apple/foundationdb/test/IterableTest.java +++ b/bindings/java/src-completable/test/com/apple/foundationdb/test/IterableTest.java @@ -21,13 +21,11 @@ package com.apple.foundationdb.test; import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Function; import com.apple.foundationdb.Cluster; import com.apple.foundationdb.Database; import com.apple.foundationdb.FDB; import com.apple.foundationdb.KeyValue; -import com.apple.foundationdb.Transaction; import com.apple.foundationdb.TransactionContext; public class IterableTest { @@ -49,14 +47,11 @@ public class IterableTest { long start = System.currentTimeMillis(); final AtomicInteger lastcount = new AtomicInteger(0); try { - db.run(new Function() { - @Override - public Void apply(Transaction tr) { - for(KeyValue e : tr.getRange("vcount".getBytes(), "zz".getBytes())) { - System.out.println("K: " + new String(e.getKey()) + ", V: " + new String(e.getValue())); - } - return null; + db.run(tr -> { + for(KeyValue e : tr.getRange("vcount".getBytes(), "zz".getBytes())) { + System.out.println("K: " + new String(e.getKey()) + ", V: " + new String(e.getValue())); } + return null; }); } catch (Throwable e) { e.printStackTrace(); @@ -71,4 +66,6 @@ public class IterableTest { System.exit(0); } + + private IterableTest() {} } diff --git a/bindings/java/src-completable/test/com/apple/foundationdb/test/LocalityTests.java b/bindings/java/src-completable/test/com/apple/foundationdb/test/LocalityTests.java index 5d3e049e36..fd9940fb74 100644 --- a/bindings/java/src-completable/test/com/apple/foundationdb/test/LocalityTests.java +++ b/bindings/java/src-completable/test/com/apple/foundationdb/test/LocalityTests.java @@ -36,17 +36,16 @@ public class LocalityTests { public static void main(String[] args) { FDB fdb = FDB.selectAPIVersion(510); Database database = fdb.open(args[0]); - { - Transaction tr = database.createTransaction(); - String[] keyAddresses = LocalityUtil.getAddressesForKey(tr, "a".getBytes()).join(); - for(String s : keyAddresses) { - System.out.println(" @ " + s); - } + + Transaction tr = database.createTransaction(); + String[] keyAddresses = LocalityUtil.getAddressesForKey(tr, "a".getBytes()).join(); + for(String s : keyAddresses) { + System.out.println(" @ " + s); } long start = System.currentTimeMillis(); - CloseableAsyncIterator keys = LocalityUtil.getBoundaryKeys(database, new byte[0], new byte[] { (byte)255 } ); + CloseableAsyncIterator keys = LocalityUtil.getBoundaryKeys(database, new byte[0], new byte[] { (byte)255 }); CompletableFuture> collection = AsyncUtil.collect(keys); List list = collection.join(); System.out.println("Took " + (System.currentTimeMillis() - start) + "ms to get " + @@ -59,4 +58,6 @@ public class LocalityTests { System.out.println(i++ + ": " + ByteArrayUtil.printable(key)); } } + + private LocalityTests() {} } diff --git a/bindings/java/src-completable/test/com/apple/foundationdb/test/ParallelRandomScan.java b/bindings/java/src-completable/test/com/apple/foundationdb/test/ParallelRandomScan.java index bee8dbfaf5..d32ed9bdb1 100644 --- a/bindings/java/src-completable/test/com/apple/foundationdb/test/ParallelRandomScan.java +++ b/bindings/java/src-completable/test/com/apple/foundationdb/test/ParallelRandomScan.java @@ -25,8 +25,6 @@ import java.util.Random; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Semaphore; import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.BiConsumer; -import java.util.function.Function; import com.apple.foundationdb.Database; import com.apple.foundationdb.FDB; @@ -92,34 +90,26 @@ public class ParallelRandomScan { final long launch = System.nanoTime(); final AsyncIterator it = range.iterator(); - final CompletableFuture f = it.onHasNext().thenApplyAsync( - new Function() { - @Override - public KeyValue apply(Boolean o) { - if(!o) { - return null; - } - return it.next(); - } - } - ); - f.whenCompleteAsync(new BiConsumer() { - @Override - public void accept(KeyValue kv, Throwable t) { - if(kv != null) { - readsCompleted.incrementAndGet(); - long timeTaken = System.nanoTime() - launch; - synchronized(latencies) { - latencies.addSample(timeTaken); - } - } - else if(t != null) { - errors.incrementAndGet(); - } - - coordinator.release(); + final CompletableFuture f = it.onHasNext().thenApplyAsync(hasFirst -> { + if(!hasFirst) { + return null; } - }); + return it.next(); + }, FDB.DEFAULT_EXECUTOR); + f.whenCompleteAsync((kv, t) -> { + if(kv != null) { + readsCompleted.incrementAndGet(); + long timeTaken = System.nanoTime() - launch; + synchronized(latencies) { + latencies.addSample(timeTaken); + } + } + else if(t != null) { + errors.incrementAndGet(); + } + + coordinator.release(); + }, FDB.DEFAULT_EXECUTOR); } // Block for ALL tasks to end! @@ -133,4 +123,6 @@ public class ParallelRandomScan { System.out.println(String.format(" Mean: %.2f, Median: %d, 98%%: %d", latencies.mean(), latencies.median(), latencies.percentile(0.98))); } + + private ParallelRandomScan() {} } diff --git a/bindings/java/src-completable/test/com/apple/foundationdb/test/PerformanceTester.java b/bindings/java/src-completable/test/com/apple/foundationdb/test/PerformanceTester.java index 5f604d22f5..57747b2dc0 100644 --- a/bindings/java/src-completable/test/com/apple/foundationdb/test/PerformanceTester.java +++ b/bindings/java/src-completable/test/com/apple/foundationdb/test/PerformanceTester.java @@ -20,13 +20,6 @@ package com.apple.foundationdb.test; -import com.apple.foundationdb.Database; -import com.apple.foundationdb.KeySelector; -import com.apple.foundationdb.Transaction; -import com.apple.foundationdb.TransactionContext; -import com.apple.foundationdb.async.AsyncUtil; -import com.apple.foundationdb.tuple.ByteArrayUtil; - import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -40,6 +33,13 @@ import java.util.stream.Collectors; import java.util.stream.IntStream; import java.util.stream.Stream; +import com.apple.foundationdb.Database; +import com.apple.foundationdb.KeySelector; +import com.apple.foundationdb.Transaction; +import com.apple.foundationdb.TransactionContext; +import com.apple.foundationdb.async.AsyncUtil; +import com.apple.foundationdb.tuple.ByteArrayUtil; + public class PerformanceTester extends AbstractTester { private final int keyCount; private final int keySize; diff --git a/bindings/java/src-completable/test/com/apple/foundationdb/test/RYWBenchmark.java b/bindings/java/src-completable/test/com/apple/foundationdb/test/RYWBenchmark.java index 501848a52c..aee1f06b59 100644 --- a/bindings/java/src-completable/test/com/apple/foundationdb/test/RYWBenchmark.java +++ b/bindings/java/src-completable/test/com/apple/foundationdb/test/RYWBenchmark.java @@ -20,14 +20,17 @@ package com.apple.foundationdb.test; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; + import com.apple.foundationdb.Database; import com.apple.foundationdb.Transaction; import com.apple.foundationdb.tuple.ByteArrayUtil; -import java.util.*; -import java.util.function.Function; -import java.util.stream.Collectors; - public class RYWBenchmark extends AbstractTester { private int keyCount; @@ -156,7 +159,7 @@ public class RYWBenchmark extends AbstractTester { public Double getRangeBasic(Transaction tr, int count) { long start = System.nanoTime(); for (int i = 0; i < count; i++) { - tr.getRange(key(0), key(keyCount)).asList().join(); + tr.getRange(key(0), key(keyCount)).asList().join(); } long end = System.nanoTime(); diff --git a/bindings/java/src-completable/test/com/apple/foundationdb/test/RangeTest.java b/bindings/java/src-completable/test/com/apple/foundationdb/test/RangeTest.java index 9426c6cd5d..768aa35335 100644 --- a/bindings/java/src-completable/test/com/apple/foundationdb/test/RangeTest.java +++ b/bindings/java/src-completable/test/com/apple/foundationdb/test/RangeTest.java @@ -55,22 +55,19 @@ public class RangeTest { Database db = fdb.open(); try { - db.run(new Function() { - @Override - public Void apply(Transaction tr) { - long version = tr.getReadVersion().join(); - System.out.println("DB version: " + version); - tr.get("apple1".getBytes()).join(); - tr.set("apple1".getBytes(), "crunchy1".getBytes()); - tr.set("apple2".getBytes(), "crunchy2".getBytes()); - tr.set("apple3".getBytes(), "crunchy3".getBytes()); - tr.set("apple4".getBytes(), "crunchy4".getBytes()); - tr.set("apple5".getBytes(), "crunchy5".getBytes()); - tr.set("apple6".getBytes(), "crunchy6".getBytes()); - System.out.println("Attempting to commit apple/crunchy pairs..."); + db.run((Function) tr -> { + long version = tr.getReadVersion().join(); + System.out.println("DB version: " + version); + tr.get("apple1".getBytes()).join(); + tr.set("apple1".getBytes(), "crunchy1".getBytes()); + tr.set("apple2".getBytes(), "crunchy2".getBytes()); + tr.set("apple3".getBytes(), "crunchy3".getBytes()); + tr.set("apple4".getBytes(), "crunchy4".getBytes()); + tr.set("apple5".getBytes(), "crunchy5".getBytes()); + tr.set("apple6".getBytes(), "crunchy6".getBytes()); + System.out.println("Attempting to commit apple/crunchy pairs..."); - return null; - } + return null; }); } catch (Throwable e){ e.printStackTrace(); @@ -167,7 +164,7 @@ public class RangeTest { System.out.println("Value is " + (val != null ? new String(val) : "not present")); - AsyncIterable entryList = tr.getRange( + AsyncIterable entryList = tr.getRange( KeySelector.firstGreaterOrEqual("apple".getBytes()), KeySelector.firstGreaterOrEqual("banana".getBytes()),4); List entries = entryList.asList().join(); @@ -187,4 +184,6 @@ public class RangeTest { } } + + private RangeTest() {} } diff --git a/bindings/java/src-completable/test/com/apple/foundationdb/test/SerialInsertion.java b/bindings/java/src-completable/test/com/apple/foundationdb/test/SerialInsertion.java index dde5606544..642fc71a92 100644 --- a/bindings/java/src-completable/test/com/apple/foundationdb/test/SerialInsertion.java +++ b/bindings/java/src-completable/test/com/apple/foundationdb/test/SerialInsertion.java @@ -94,4 +94,5 @@ public class SerialInsertion { } } + private SerialInsertion() {} } diff --git a/bindings/java/src-completable/test/com/apple/foundationdb/test/SerialIteration.java b/bindings/java/src-completable/test/com/apple/foundationdb/test/SerialIteration.java index 445f998edd..422ea0307c 100644 --- a/bindings/java/src-completable/test/com/apple/foundationdb/test/SerialIteration.java +++ b/bindings/java/src-completable/test/com/apple/foundationdb/test/SerialIteration.java @@ -133,4 +133,6 @@ public class SerialIteration { } return counter; } + + private SerialIteration() {} } diff --git a/bindings/java/src-completable/test/com/apple/foundationdb/test/SerialTest.java b/bindings/java/src-completable/test/com/apple/foundationdb/test/SerialTest.java index 48ead15d57..526758d308 100644 --- a/bindings/java/src-completable/test/com/apple/foundationdb/test/SerialTest.java +++ b/bindings/java/src-completable/test/com/apple/foundationdb/test/SerialTest.java @@ -21,12 +21,10 @@ package com.apple.foundationdb.test; import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Function; import com.apple.foundationdb.Cluster; import com.apple.foundationdb.Database; import com.apple.foundationdb.FDB; -import com.apple.foundationdb.Transaction; import com.apple.foundationdb.TransactionContext; public class SerialTest { @@ -56,17 +54,14 @@ public class SerialTest { final AtomicInteger lastcount = new AtomicInteger(0); for(int i = 0; i < reps; i++) { try { - db.run(new Function() { - @Override - public Void apply(Transaction tr) { - byte[] val = tr.get("count".getBytes()).join(); - //System.out.println("Got value"); - int count = Integer.parseInt(new String(val)); - tr.set("count".getBytes(), Integer.toString(count + 1).getBytes()); - lastcount.set(count); + db.run(tr -> { + byte[] val = tr.get("count".getBytes()).join(); + //System.out.println("Got value"); + int count = Integer.parseInt(new String(val)); + tr.set("count".getBytes(), Integer.toString(count + 1).getBytes()); + lastcount.set(count); - return null; - } + return null; }); } catch (Throwable e) { e.printStackTrace(); @@ -83,4 +78,5 @@ public class SerialTest { System.exit(0); } + private SerialTest() {} } diff --git a/bindings/java/src-completable/test/com/apple/foundationdb/test/StackTester.java b/bindings/java/src-completable/test/com/apple/foundationdb/test/StackTester.java index 343a2f6bc1..76bc437448 100644 --- a/bindings/java/src-completable/test/com/apple/foundationdb/test/StackTester.java +++ b/bindings/java/src-completable/test/com/apple/foundationdb/test/StackTester.java @@ -21,10 +21,15 @@ package com.apple.foundationdb.test; import java.math.BigInteger; -import java.util.*; - import java.nio.ByteBuffer; import java.nio.ByteOrder; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; import java.util.function.Function; @@ -110,7 +115,7 @@ public class StackTester { } else if(op == StackOperation.WAIT_EMPTY) { List params = inst.popParams(1).join(); - inst.context.db.run(new WaitEmpty((byte [])params.get(0))); + inst.context.db.run(new WaitEmpty((byte[])params.get(0))); inst.push("WAITED_FOR_EMPTY".getBytes()); } else if(op == StackOperation.START_THREAD) { @@ -129,62 +134,40 @@ public class StackTester { final List params = inst.popParams(2).join(); //System.out.println(inst.context.preStr + " - " + "Setting '" + ArrayUtils.printable((byte[]) params.get(0)) + // "' to '" + ArrayUtils.printable((byte[]) params.get(1)) + "'"); - executeMutation(inst, - new Function() { - @Override - public Void apply(Transaction tr) { - tr.set((byte[])params.get(0), (byte[])params.get(1)); - return null; - } - }); + executeMutation(inst, tr -> { + tr.set((byte[])params.get(0), (byte[])params.get(1)); + return null; + }); } else if(op == StackOperation.CLEAR) { final List params = inst.popParams(1).join(); //System.out.println(inst.context.preStr + " - " + "Clearing: '" + ByteArrayUtil.printable((byte[]) params.get(0)) + "'"); - executeMutation(inst, - new Function() { - @Override - public Void apply(Transaction tr) { - tr.clear((byte[])params.get(0)); - return null; - } - } - ); + executeMutation(inst, tr -> { + tr.clear((byte[])params.get(0)); + return null; + }); } else if(op == StackOperation.CLEAR_RANGE) { final List params = inst.popParams(2).join(); - executeMutation(inst, - new Function() { - @Override - public Void apply(Transaction tr) { - tr.clear((byte[])params.get(0), (byte[])params.get(1)); - return null; - } - }); + executeMutation(inst, tr -> { + tr.clear((byte[])params.get(0), (byte[])params.get(1)); + return null; + }); } else if(op == StackOperation.CLEAR_RANGE_STARTS_WITH) { final List params = inst.popParams(1).join(); - executeMutation(inst, - new Function() { - @Override - public Void apply(Transaction tr) { - tr.clear(Range.startsWith((byte[])params.get(0))); - return null; - } - }); + executeMutation(inst, tr -> { + tr.clear(Range.startsWith((byte[])params.get(0))); + return null; + }); } else if(op == StackOperation.ATOMIC_OP) { final List params = inst.popParams(3).join(); final MutationType optype = MutationType.valueOf((String)params.get(0)); - executeMutation(inst, - new Function() { - @Override - public Void apply(Transaction tr) { - tr.mutate(optype, (byte[])params.get(1), (byte[])params.get(2)); - return null; - } - } - ); + executeMutation(inst, tr -> { + tr.mutate(optype, (byte[])params.get(1), (byte[])params.get(2)); + return null; + }); } else if(op == StackOperation.COMMIT) { inst.push(inst.tr.commit()); @@ -723,5 +706,7 @@ public class StackTester { db.close(); System.gc(); } + + private StackTester() {} } diff --git a/bindings/java/src-completable/test/com/apple/foundationdb/test/StackUtils.java b/bindings/java/src-completable/test/com/apple/foundationdb/test/StackUtils.java index 5da664d60d..21210efc68 100644 --- a/bindings/java/src-completable/test/com/apple/foundationdb/test/StackUtils.java +++ b/bindings/java/src-completable/test/com/apple/foundationdb/test/StackUtils.java @@ -27,7 +27,6 @@ import java.util.concurrent.CompletionException; import com.apple.foundationdb.FDBException; import com.apple.foundationdb.KeySelector; -import com.apple.foundationdb.async.AsyncUtil; import com.apple.foundationdb.tuple.Tuple; public class StackUtils { @@ -127,4 +126,6 @@ public class StackUtils { return (t instanceof FDBException) ? (FDBException)t : null; } + + private StackUtils() {} } diff --git a/bindings/java/src-completable/test/com/apple/foundationdb/test/TesterArgs.java b/bindings/java/src-completable/test/com/apple/foundationdb/test/TesterArgs.java index fc4f604731..1d6d30a78d 100644 --- a/bindings/java/src-completable/test/com/apple/foundationdb/test/TesterArgs.java +++ b/bindings/java/src-completable/test/com/apple/foundationdb/test/TesterArgs.java @@ -20,13 +20,12 @@ package com.apple.foundationdb.test; +import java.util.ArrayList; +import java.util.List; + import com.apple.foundationdb.subspace.Subspace; import com.apple.foundationdb.tuple.Tuple; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - public class TesterArgs { private String outputDirectory; private boolean multiversionApi; @@ -45,15 +44,15 @@ public class TesterArgs { } public static void printUsage() { - String usage = "Arguments: [-o/--output-directory DIR] [--disable-multiversion-api] [--enable-callbacks-on-external-threads] [--use-external-client] [--tests-to-run TEST [TEST ...]] [-h/--help]\n" - + "\n" - + "Arguments:\n" - + " -o/--output-directory DIR Directory to store JSON output. If not set, the current directory is used.\n" - + " --disable-multiversion-api Disables the multi-version client API\n" - + " --enable-callbacks-on-external-threads Allows callbacks to be called on threads created by the client library.\n" - + " --use-external-client Connect to the server using an external client.\n" - + " --tests-to-run TEST [TEST ...] List of test names to run.\n" - + " -h/--help Print this help message and then quit.\n"; + String usage = "Arguments: [-o/--output-directory DIR] [--disable-multiversion-api] [--enable-callbacks-on-external-threads] [--use-external-client] [--tests-to-run TEST [TEST ...]] [-h/--help]\n" + + "\n" + + "Arguments:\n" + + " -o/--output-directory DIR Directory to store JSON output. If not set, the current directory is used.\n" + + " --disable-multiversion-api Disables the multi-version client API\n" + + " --enable-callbacks-on-external-threads Allows callbacks to be called on threads created by the client library.\n" + + " --use-external-client Connect to the server using an external client.\n" + + " --tests-to-run TEST [TEST ...] List of test names to run.\n" + + " -h/--help Print this help message and then quit.\n"; System.out.print(usage); } diff --git a/bindings/java/src-completable/test/com/apple/foundationdb/test/TupleTest.java b/bindings/java/src-completable/test/com/apple/foundationdb/test/TupleTest.java index 3946cbf9be..28b1b3c5ec 100644 --- a/bindings/java/src-completable/test/com/apple/foundationdb/test/TupleTest.java +++ b/bindings/java/src-completable/test/com/apple/foundationdb/test/TupleTest.java @@ -20,12 +20,9 @@ package com.apple.foundationdb.test; -import java.util.function.Function; - import com.apple.foundationdb.Cluster; import com.apple.foundationdb.Database; import com.apple.foundationdb.FDB; -import com.apple.foundationdb.Transaction; import com.apple.foundationdb.TransactionContext; import com.apple.foundationdb.tuple.Tuple; @@ -47,19 +44,16 @@ public class TupleTest { System.out.println("Running tests..."); long start = System.currentTimeMillis(); try { - db.run(new Function() { - @Override - public Void apply(Transaction tr) { - Tuple t = new Tuple(); - t.add(100230045000L); - t.add("Hello!"); - t.add("foo".getBytes()); + db.run(tr -> { + Tuple t = new Tuple(); + t.add(100230045000L); + t.add("Hello!"); + t.add("foo".getBytes()); - /*for(Map.Entry e : tr.getRange("vcount".getBytes(), "zz".getBytes())) { - System.out.println("K: " + new String(e.getKey()) + ", V: " + new String(e.getValue())); - }*/ - return null; - } + /*for(Map.Entry e : tr.getRange("vcount".getBytes(), "zz".getBytes())) { + System.out.println("K: " + new String(e.getKey()) + ", V: " + new String(e.getValue())); + }*/ + return null; }); } catch (Throwable e) { e.printStackTrace(); @@ -73,4 +67,6 @@ public class TupleTest { System.exit(0); } + + private TupleTest() {} } diff --git a/bindings/java/src-completable/test/com/apple/foundationdb/test/VersionstampSmokeTest.java b/bindings/java/src-completable/test/com/apple/foundationdb/test/VersionstampSmokeTest.java index 4cceb98789..32db34e304 100644 --- a/bindings/java/src-completable/test/com/apple/foundationdb/test/VersionstampSmokeTest.java +++ b/bindings/java/src-completable/test/com/apple/foundationdb/test/VersionstampSmokeTest.java @@ -20,6 +20,8 @@ package com.apple.foundationdb.test; +import java.util.concurrent.CompletableFuture; + import com.apple.foundationdb.Database; import com.apple.foundationdb.FDB; import com.apple.foundationdb.MutationType; @@ -28,36 +30,36 @@ import com.apple.foundationdb.subspace.Subspace; import com.apple.foundationdb.tuple.Tuple; import com.apple.foundationdb.tuple.Versionstamp; -import java.util.concurrent.CompletableFuture; - public class VersionstampSmokeTest { public static void main(String[] args) { FDB fdb = FDB.selectAPIVersion(510); Database db = fdb.open(); db.run(tr -> { - tr.clear(Tuple.from("prefix").range()); - return null; + tr.clear(Tuple.from("prefix").range()); + return null; }); CompletableFuture trVersionFuture = db.run((Transaction tr) -> { - // The incomplete Versionstamp will have tr's version information when committed. - Tuple t = Tuple.from("prefix", Versionstamp.incomplete()); - tr.mutate(MutationType.SET_VERSIONSTAMPED_KEY, t.packWithVersionstamp(), new byte[0]); - return tr.getVersionstamp(); + // The incomplete Versionstamp will have tr's version information when committed. + Tuple t = Tuple.from("prefix", Versionstamp.incomplete()); + tr.mutate(MutationType.SET_VERSIONSTAMPED_KEY, t.packWithVersionstamp(), new byte[0]); + return tr.getVersionstamp(); }); byte[] trVersion = trVersionFuture.join(); Versionstamp v = db.run((Transaction tr) -> { - Subspace subspace = new Subspace(Tuple.from("prefix")); - byte[] serialized = tr.getRange(subspace.range(), 1).iterator().next().getKey(); - Tuple t = subspace.unpack(serialized); - return t.getVersionstamp(0); + Subspace subspace = new Subspace(Tuple.from("prefix")); + byte[] serialized = tr.getRange(subspace.range(), 1).iterator().next().getKey(); + Tuple t = subspace.unpack(serialized); + return t.getVersionstamp(0); }); System.out.println(v); System.out.println(Versionstamp.complete(trVersion)); assert v.equals(Versionstamp.complete(trVersion)); } + + private VersionstampSmokeTest() {} } diff --git a/bindings/java/src-completable/test/com/apple/foundationdb/test/WatchTest.java b/bindings/java/src-completable/test/com/apple/foundationdb/test/WatchTest.java index d646938386..27558bca72 100644 --- a/bindings/java/src-completable/test/com/apple/foundationdb/test/WatchTest.java +++ b/bindings/java/src-completable/test/com/apple/foundationdb/test/WatchTest.java @@ -75,20 +75,17 @@ public class WatchTest { a.incrementAndGet(); } }; - Runnable get = new Runnable() { - @Override - public void run() { - try { - System.err.println("`f' get()..."); - f.join(); - System.err.println("`f' changed"); - } catch(FDBException e) { - System.err.println("`f' watch error -> " + e.getMessage()); - if(e.getCode() != 1101) - throw e; - } finally { - a.incrementAndGet(); - } + Runnable get = () -> { + try { + System.err.println("`f' get()..."); + f.join(); + System.err.println("`f' changed"); + } catch(FDBException e12) { + System.err.println("`f' watch error -> " + e12.getMessage()); + if(e12.getCode() != 1101) + throw e12; + } finally { + a.incrementAndGet(); } }; if(r.nextBoolean()) { @@ -109,8 +106,10 @@ public class WatchTest { } //if(i % 1000 == 0) { - System.out.println("Done with " + i); + System.out.println("Done with " + i); //} } } + + private WatchTest() {} } diff --git a/bindings/java/src-completable/test/com/apple/foundationdb/test/WhileTrueTest.java b/bindings/java/src-completable/test/com/apple/foundationdb/test/WhileTrueTest.java index 28ae6b06e7..3cfb189bf2 100644 --- a/bindings/java/src-completable/test/com/apple/foundationdb/test/WhileTrueTest.java +++ b/bindings/java/src-completable/test/com/apple/foundationdb/test/WhileTrueTest.java @@ -20,10 +20,11 @@ package com.apple.foundationdb.test; -import com.apple.foundationdb.async.AsyncUtil; import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicInteger; +import com.apple.foundationdb.async.AsyncUtil; + public class WhileTrueTest { public static void main(String[] args) { // This should cause memory issues using the old implementation but not the new one. @@ -32,4 +33,6 @@ public class WhileTrueTest { AsyncUtil.whileTrue(() -> CompletableFuture.completedFuture(count.decrementAndGet()).thenApplyAsync(c -> c > 0)).join(); System.out.println("Final value: " + count.get()); } + + private WhileTrueTest() {} } diff --git a/bindings/java/suppressions.xml b/bindings/java/suppressions.xml new file mode 100644 index 0000000000..6d21d7353b --- /dev/null +++ b/bindings/java/suppressions.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + From 9934b2e09a4571171edc832bdf1b64b9aad4d88d Mon Sep 17 00:00:00 2001 From: Alec Grieser Date: Thu, 14 Dec 2017 09:57:24 -0800 Subject: [PATCH 03/10] =?UTF-8?q?believe=20it=20or=20not,=20for=20once,=20?= =?UTF-8?q?it's=20a=20whitespace=20only=20change,=20spaces=20->=20tabs=20?= =?UTF-8?q?=F0=9F=A4=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/com/apple/foundationdb/FDB.java | 58 +++++++++---------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/FDB.java b/bindings/java/src-completable/main/com/apple/foundationdb/FDB.java index 4344d9ba44..d56b5eae79 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/FDB.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/FDB.java @@ -337,37 +337,37 @@ public class FDB { netStarted = true; e.execute(() -> { - boolean acquired = false; - try { - while(!acquired) { - try { - // make attempt to avoid a needless deadlock - synchronized (FDB.this) { - if(netStopped) { - return; - } - } + boolean acquired = false; + try { + while(!acquired) { + try { + // make attempt to avoid a needless deadlock + synchronized (FDB.this) { + if(netStopped) { + return; + } + } - netRunning.acquire(); - acquired = true; - } catch(InterruptedException err) { - // Swallow thread interruption + netRunning.acquire(); + acquired = true; + } catch(InterruptedException err) { + // Swallow thread interruption } - } - try { - Network_run(); - } catch (Throwable t) { - System.err.println("Unhandled error in FoundationDB network thread: " + t.getMessage()); - // eat this error. we have nowhere to send it. - } - } finally { - if(acquired) { - netRunning.release(); - } - synchronized (FDB.this) { - netStopped = true; - } - } + } + try { + Network_run(); + } catch (Throwable t) { + System.err.println("Unhandled error in FoundationDB network thread: " + t.getMessage()); + // eat this error. we have nowhere to send it. + } + } finally { + if(acquired) { + netRunning.release(); + } + synchronized (FDB.this) { + netStopped = true; + } + } }); } From 9b1bcea525527b642caae19b5c1bc42cd528e5c9 Mon Sep 17 00:00:00 2001 From: Alec Grieser Date: Thu, 14 Dec 2017 10:10:11 -0800 Subject: [PATCH 04/10] added javadocs for DONE, READY_TRUE, and READY_FALSE ; used it in some places instead of CompletableFuture.completedFuture --- .../com/apple/foundationdb/LocalityUtil.java | 2 +- .../apple/foundationdb/async/AsyncUtil.java | 20 +++++++++++++++++-- .../directory/DirectoryLayer.java | 4 ++-- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/LocalityUtil.java b/bindings/java/src-completable/main/com/apple/foundationdb/LocalityUtil.java index 9e4ae395bc..9a2797f1c5 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/LocalityUtil.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/LocalityUtil.java @@ -156,7 +156,7 @@ public class LocalityUtil { CompletableFuture restartGet() { if(ByteArrayUtil.compareUnsigned(begin, end) >= 0) { - return CompletableFuture.completedFuture(false); + return AsyncUtil.READY_FALSE; } lastBegin = begin; tr.options().setReadSystemKeys(); diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/async/AsyncUtil.java b/bindings/java/src-completable/main/com/apple/foundationdb/async/AsyncUtil.java index 5a45f614a3..2d5337439b 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/async/AsyncUtil.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/async/AsyncUtil.java @@ -37,9 +37,25 @@ import java.util.function.Supplier; * Provided utilities for using and manipulating {@link CompletableFuture}s. */ public class AsyncUtil { + /** + * A completed future of type {@link Void}. In particular, it is completed to {@code null}, + * but that shouldn't really matter for the {@link Void} type. This can be used instead + * of creating a new future if one wants to signal that some asynchronous task has + * already been completed. + */ public static final CompletableFuture DONE = CompletableFuture.completedFuture(null); - public static final CompletableFuture READY_TRUE = CompletableFuture.completedFuture(true); - public static final CompletableFuture READY_FALSE = CompletableFuture.completedFuture(false); + /** + * A completed future of type {@link Boolean} that is set to {@code true}. This can be + * used instead of creating a new future if one wants to signal that some task has + * already been completed with a {@code true} result. + */ + public static final CompletableFuture READY_TRUE = CompletableFuture.completedFuture(Boolean.TRUE); + /** + * A completed future of type {@link Boolean} that is set to {@code false}. This can be + * used instead of creating a new future if one wants to signal that some task has + * already been completed with a {@code false} result. + */ + public static final CompletableFuture READY_FALSE = CompletableFuture.completedFuture(Boolean.FALSE); /** * Run {@code Function} {@code func}, returning all caught exceptions as a diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/directory/DirectoryLayer.java b/bindings/java/src-completable/main/com/apple/foundationdb/directory/DirectoryLayer.java index 1d7aeba10d..e48a8349e3 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/directory/DirectoryLayer.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/directory/DirectoryLayer.java @@ -907,14 +907,14 @@ public class DirectoryLayer implements Directory { return AsyncUtil.whileTrue(() -> { if(index == path.size()) - return CompletableFuture.completedFuture(false); + return AsyncUtil.READY_FALSE; return tr.get(node.subspace.get(SUB_DIR_KEY).get(path.get(index)).getKey()).thenComposeAsync(key -> { currentPath.add(path.get(index)); node = new Node(nodeWithPrefix(key), currentPath, path); if(!node.exists()) - return CompletableFuture.completedFuture(false); + return AsyncUtil.READY_FALSE; return node.loadMetadata(tr).thenApply(ignore -> { ++index; From 616e27e476db23c9b8f5dc3218ff11f6dabd8c29 Mon Sep 17 00:00:00 2001 From: Alec Grieser Date: Thu, 14 Dec 2017 11:07:19 -0800 Subject: [PATCH 05/10] added redundant modifier check to style and then fixed errors it turned up --- bindings/java/fdb-java-style.xml | 4 +--- .../main/com/apple/foundationdb/FDB.java | 2 +- .../main/com/apple/foundationdb/LocalityUtil.java | 2 +- .../com/apple/foundationdb/NativeObjectWrapper.java | 2 +- .../main/com/apple/foundationdb/OptionsSet.java | 2 +- .../main/com/apple/foundationdb/async/Cancellable.java | 2 +- .../apple/foundationdb/async/CloneableException.java | 2 +- .../apple/foundationdb/directory/DirectoryLayer.java | 10 +++++----- .../foundationdb/test/AsyncDirectoryExtension.java | 2 +- .../apple/foundationdb/test/DirectoryExtension.java | 2 +- .../test/com/apple/foundationdb/test/Instruction.java | 2 +- .../test/com/apple/foundationdb/test/StackEntry.java | 2 +- 12 files changed, 16 insertions(+), 18 deletions(-) diff --git a/bindings/java/fdb-java-style.xml b/bindings/java/fdb-java-style.xml index 15cacc6fe2..62d6232eed 100644 --- a/bindings/java/fdb-java-style.xml +++ b/bindings/java/fdb-java-style.xml @@ -1,3 +1,4 @@ + - @@ -88,9 +88,7 @@ - diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/FDB.java b/bindings/java/src-completable/main/com/apple/foundationdb/FDB.java index d56b5eae79..d3f1ce6ad3 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/FDB.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/FDB.java @@ -64,7 +64,7 @@ public class FDB { static class DaemonThreadFactory implements ThreadFactory { private final ThreadFactory factory; - public DaemonThreadFactory(ThreadFactory factory) { + DaemonThreadFactory(ThreadFactory factory) { this.factory = factory; } diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/LocalityUtil.java b/bindings/java/src-completable/main/com/apple/foundationdb/LocalityUtil.java index 9a2797f1c5..1e31faadec 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/LocalityUtil.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/LocalityUtil.java @@ -82,7 +82,7 @@ public class LocalityUtil { * @return an sequence of keys denoting the start of single-server ranges */ public static CloseableAsyncIterator getBoundaryKeys(Transaction tr, byte[] begin, byte[] end) { - Transaction local = tr.getDatabase().createTransaction(); + Transaction local = tr.getDatabase().createTransaction(tr.getExecutor()); CompletableFuture readVersion = tr.getReadVersion(); if(readVersion.isDone() && !readVersion.isCompletedExceptionally()) { local.setReadVersion(readVersion.getNow(null)); diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/NativeObjectWrapper.java b/bindings/java/src-completable/main/com/apple/foundationdb/NativeObjectWrapper.java index 9366d37c0a..65d073f856 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/NativeObjectWrapper.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/NativeObjectWrapper.java @@ -30,7 +30,7 @@ abstract class NativeObjectWrapper implements AutoCloseable { private boolean closed = false; private long cPtr; - public NativeObjectWrapper(long cPtr) { + NativeObjectWrapper(long cPtr) { this.cPtr = cPtr; if(this.cPtr == 0) this.closed = true; diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/OptionsSet.java b/bindings/java/src-completable/main/com/apple/foundationdb/OptionsSet.java index 638a64e1c8..1bc48f548f 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/OptionsSet.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/OptionsSet.java @@ -28,7 +28,7 @@ abstract class OptionsSet { private static final Charset CHARSET_UTF8 = Charset.forName("UTF-8"); OptionConsumer consumer; - public OptionsSet(OptionConsumer provider) { + OptionsSet(OptionConsumer provider) { this.consumer = provider; } diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/async/Cancellable.java b/bindings/java/src-completable/main/com/apple/foundationdb/async/Cancellable.java index 70c734cc86..778eee04ff 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/async/Cancellable.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/async/Cancellable.java @@ -33,5 +33,5 @@ public interface Cancellable { * is not an error to call this method on an operation that has already completed or * already been cancelled. This method will not block or throw non-fatal exceptions. */ - public abstract void cancel(); + void cancel(); } diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/async/CloneableException.java b/bindings/java/src-completable/main/com/apple/foundationdb/async/CloneableException.java index dd93a56c0e..5a4f86060b 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/async/CloneableException.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/async/CloneableException.java @@ -30,5 +30,5 @@ public interface CloneableException { * * @return a newly created {@code Exception}. */ - public Exception retargetClone(); + Exception retargetClone(); } diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/directory/DirectoryLayer.java b/bindings/java/src-completable/main/com/apple/foundationdb/directory/DirectoryLayer.java index e48a8349e3..523a63eaf8 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/directory/DirectoryLayer.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/directory/DirectoryLayer.java @@ -896,7 +896,7 @@ public class DirectoryLayer implements Directory { private Node node; private List currentPath; - public NodeFinder(List path) { + NodeFinder(List path) { this.path = path; } @@ -929,7 +929,7 @@ public class DirectoryLayer implements Directory { private static class NodeMetadataLoader implements Function> { private final ReadTransaction tr; - public NodeMetadataLoader(ReadTransaction tr) { + NodeMetadataLoader(ReadTransaction tr) { this.tr = tr; } @@ -947,7 +947,7 @@ public class DirectoryLayer implements Directory { private boolean loadedMetadata; - public Node(Subspace subspace, List path, List targetPath) { + Node(Subspace subspace, List path, List targetPath) { this.subspace = subspace; this.path = path; this.targetPath = targetPath; @@ -1004,7 +1004,7 @@ public class DirectoryLayer implements Directory { private long candidate; private boolean restart; - public PrefixFinder() { + PrefixFinder() { this.random = new Random(); this.windowStart = 0; } @@ -1126,7 +1126,7 @@ public class DirectoryLayer implements Directory { public final Subspace counters; public final Subspace recent; - public HighContentionAllocator(Subspace subspace) { + HighContentionAllocator(Subspace subspace) { this.counters = subspace.get(0); this.recent = subspace.get(1); } diff --git a/bindings/java/src-completable/test/com/apple/foundationdb/test/AsyncDirectoryExtension.java b/bindings/java/src-completable/test/com/apple/foundationdb/test/AsyncDirectoryExtension.java index 8c34cc35ef..d1b83b2301 100644 --- a/bindings/java/src-completable/test/com/apple/foundationdb/test/AsyncDirectoryExtension.java +++ b/bindings/java/src-completable/test/com/apple/foundationdb/test/AsyncDirectoryExtension.java @@ -39,7 +39,7 @@ class AsyncDirectoryExtension { int dirIndex = 0; int errorIndex = 0; - public AsyncDirectoryExtension() { + AsyncDirectoryExtension() { dirList.add(DirectoryLayer.getDefault()); } diff --git a/bindings/java/src-completable/test/com/apple/foundationdb/test/DirectoryExtension.java b/bindings/java/src-completable/test/com/apple/foundationdb/test/DirectoryExtension.java index ae85296fd2..f28253f415 100644 --- a/bindings/java/src-completable/test/com/apple/foundationdb/test/DirectoryExtension.java +++ b/bindings/java/src-completable/test/com/apple/foundationdb/test/DirectoryExtension.java @@ -38,7 +38,7 @@ class DirectoryExtension { int dirIndex = 0; int errorIndex = 0; - public DirectoryExtension() { + DirectoryExtension() { dirList.add(DirectoryLayer.getDefault()); } diff --git a/bindings/java/src-completable/test/com/apple/foundationdb/test/Instruction.java b/bindings/java/src-completable/test/com/apple/foundationdb/test/Instruction.java index a16bda49e9..50dc9c317a 100644 --- a/bindings/java/src-completable/test/com/apple/foundationdb/test/Instruction.java +++ b/bindings/java/src-completable/test/com/apple/foundationdb/test/Instruction.java @@ -44,7 +44,7 @@ class Instruction extends Stack { final TransactionContext tcx; final ReadTransactionContext readTcx; - public Instruction(Context context, Tuple tokens) { + Instruction(Context context, Tuple tokens) { this.context = context; this.tokens = tokens; diff --git a/bindings/java/src-completable/test/com/apple/foundationdb/test/StackEntry.java b/bindings/java/src-completable/test/com/apple/foundationdb/test/StackEntry.java index a9f1f11cef..e854ab862f 100644 --- a/bindings/java/src-completable/test/com/apple/foundationdb/test/StackEntry.java +++ b/bindings/java/src-completable/test/com/apple/foundationdb/test/StackEntry.java @@ -23,7 +23,7 @@ package com.apple.foundationdb.test; class StackEntry { int idx; Object value; - public StackEntry(int idx, Object value) { + StackEntry(int idx, Object value) { this.idx = idx; this.value = value; } From 87b769f446284d314c76bbc5e8e80eadbb580e28 Mon Sep 17 00:00:00 2001 From: Alec Grieser Date: Thu, 14 Dec 2017 11:33:17 -0800 Subject: [PATCH 06/10] rename methods on iterators to include "remaining" ; removed unused version of mapIterable --- .../apple/foundationdb/async/AsyncUtil.java | 34 ++++++++----------- .../foundationdb/test/LocalityTests.java | 2 +- .../apple/foundationdb/test/StackTester.java | 2 +- 3 files changed, 17 insertions(+), 21 deletions(-) diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/async/AsyncUtil.java b/bindings/java/src-completable/main/com/apple/foundationdb/async/AsyncUtil.java index 2d5337439b..cf279d2eab 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/async/AsyncUtil.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/async/AsyncUtil.java @@ -91,7 +91,7 @@ public class AsyncUtil { * @return a future that is ready once the asynchronous operation completes */ public static CompletableFuture forEach(final AsyncIterable iterable, final Consumer consumer) { - return forEach(iterable.iterator(), consumer); + return forEachRemaining(iterable.iterator(), consumer); } /** @@ -110,11 +110,11 @@ public class AsyncUtil { * @return a future that is ready once the asynchronous operation completes */ public static CompletableFuture forEach(final AsyncIterable iterable, final Consumer consumer, final Executor executor) { - return forEach(iterable.iterator(), consumer, executor); + return forEachRemaining(iterable.iterator(), consumer, executor); } /** - * Run the {@code consumer} on each element of the iterator in order. The future will + * Run the {@code consumer} on each element remaining in the iterator in order. The future will * complete with either the first error encountered by either the iterator itself * or by the consumer provided or with {@code null} if the future completes * successfully. Items are processed in order from the iterator, and each item @@ -126,12 +126,12 @@ public class AsyncUtil { * * @return a future that is ready once the asynchronous operation completes */ - public static CompletableFuture forEach(final AsyncIterator iterator, final Consumer consumer) { - return forEach(iterator, consumer, DEFAULT_EXECUTOR); + public static CompletableFuture forEachRemaining(final AsyncIterator iterator, final Consumer consumer) { + return forEachRemaining(iterator, consumer, DEFAULT_EXECUTOR); } /** - * Run the {@code consumer} on each element of the iterator in order. The future will + * Run the {@code consumer} on each element remaining if the iterator in order. The future will * complete with either the first error encountered by either the iterator itself * or by the consumer provided or with {@code null} if the future completes * successfully. Items are processed in order from the iterator, and each item @@ -145,7 +145,7 @@ public class AsyncUtil { * * @return a future that is ready once the asynchronous operation completes */ - public static CompletableFuture forEach(final AsyncIterator iterator, final Consumer consumer, final Executor executor) { + public static CompletableFuture forEachRemaining(final AsyncIterator iterator, final Consumer consumer, final Executor executor) { return iterator.onHasNext().thenComposeAsync(hasAny -> { if (hasAny) { return whileTrue(() -> { @@ -171,15 +171,15 @@ public class AsyncUtil { } /** - * Iterates over a set of items and returns the result as a list. + * Iterates over a set of items and returns the remaining results as a list. * * @param iterator the source of data over which to iterate. This function will exhaust the iterator. * * @return a {@code CompletableFuture} which will be set to the amalgamation of results * from iteration. */ - public static CompletableFuture> collect(final AsyncIterator iterator) { - return collect(iterator, DEFAULT_EXECUTOR); + public static CompletableFuture> collectRemaining(final AsyncIterator iterator) { + return collectRemaining(iterator, DEFAULT_EXECUTOR); } /** @@ -192,11 +192,11 @@ public class AsyncUtil { * from iteration. */ public static CompletableFuture> collect(final AsyncIterable iterable, final Executor executor) { - return collect(iterable.iterator(), executor); + return collectRemaining(iterable.iterator(), executor); } /** - * Iterates over a set of items and returns the result as a list. + * Iterates over a set of items and returns the remaining results as a list. * * @param iterator the source of data over which to iterate. This function will exhaust the iterator. * @param executor the {@link Executor} to use for asynchronous operations @@ -204,13 +204,9 @@ public class AsyncUtil { * @return a {@code CompletableFuture} which will be set to the amalgamation of results * from iteration. */ - public static CompletableFuture> collect(final AsyncIterator iterator, final Executor executor) { + public static CompletableFuture> collectRemaining(final AsyncIterator iterator, final Executor executor) { final List accumulator = new LinkedList<>(); - return forEach(iterator, accumulator::add, executor).thenApply(ignore -> accumulator); - } - - public static AsyncIterable mapIterable(final AsyncIterable iterable, final Function func) { - return mapIterable(iterable, func, DEFAULT_EXECUTOR); + return tag(forEachRemaining(iterator, accumulator::add, executor), accumulator); } /** @@ -222,7 +218,7 @@ public class AsyncUtil { * @return a new iterable with each element mapped to a different value */ public static AsyncIterable mapIterable(final AsyncIterable iterable, - final Function func, final Executor executor) { + final Function func) { return new AsyncIterable() { @Override public AsyncIterator iterator() { diff --git a/bindings/java/src-completable/test/com/apple/foundationdb/test/LocalityTests.java b/bindings/java/src-completable/test/com/apple/foundationdb/test/LocalityTests.java index fd9940fb74..69b286ba68 100644 --- a/bindings/java/src-completable/test/com/apple/foundationdb/test/LocalityTests.java +++ b/bindings/java/src-completable/test/com/apple/foundationdb/test/LocalityTests.java @@ -46,7 +46,7 @@ public class LocalityTests { long start = System.currentTimeMillis(); CloseableAsyncIterator keys = LocalityUtil.getBoundaryKeys(database, new byte[0], new byte[] { (byte)255 }); - CompletableFuture> collection = AsyncUtil.collect(keys); + CompletableFuture> collection = AsyncUtil.collectRemaining(keys); List list = collection.join(); System.out.println("Took " + (System.currentTimeMillis() - start) + "ms to get " + list.size() + " items"); diff --git a/bindings/java/src-completable/test/com/apple/foundationdb/test/StackTester.java b/bindings/java/src-completable/test/com/apple/foundationdb/test/StackTester.java index 76bc437448..d6b6b0c66e 100644 --- a/bindings/java/src-completable/test/com/apple/foundationdb/test/StackTester.java +++ b/bindings/java/src-completable/test/com/apple/foundationdb/test/StackTester.java @@ -661,7 +661,7 @@ public class StackTester { CloseableAsyncIterator boundaryKeys = LocalityUtil.getBoundaryKeys( tr, new byte[0], new byte[]{(byte) 255, (byte) 255}); try { - List keys = AsyncUtil.collect(boundaryKeys).join(); + List keys = AsyncUtil.collectRemaining(boundaryKeys).join(); for(int i = 0; i < keys.size() - 1; i++) { byte[] start = keys.get(i); byte[] end = tr.getKey(KeySelector.lastLessThan(keys.get(i + 1))).join(); From 311bb89258a8b024a5a73fa2a75c1369ccb3c864 Mon Sep 17 00:00:00 2001 From: Alec Grieser Date: Thu, 14 Dec 2017 11:35:11 -0800 Subject: [PATCH 07/10] =?UTF-8?q?for=20some=20reason,=20my=20IDE=20wants?= =?UTF-8?q?=20to=20insert=20spaces=20after=20a=20tab=20instead=20of=20a=20?= =?UTF-8?q?tab=20and=20I=20don't=20like=20it=20=F0=9F=A4=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/com/apple/foundationdb/async/AsyncUtil.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/async/AsyncUtil.java b/bindings/java/src-completable/main/com/apple/foundationdb/async/AsyncUtil.java index cf279d2eab..9f5b32ff91 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/async/AsyncUtil.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/async/AsyncUtil.java @@ -227,7 +227,7 @@ public class AsyncUtil { @Override public CompletableFuture> asList() { - final List accumulator = new LinkedList<>(); + final List accumulator = new LinkedList<>(); return tag(AsyncUtil.forEach(iterable, value -> accumulator.add(func.apply(value))), accumulator); } }; @@ -441,7 +441,7 @@ public class AsyncUtil { * @return a new {@link CompletableFuture} that is set when {@code task} is ready. */ public static CompletableFuture whenReady(CompletableFuture task) { - return task.handle((v, t) -> null); + return task.handle((v, t) -> null); } public static CompletableFuture composeExceptionally(CompletableFuture task, Function> fn) { @@ -471,7 +471,7 @@ public class AsyncUtil { * @return future with same completion properties as the future returned by the handler */ public static CompletableFuture composeHandle(CompletableFuture future, BiFunction> handler) { - return future.handle(handler).thenCompose(Function.identity()); + return future.handle(handler).thenCompose(Function.identity()); } /** @@ -492,7 +492,7 @@ public class AsyncUtil { * @return future with same completion properties as the future returned by the handler */ public static CompletableFuture composeHandleAsync(CompletableFuture future, BiFunction> handler) { - return composeHandleAsync(future, handler, DEFAULT_EXECUTOR); + return composeHandleAsync(future, handler, DEFAULT_EXECUTOR); } /** From c7a730006c3e73802093f6ebcaae26a762622867 Mon Sep 17 00:00:00 2001 From: Alec Grieser Date: Thu, 14 Dec 2017 11:45:08 -0800 Subject: [PATCH 08/10] I have had it with these monkey-fighting whitespaces changes in this Monday-to-Friday repo --- .../directory/DirectoryLayer.java | 340 +++++++++--------- 1 file changed, 170 insertions(+), 170 deletions(-) diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/directory/DirectoryLayer.java b/bindings/java/src-completable/main/com/apple/foundationdb/directory/DirectoryLayer.java index 523a63eaf8..0e0c613513 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/directory/DirectoryLayer.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/directory/DirectoryLayer.java @@ -242,7 +242,7 @@ public class DirectoryLayer implements Directory { */ @Override public int hashCode() { - return path.hashCode() ^ (nodeSubspace.hashCode() * 179) ^ (contentSubspace.hashCode() * 937); + return path.hashCode() ^ (nodeSubspace.hashCode() * 179) ^ (contentSubspace.hashCode() * 937); } /** @@ -327,7 +327,7 @@ public class DirectoryLayer implements Directory { */ @Override public CompletableFuture open(ReadTransactionContext tcx, final List path, final byte[] layer) { - return tcx.readAsync(rtr -> createOrOpenInternal(rtr, null, path, layer, null, false, true)); + return tcx.readAsync(rtr -> createOrOpenInternal(rtr, null, path, layer, null, false, true)); } /** @@ -349,7 +349,7 @@ public class DirectoryLayer implements Directory { */ @Override public CompletableFuture create(TransactionContext tcx, final List path, final byte[] layer, final byte[] prefix) { - return tcx.runAsync(tr -> createOrOpenInternal(tr, tr, path, layer, prefix, true, false)); + return tcx.runAsync(tr -> createOrOpenInternal(tr, tr, path, layer, prefix, true, false)); } /** @@ -512,25 +512,25 @@ public class DirectoryLayer implements Directory { final List pathCopy = new ArrayList(path); return tcx.readAsync(tr -> checkVersion(tr) - .thenComposeAsync(ignore -> - new NodeFinder(pathCopy).find(tr).thenComposeAsync(new NodeMetadataLoader(tr), tr.getExecutor()), - tr.getExecutor()) - .thenComposeAsync(node -> { - if(!node.exists()) - throw new NoSuchDirectoryException(toAbsolutePath(pathCopy)); + .thenComposeAsync(ignore -> + new NodeFinder(pathCopy).find(tr).thenComposeAsync(new NodeMetadataLoader(tr), tr.getExecutor()), + tr.getExecutor()) + .thenComposeAsync(node -> { + if(!node.exists()) + throw new NoSuchDirectoryException(toAbsolutePath(pathCopy)); - if(node.isInPartition(true)) - return node.getContents().list(tr, node.getPartitionSubpath()); + if(node.isInPartition(true)) + return node.getContents().list(tr, node.getPartitionSubpath()); - final Subspace subdir = node.subspace.get(SUB_DIR_KEY); + final Subspace subdir = node.subspace.get(SUB_DIR_KEY); - return AsyncUtil.collect( - AsyncUtil.mapIterable(tr.getRange(subdir.range()), + return AsyncUtil.collect( + AsyncUtil.mapIterable(tr.getRange(subdir.range()), kv -> subdir.unpack(kv.getKey()).getString(0), tr.getExecutor() - ) - ); - }, tr.getExecutor()) + ) + ); + }, tr.getExecutor()) ); } @@ -558,17 +558,17 @@ public class DirectoryLayer implements Directory { final List pathCopy = new ArrayList<>(path); return tcx.readAsync(tr -> checkVersion(tr) - .thenComposeAsync(ignore -> - new NodeFinder(pathCopy).find(tr).thenComposeAsync(new NodeMetadataLoader(tr), tr.getExecutor()), - tr.getExecutor()) - .thenComposeAsync(node -> { - if(!node.exists()) - return AsyncUtil.READY_FALSE; - else if(node.isInPartition(false)) - return node.getContents().exists(tr, node.getPartitionSubpath()); + .thenComposeAsync(ignore -> + new NodeFinder(pathCopy).find(tr).thenComposeAsync(new NodeMetadataLoader(tr), tr.getExecutor()), + tr.getExecutor()) + .thenComposeAsync(node -> { + if(!node.exists()) + return AsyncUtil.READY_FALSE; + else if(node.isInPartition(false)) + return node.getContents().exists(tr, node.getPartitionSubpath()); - return AsyncUtil.READY_TRUE; - }, tr.getExecutor())); + return AsyncUtil.READY_TRUE; + }, tr.getExecutor())); } // @@ -593,15 +593,15 @@ public class DirectoryLayer implements Directory { return tr.getRange(nodeSubspace.range().begin, ByteArrayUtil.join(nodeSubspace.pack(key), new byte[]{0x00}), 1, true) .asList() .thenApply(results -> { - if(results.size() > 0) { - byte[] resultKey = results.get(0).getKey(); - byte[] prevPrefix = nodeSubspace.unpack(resultKey).getBytes(0); - if(ByteArrayUtil.startsWith(key, prevPrefix)) { - return nodeWithPrefix(prevPrefix); - } - } + if(results.size() > 0) { + byte[] resultKey = results.get(0).getKey(); + byte[] prevPrefix = nodeSubspace.unpack(resultKey).getBytes(0); + if(ByteArrayUtil.startsWith(key, prevPrefix)) { + return nodeWithPrefix(prevPrefix); + } + } - return null; + return null; }); } @@ -659,13 +659,13 @@ public class DirectoryLayer implements Directory { tr.clear(node.range()); return AsyncUtil.whileTrue(() -> { - CompletableFuture subdirRemoveFuture; - if(rangeItr.onHasNext().isDone() && rangeItr.hasNext()) - subdirRemoveFuture = removeRecursive(tr, nodeWithPrefix(rangeItr.next().getValue())); - else - subdirRemoveFuture = AsyncUtil.DONE; + CompletableFuture subdirRemoveFuture; + if(rangeItr.onHasNext().isDone() && rangeItr.hasNext()) + subdirRemoveFuture = removeRecursive(tr, nodeWithPrefix(rangeItr.next().getValue())); + else + subdirRemoveFuture = AsyncUtil.DONE; - return subdirRemoveFuture.thenCompose(ignore -> rangeItr.onHasNext()); + return subdirRemoveFuture.thenCompose(ignore -> rangeItr.onHasNext()); }, tr.getExecutor()); } @@ -674,14 +674,14 @@ public class DirectoryLayer implements Directory { // allocated prefix (including the root node). This means that it neither // contains any other prefix nor is contained by any other prefix. if(prefix == null || prefix.length == 0) - return AsyncUtil.READY_FALSE; + return AsyncUtil.READY_FALSE; return nodeContainingKey(tr, prefix).thenComposeAsync(node -> { - if(node != null) - return AsyncUtil.READY_FALSE; + if(node != null) + return AsyncUtil.READY_FALSE; - final AsyncIterator it = tr.getRange(nodeSubspace.pack(prefix), nodeSubspace.pack(ByteArrayUtil.strinc(prefix)), 1).iterator(); - return it.onHasNext().thenApply(hasNext -> !hasNext); + final AsyncIterator it = tr.getRange(nodeSubspace.pack(prefix), nodeSubspace.pack(ByteArrayUtil.strinc(prefix)), 1).iterator(); + return it.onHasNext().thenApply(hasNext -> !hasNext); }, tr.getExecutor()); } @@ -769,46 +769,46 @@ public class DirectoryLayer implements Directory { } return checkOrWriteVersion(tr).thenComposeAsync(ignore -> { - if(prefix == null) { - return allocator.allocate(tr).thenComposeAsync(allocated -> { - final byte[] finalPrefix = ByteArrayUtil.join(contentSubspace.getKey(), allocated); - return tr.getRange(Range.startsWith(finalPrefix), 1).iterator().onHasNext().thenApply(hasAny -> { - if(hasAny) { - throw new IllegalStateException("The database has keys stored at the prefix chosen by the automatic " + - "prefix allocator: " + ByteArrayUtil.printable(finalPrefix) + "."); - } - return finalPrefix; - }); - }, tr.getExecutor()); - } - else - return CompletableFuture.completedFuture(prefix); + if(prefix == null) { + return allocator.allocate(tr).thenComposeAsync(allocated -> { + final byte[] finalPrefix = ByteArrayUtil.join(contentSubspace.getKey(), allocated); + return tr.getRange(Range.startsWith(finalPrefix), 1).iterator().onHasNext().thenApply(hasAny -> { + if(hasAny) { + throw new IllegalStateException("The database has keys stored at the prefix chosen by the automatic " + + "prefix allocator: " + ByteArrayUtil.printable(finalPrefix) + "."); + } + return finalPrefix; + }); + }, tr.getExecutor()); + } + else + return CompletableFuture.completedFuture(prefix); }, tr.getExecutor()) .thenComposeAsync(actualPrefix -> isPrefixFree(prefix == null ? tr.snapshot() : tr, actualPrefix) - .thenComposeAsync(prefixFree -> { - if(!prefixFree) { - if(prefix == null) { - throw new IllegalStateException("The directory layer has manually allocated prefixes that conflict " + - "with the automatic prefix allocator."); - } - else - throw new IllegalArgumentException("Prefix already in use: " + ByteArrayUtil.printable(actualPrefix) + "."); - } - else if(path.size() > 1) { - return createOrOpen(tr, PathUtil.popBack(path)).thenApply(dir -> nodeWithPrefix(dir.getKey())); - } - else - return CompletableFuture.completedFuture(rootNode); - }, tr.getExecutor()) - .thenApplyAsync(parentNode -> { - if(parentNode == null) - throw new IllegalStateException("The parent directory does not exist."); //Shouldn't happen - Subspace node = nodeWithPrefix(actualPrefix); - tr.set(parentNode.get(SUB_DIR_KEY).get(getLast(path)).getKey(), actualPrefix); - tr.set(node.get(LAYER_KEY).getKey(), layer); - return contentsOfNode(node, path, layer); - }, tr.getExecutor()), - tr.getExecutor()); + .thenComposeAsync(prefixFree -> { + if(!prefixFree) { + if(prefix == null) { + throw new IllegalStateException("The directory layer has manually allocated prefixes that conflict " + + "with the automatic prefix allocator."); + } + else + throw new IllegalArgumentException("Prefix already in use: " + ByteArrayUtil.printable(actualPrefix) + "."); + } + else if(path.size() > 1) { + return createOrOpen(tr, PathUtil.popBack(path)).thenApply(dir -> nodeWithPrefix(dir.getKey())); + } + else + return CompletableFuture.completedFuture(rootNode); + }, tr.getExecutor()) + .thenApplyAsync(parentNode -> { + if(parentNode == null) + throw new IllegalStateException("The parent directory does not exist."); //Shouldn't happen + Subspace node = nodeWithPrefix(actualPrefix); + tr.set(parentNode.get(SUB_DIR_KEY).get(getLast(path)).getKey(), actualPrefix); + tr.set(node.get(LAYER_KEY).getKey(), layer); + return contentsOfNode(node, path, layer); + }, tr.getExecutor()), + tr.getExecutor()); } // @@ -906,23 +906,23 @@ public class DirectoryLayer implements Directory { currentPath = new ArrayList<>(); return AsyncUtil.whileTrue(() -> { - if(index == path.size()) - return AsyncUtil.READY_FALSE; + if(index == path.size()) + return AsyncUtil.READY_FALSE; - return tr.get(node.subspace.get(SUB_DIR_KEY).get(path.get(index)).getKey()).thenComposeAsync(key -> { - currentPath.add(path.get(index)); - node = new Node(nodeWithPrefix(key), currentPath, path); + return tr.get(node.subspace.get(SUB_DIR_KEY).get(path.get(index)).getKey()).thenComposeAsync(key -> { + currentPath.add(path.get(index)); + node = new Node(nodeWithPrefix(key), currentPath, path); - if(!node.exists()) - return AsyncUtil.READY_FALSE; + if(!node.exists()) + return AsyncUtil.READY_FALSE; - return node.loadMetadata(tr).thenApply(ignore -> { - ++index; - return !Arrays.equals(node.layer, DirectoryLayer.PARTITION_LAYER); - }); - }, tr.getExecutor()); + return node.loadMetadata(tr).thenApply(ignore -> { + ++index; + return !Arrays.equals(node.layer, DirectoryLayer.PARTITION_LAYER); + }); + }, tr.getExecutor()); }, tr.getExecutor()) - .thenApply(ignore -> node); + .thenApply(ignore -> node); } } @@ -968,9 +968,9 @@ public class DirectoryLayer implements Directory { return tr.get(subspace.pack(new Tuple().add(LAYER_KEY))) .thenApply(value -> { - layer = value; - loadedMetadata = true; - return Node.this; + layer = value; + loadedMetadata = true; + return Node.this; }); } @@ -1011,99 +1011,99 @@ public class DirectoryLayer implements Directory { public CompletableFuture find(final Transaction tr, final HighContentionAllocator allocator) { return AsyncUtil.whileTrue(() -> { - final AsyncIterator rangeItr = tr.snapshot().getRange(allocator.counters.range(), 1, true).iterator(); - return rangeItr.onHasNext().thenApply(hasNext -> { - if(hasNext) { - KeyValue kv = rangeItr.next(); - windowStart = allocator.counters.unpack(kv.getKey()).getLong(0); - } + final AsyncIterator rangeItr = tr.snapshot().getRange(allocator.counters.range(), 1, true).iterator(); + return rangeItr.onHasNext().thenApply(hasNext -> { + if(hasNext) { + KeyValue kv = rangeItr.next(); + windowStart = allocator.counters.unpack(kv.getKey()).getLong(0); + } - return null; - }) - .thenComposeAsync(ignore -> chooseWindow(tr, allocator), tr.getExecutor()) - .thenComposeAsync(ignore -> choosePrefix(tr, allocator), tr.getExecutor()); + return null; + }) + .thenComposeAsync(ignore -> chooseWindow(tr, allocator), tr.getExecutor()) + .thenComposeAsync(ignore -> choosePrefix(tr, allocator), tr.getExecutor()); }, tr.getExecutor()) - .thenApply(ignore -> Tuple.from(candidate).pack()); + .thenApply(ignore -> Tuple.from(candidate).pack()); } public CompletableFuture chooseWindow(final Transaction tr, final HighContentionAllocator allocator) { final long initialWindowStart = windowStart; return AsyncUtil.whileTrue(() -> { - final byte[] counterKey = allocator.counters.get(windowStart).getKey(); + final byte[] counterKey = allocator.counters.get(windowStart).getKey(); - Range oldCounters = new Range(allocator.counters.getKey(), counterKey); - Range oldAllocations = new Range(allocator.recent.getKey(), allocator.recent.get(windowStart).getKey()); + Range oldCounters = new Range(allocator.counters.getKey(), counterKey); + Range oldAllocations = new Range(allocator.recent.getKey(), allocator.recent.get(windowStart).getKey()); - CompletableFuture newCountRead; - // SOMEDAY: synchronize on something transaction local - synchronized(HighContentionAllocator.class) { - if(windowStart > initialWindowStart) { - tr.clear(oldCounters); - tr.options().setNextWriteNoWriteConflictRange(); - tr.clear(oldAllocations); - } + CompletableFuture newCountRead; + // SOMEDAY: synchronize on something transaction local + synchronized(HighContentionAllocator.class) { + if(windowStart > initialWindowStart) { + tr.clear(oldCounters); + tr.options().setNextWriteNoWriteConflictRange(); + tr.clear(oldAllocations); + } - tr.mutate(MutationType.ADD, counterKey, LITTLE_ENDIAN_LONG_ONE); - newCountRead = tr.snapshot().get(counterKey); - } + tr.mutate(MutationType.ADD, counterKey, LITTLE_ENDIAN_LONG_ONE); + newCountRead = tr.snapshot().get(counterKey); + } - return newCountRead.thenApply(newCountBytes -> { - long newCount = newCountBytes == null ? 0 : unpackLittleEndian(newCountBytes); - windowSize = getWindowSize(windowStart); - if(newCount * 2 >= windowSize) { - windowStart += windowSize; - return true; - } + return newCountRead.thenApply(newCountBytes -> { + long newCount = newCountBytes == null ? 0 : unpackLittleEndian(newCountBytes); + windowSize = getWindowSize(windowStart); + if(newCount * 2 >= windowSize) { + windowStart += windowSize; + return true; + } - return false; // exit the loop - }); + return false; // exit the loop + }); }, tr.getExecutor()); } public CompletableFuture choosePrefix(final Transaction tr, final HighContentionAllocator allocator) { restart = false; return AsyncUtil.whileTrue(() -> { - // As of the snapshot being read from, the window is less than half - // full, so this should be expected to take 2 tries. Under high - // contention (and when the window advances), there is an additional - // subsequent risk of conflict for this transaction. - candidate = windowStart + random.nextInt(windowSize); - final byte[] allocationKey = allocator.recent.get(candidate).getKey(); - Range countersRange = allocator.counters.range(); + // As of the snapshot being read from, the window is less than half + // full, so this should be expected to take 2 tries. Under high + // contention (and when the window advances), there is an additional + // subsequent risk of conflict for this transaction. + candidate = windowStart + random.nextInt(windowSize); + final byte[] allocationKey = allocator.recent.get(candidate).getKey(); + Range countersRange = allocator.counters.range(); - AsyncIterable counterRange; - CompletableFuture allocationTemp; - // SOMEDAY: synchronize on something transaction local - synchronized(HighContentionAllocator.class) { - counterRange = tr.snapshot().getRange(countersRange, 1, true); - allocationTemp = tr.get(allocationKey); - tr.options().setNextWriteNoWriteConflictRange(); - tr.set(allocationKey, EMPTY_BYTES); - } + AsyncIterable counterRange; + CompletableFuture allocationTemp; + // SOMEDAY: synchronize on something transaction local + synchronized(HighContentionAllocator.class) { + counterRange = tr.snapshot().getRange(countersRange, 1, true); + allocationTemp = tr.get(allocationKey); + tr.options().setNextWriteNoWriteConflictRange(); + tr.set(allocationKey, EMPTY_BYTES); + } - final CompletableFuture> lastCounter = counterRange.asList(); - final CompletableFuture allocation = allocationTemp; + final CompletableFuture> lastCounter = counterRange.asList(); + final CompletableFuture allocation = allocationTemp; - return lastCounter.thenCombineAsync(allocation, (result, allocationValue) -> { - long currentWindowStart = 0; - if(!result.isEmpty()) { - currentWindowStart = allocator.counters.unpack(result.get(0).getKey()).getLong(0); - } + return lastCounter.thenCombineAsync(allocation, (result, allocationValue) -> { + long currentWindowStart = 0; + if(!result.isEmpty()) { + currentWindowStart = allocator.counters.unpack(result.get(0).getKey()).getLong(0); + } - if(currentWindowStart > windowStart) { - restart = true; - return false; // exit the loop and rerun the allocation from the beginning - } + if(currentWindowStart > windowStart) { + restart = true; + return false; // exit the loop and rerun the allocation from the beginning + } - if(allocationValue == null) { - tr.addWriteConflictKey(allocationKey); - return false; // exit the loop and return this candidate - } + if(allocationValue == null) { + tr.addWriteConflictKey(allocationKey); + return false; // exit the loop and return this candidate + } - return true; - }, tr.getExecutor()); + return true; + }, tr.getExecutor()); }, tr.getExecutor()) - .thenApply(ignore -> restart); + .thenApply(ignore -> restart); } private static int getWindowSize(long start) { @@ -1134,8 +1134,8 @@ public class DirectoryLayer implements Directory { /** * Returns a byte string that: *
    - *
  1. has never and will never be returned by another call to this method on the same subspace
  2. - *
  3. is nearly as short as possible given the above
  4. + *
  5. has never and will never be returned by another call to this method on the same subspace
  6. + *
  7. is nearly as short as possible given the above
  8. *
*/ public CompletableFuture allocate(final Transaction tr) { From c88b30b815df4e7c204e9889b7aeda30e510c430 Mon Sep 17 00:00:00 2001 From: Alec Grieser Date: Thu, 14 Dec 2017 11:49:47 -0800 Subject: [PATCH 09/10] SPACES TO TABS I CAN'T EVEN RIGHT NOW --- .../directory/DirectoryLayer.java | 6 +- .../test/AsyncDirectoryExtension.java | 188 +++++++++--------- 2 files changed, 97 insertions(+), 97 deletions(-) diff --git a/bindings/java/src-completable/main/com/apple/foundationdb/directory/DirectoryLayer.java b/bindings/java/src-completable/main/com/apple/foundationdb/directory/DirectoryLayer.java index 0e0c613513..7dde95f1a2 100644 --- a/bindings/java/src-completable/main/com/apple/foundationdb/directory/DirectoryLayer.java +++ b/bindings/java/src-completable/main/com/apple/foundationdb/directory/DirectoryLayer.java @@ -526,9 +526,9 @@ public class DirectoryLayer implements Directory { return AsyncUtil.collect( AsyncUtil.mapIterable(tr.getRange(subdir.range()), - kv -> subdir.unpack(kv.getKey()).getString(0), - tr.getExecutor() - ) + kv -> subdir.unpack(kv.getKey()).getString(0) + ), + tr.getExecutor() ); }, tr.getExecutor()) ); diff --git a/bindings/java/src-completable/test/com/apple/foundationdb/test/AsyncDirectoryExtension.java b/bindings/java/src-completable/test/com/apple/foundationdb/test/AsyncDirectoryExtension.java index d1b83b2301..6a42008eed 100644 --- a/bindings/java/src-completable/test/com/apple/foundationdb/test/AsyncDirectoryExtension.java +++ b/bindings/java/src-completable/test/com/apple/foundationdb/test/AsyncDirectoryExtension.java @@ -53,8 +53,8 @@ class AsyncDirectoryExtension { CompletableFuture processInstruction(final Instruction inst) { return executeInstruction(inst).exceptionally(e -> { - DirectoryUtil.pushError(inst, e, dirList); - return null; + DirectoryUtil.pushError(inst, e, dirList); + return null; }); } @@ -64,25 +64,25 @@ class AsyncDirectoryExtension { if(op == DirectoryOperation.DIRECTORY_CREATE_SUBSPACE) { return DirectoryUtil.popTuple(inst) .thenComposeAsync(prefix -> inst.popParam() - .thenAccept(rawPrefix -> dirList.add(new Subspace(prefix, (byte[])rawPrefix)))); + .thenAccept(rawPrefix -> dirList.add(new Subspace(prefix, (byte[])rawPrefix)))); } else if(op == DirectoryOperation.DIRECTORY_CREATE_LAYER) { return inst.popParams(3).thenAcceptAsync(params -> { - Subspace nodeSubspace = (Subspace)dirList.get(StackUtils.getInt(params.get(0))); - Subspace contentSubspace = (Subspace)dirList.get(StackUtils.getInt(params.get(1))); - boolean allowManualPrefixes = StackUtils.getInt(params.get(2)) == 1; + Subspace nodeSubspace = (Subspace)dirList.get(StackUtils.getInt(params.get(0))); + Subspace contentSubspace = (Subspace)dirList.get(StackUtils.getInt(params.get(1))); + boolean allowManualPrefixes = StackUtils.getInt(params.get(2)) == 1; - if(nodeSubspace == null || contentSubspace == null) - dirList.add(null); - else - dirList.add(new DirectoryLayer(nodeSubspace, contentSubspace, allowManualPrefixes)); + if(nodeSubspace == null || contentSubspace == null) + dirList.add(null); + else + dirList.add(new DirectoryLayer(nodeSubspace, contentSubspace, allowManualPrefixes)); }); } else if(op == DirectoryOperation.DIRECTORY_CHANGE) { return inst.popParam().thenAcceptAsync(index -> { - dirIndex = StackUtils.getInt(index); - if(dirList.get(dirIndex) == null) - dirIndex = errorIndex; + dirIndex = StackUtils.getInt(index); + if(dirList.get(dirIndex) == null) + dirIndex = errorIndex; }); } else if(op == DirectoryOperation.DIRECTORY_SET_ERROR_INDEX) { @@ -91,110 +91,110 @@ class AsyncDirectoryExtension { else if(op == DirectoryOperation.DIRECTORY_CREATE_OR_OPEN || op == DirectoryOperation.DIRECTORY_OPEN) { return DirectoryUtil.popPath(inst) .thenComposeAsync(path -> inst.popParam().thenComposeAsync(layer -> { - CompletableFuture dir; - if(layer == null) { - if(op == DirectoryOperation.DIRECTORY_CREATE_OR_OPEN) - dir = directory().createOrOpen(inst.tcx, path); - else - dir = directory().open(inst.readTcx, path); - } - else { - if(op == DirectoryOperation.DIRECTORY_CREATE_OR_OPEN) - dir = directory().createOrOpen(inst.tcx, path, (byte[])layer); - else - dir = directory().open(inst.readTcx, path, (byte[])layer); - } + CompletableFuture dir; + if(layer == null) { + if(op == DirectoryOperation.DIRECTORY_CREATE_OR_OPEN) + dir = directory().createOrOpen(inst.tcx, path); + else + dir = directory().open(inst.readTcx, path); + } + else { + if(op == DirectoryOperation.DIRECTORY_CREATE_OR_OPEN) + dir = directory().createOrOpen(inst.tcx, path, (byte[])layer); + else + dir = directory().open(inst.readTcx, path, (byte[])layer); + } - return dir.thenAccept(dirList::add); - })); + return dir.thenAccept(dirList::add); + })); } else if(op == DirectoryOperation.DIRECTORY_CREATE) { return DirectoryUtil.popPath(inst).thenComposeAsync(path -> inst.popParams(2).thenComposeAsync(params -> { - byte[] layer = (byte[])params.get(0); - byte[] prefix = (byte[])params.get(1); + byte[] layer = (byte[])params.get(0); + byte[] prefix = (byte[])params.get(1); - CompletableFuture dir; - if(layer == null && prefix == null) - dir = directory().create(inst.tcx, path); - else if(prefix == null) - dir = directory().create(inst.tcx, path, layer); - else { - if(layer == null) - layer = new byte[0]; + CompletableFuture dir; + if(layer == null && prefix == null) + dir = directory().create(inst.tcx, path); + else if(prefix == null) + dir = directory().create(inst.tcx, path, layer); + else { + if(layer == null) + layer = new byte[0]; - dir = directory().create(inst.tcx, path, layer, prefix); - } + dir = directory().create(inst.tcx, path, layer, prefix); + } - return dir.thenAccept(dirList::add); - })); + return dir.thenAccept(dirList::add); + })); } else if(op == DirectoryOperation.DIRECTORY_MOVE) { return DirectoryUtil.popPaths(inst, 2) .thenComposeAsync(paths -> directory().move(inst.tcx, paths.get(0), paths.get(1))) - .thenAccept(dirList::add); + .thenAccept(dirList::add); } else if(op == DirectoryOperation.DIRECTORY_MOVE_TO) { return DirectoryUtil.popPath(inst) .thenComposeAsync(newAbsolutePath -> directory().moveTo(inst.tcx, newAbsolutePath)) - .thenAccept(dirList::add); + .thenAccept(dirList::add); } else if(op == DirectoryOperation.DIRECTORY_REMOVE) { return inst.popParam() - .thenComposeAsync(count -> DirectoryUtil.popPaths(inst, StackUtils.getInt(count))) + .thenComposeAsync(count -> DirectoryUtil.popPaths(inst, StackUtils.getInt(count))) .thenComposeAsync(path -> { - if(path.size() == 0) - return directory().remove(inst.tcx); - else - return directory().remove(inst.tcx, path.get(0)); + if(path.size() == 0) + return directory().remove(inst.tcx); + else + return directory().remove(inst.tcx, path.get(0)); }); } else if(op == DirectoryOperation.DIRECTORY_REMOVE_IF_EXISTS) { return inst.popParam() .thenComposeAsync(count -> DirectoryUtil.popPaths(inst, StackUtils.getInt(count))) .thenComposeAsync(path -> { - if(path.size() == 0) - return AsyncUtil.success(directory().removeIfExists(inst.tcx)); - else - return AsyncUtil.success(directory().removeIfExists(inst.tcx, path.get(0))); - }); + if(path.size() == 0) + return AsyncUtil.success(directory().removeIfExists(inst.tcx)); + else + return AsyncUtil.success(directory().removeIfExists(inst.tcx, path.get(0))); + }); } else if(op == DirectoryOperation.DIRECTORY_LIST) { return inst.popParam() .thenComposeAsync(count -> DirectoryUtil.popPaths(inst, StackUtils.getInt(count))) .thenComposeAsync(path -> { - if(path.size() == 0) - return directory().list(inst.readTcx); - else - return directory().list(inst.readTcx, path.get(0)); - }) + if(path.size() == 0) + return directory().list(inst.readTcx); + else + return directory().list(inst.readTcx, path.get(0)); + }) .thenAccept(children -> inst.push(Tuple.fromItems(children).pack())); } else if(op == DirectoryOperation.DIRECTORY_EXISTS) { return inst.popParam() .thenComposeAsync(count -> DirectoryUtil.popPaths(inst, StackUtils.getInt(count))) .thenComposeAsync(path -> { - if(path.size() == 0) - return directory().exists(inst.readTcx); - else - return directory().exists(inst.readTcx, path.get(0)); + if(path.size() == 0) + return directory().exists(inst.readTcx); + else + return directory().exists(inst.readTcx, path.get(0)); }) - .thenAccept(exists -> inst.push(exists ? 1 : 0)); + .thenAccept(exists -> inst.push(exists ? 1 : 0)); } else if(op == DirectoryOperation.DIRECTORY_PACK_KEY) { return DirectoryUtil.popTuple(inst).thenAccept(keyTuple -> inst.push(subspace().pack(keyTuple))); } else if(op == DirectoryOperation.DIRECTORY_UNPACK_KEY) { return inst.popParam().thenAcceptAsync(key -> { - Tuple tup = subspace().unpack((byte[])key); - for(Object o : tup) - inst.push(o); + Tuple tup = subspace().unpack((byte[])key); + for(Object o : tup) + inst.push(o); }); } else if(op == DirectoryOperation.DIRECTORY_RANGE) { return DirectoryUtil.popTuple(inst).thenAcceptAsync(tup -> { - Range range = subspace().range(tup); - inst.push(range.begin); - inst.push(range.end); + Range range = subspace().range(tup); + inst.push(range.begin); + inst.push(range.end); }); } else if(op == DirectoryOperation.DIRECTORY_CONTAINS) { @@ -205,42 +205,42 @@ class AsyncDirectoryExtension { } else if(op == DirectoryOperation.DIRECTORY_LOG_SUBSPACE) { return inst.popParam().thenComposeAsync(prefix -> - inst.tcx.runAsync(tr -> { - tr.set(Tuple.from(dirIndex).pack((byte[])prefix), subspace().getKey()); - return AsyncUtil.DONE; - }) + inst.tcx.runAsync(tr -> { + tr.set(Tuple.from(dirIndex).pack((byte[])prefix), subspace().getKey()); + return AsyncUtil.DONE; + }) ); } else if(op == DirectoryOperation.DIRECTORY_LOG_DIRECTORY) { return inst.popParam().thenComposeAsync(prefix -> { - final Subspace logSubspace = new Subspace(new Tuple().add(dirIndex), (byte[])prefix); - return inst.tcx.runAsync(tr -> directory().exists(tr) - .thenComposeAsync(exists -> { - tr.set(logSubspace.pack("path"), Tuple.fromItems(directory().getPath()).pack()); - tr.set(logSubspace.pack("layer"), new Tuple().add(directory().getLayer()).pack()); - tr.set(logSubspace.pack("exists"), new Tuple().add(exists ? 1 : 0).pack()); - if(exists) - return directory().list(tr); - else - return CompletableFuture.completedFuture(Collections.emptyList()); - }) - .thenAcceptAsync(children -> tr.set(logSubspace.pack("children"), Tuple.fromItems(children).pack())) + final Subspace logSubspace = new Subspace(new Tuple().add(dirIndex), (byte[])prefix); + return inst.tcx.runAsync(tr -> directory().exists(tr) + .thenComposeAsync(exists -> { + tr.set(logSubspace.pack("path"), Tuple.fromItems(directory().getPath()).pack()); + tr.set(logSubspace.pack("layer"), new Tuple().add(directory().getLayer()).pack()); + tr.set(logSubspace.pack("exists"), new Tuple().add(exists ? 1 : 0).pack()); + if(exists) + return directory().list(tr); + else + return CompletableFuture.completedFuture(Collections.emptyList()); + }) + .thenAcceptAsync(children -> tr.set(logSubspace.pack("children"), Tuple.fromItems(children).pack())) ); }); } else if(op == DirectoryOperation.DIRECTORY_STRIP_PREFIX) { return inst.popParam().thenAcceptAsync(param -> { - byte[] str = (byte[])param; - byte[] rawPrefix = subspace().getKey(); + byte[] str = (byte[])param; + byte[] rawPrefix = subspace().getKey(); - if(str.length < rawPrefix.length) - throw new RuntimeException("String does not start with raw prefix"); + if(str.length < rawPrefix.length) + throw new RuntimeException("String does not start with raw prefix"); - for(int i = 0; i < rawPrefix.length; ++i) - if(str[i] != rawPrefix[i]) - throw new RuntimeException("String does not start with raw prefix"); + for(int i = 0; i < rawPrefix.length; ++i) + if(str[i] != rawPrefix[i]) + throw new RuntimeException("String does not start with raw prefix"); - inst.push(Arrays.copyOfRange(str, rawPrefix.length, str.length)); + inst.push(Arrays.copyOfRange(str, rawPrefix.length, str.length)); }); } else { From fd10562b552c8dcd6cb8d55d3a77dcd9d3434727 Mon Sep 17 00:00:00 2001 From: Alec Grieser Date: Thu, 14 Dec 2017 13:36:34 -0800 Subject: [PATCH 10/10] made tabulation consistent for two lines --- .../com/apple/foundationdb/test/AsyncDirectoryExtension.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bindings/java/src-completable/test/com/apple/foundationdb/test/AsyncDirectoryExtension.java b/bindings/java/src-completable/test/com/apple/foundationdb/test/AsyncDirectoryExtension.java index 6a42008eed..e7f68da89a 100644 --- a/bindings/java/src-completable/test/com/apple/foundationdb/test/AsyncDirectoryExtension.java +++ b/bindings/java/src-completable/test/com/apple/foundationdb/test/AsyncDirectoryExtension.java @@ -63,8 +63,8 @@ class AsyncDirectoryExtension { if(op == DirectoryOperation.DIRECTORY_CREATE_SUBSPACE) { return DirectoryUtil.popTuple(inst) - .thenComposeAsync(prefix -> inst.popParam() - .thenAccept(rawPrefix -> dirList.add(new Subspace(prefix, (byte[])rawPrefix)))); + .thenComposeAsync(prefix -> inst.popParam() + .thenAccept(rawPrefix -> dirList.add(new Subspace(prefix, (byte[])rawPrefix)))); } else if(op == DirectoryOperation.DIRECTORY_CREATE_LAYER) { return inst.popParams(3).thenAcceptAsync(params -> {