added a style guide ; fixed errors found from the style guide ; updated tests to use java 8 closures
This commit is contained in:
parent
4d734a4925
commit
33f8b2f7cf
|
@ -0,0 +1,148 @@
|
|||
<!--
|
||||
The style for code written within the FDB Java bindings.
|
||||
Note that this style guide grew up somewhat organically from
|
||||
the idiosyncracies of the committers involved. It aims to
|
||||
be at least a little idiomatically Java while at the same time
|
||||
trying not to look too incongruous when compared to the style
|
||||
of our core products (e.g., fdbserver). It also isn't
|
||||
borrowed from some other style guide, because that would
|
||||
be too easy.
|
||||
-->
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE module PUBLIC
|
||||
"-//Puppy Crawl//DTD Check Configuration 1.3//EN"
|
||||
"http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
|
||||
|
||||
|
||||
<module name="Checker">
|
||||
<module name="SuppressionFilter">
|
||||
<property name="file" value="suppressions.xml"/>
|
||||
</module>
|
||||
|
||||
<module name="TreeWalker">
|
||||
<property name="tabWidth" value="4"/>
|
||||
|
||||
<!-- Blocks -->
|
||||
<module name="AvoidNestedBlocks"/>
|
||||
<module name="EmptyBlock"/>
|
||||
<module name="EmptyCatchBlock"/>
|
||||
<module name="LeftCurly">
|
||||
<property name="option" value="eol"/>
|
||||
<property name="ignoreEnums" value="false"/>
|
||||
</module>
|
||||
<!-- We have about 76 errors with value = "alone" and 27 with value = "same". We should pick one.
|
||||
<module name="RightCurly">
|
||||
<property name="option" value="same"/>
|
||||
</module>
|
||||
-->
|
||||
|
||||
<!-- Design -->
|
||||
<!-- We might get some helpful errors if we turned this on, but not right now.
|
||||
<module name="DesignForExtension"/>
|
||||
-->
|
||||
<!-- We have some classes violating this. It seems like a reasonable thing to add, but it is technically API breaking.
|
||||
<module name="FinalClass"/>
|
||||
-->
|
||||
<module name="HideUtilityClassConstructor"/>
|
||||
<module name="MutableException"/>
|
||||
<module name="OneTopLevelClass"/>
|
||||
|
||||
<!-- Coding -->
|
||||
<module name="CovariantEquals"/>
|
||||
<module name="DefaultComesLast"/>
|
||||
<module name="EmptyStatement"/>
|
||||
<module name="EqualsHashCode"/>
|
||||
<module name="FallThrough"/>
|
||||
<!-- We should probably clean these up at some point, but not today.
|
||||
<module name="MagicNumber">
|
||||
<property name="ignoreNumbers" value="-1, 0, 1, 2, 255, 65535"/>
|
||||
<property name="ignoreHashCodeMethod" value="true"/>
|
||||
</module>
|
||||
-->
|
||||
<module name="MissingSwitchDefault"/>
|
||||
<module name="NoClone"/>
|
||||
<module name="PackageDeclaration"/>
|
||||
<module name="SimplifyBooleanExpression"/>
|
||||
<module name="SimplifyBooleanReturn"/>
|
||||
<module name="StringLiteralEquality"/>
|
||||
<module name="SuperClone"/>
|
||||
<module name="SuperFinalize"/>
|
||||
|
||||
<!-- Imports -->
|
||||
<module name="CustomImportOrder">
|
||||
<property name="customImportOrderRules" value="STATIC###STANDARD_JAVA_PACKAGE###SAME_PACKAGE(3)"/>
|
||||
</module>
|
||||
<module name="AvoidStarImport"/>
|
||||
<module name="UnusedImports"/>
|
||||
<module name="RedundantImport"/>
|
||||
|
||||
<!-- Javadoc -->
|
||||
<!-- TODO -->
|
||||
|
||||
<!-- Miscellaneous -->
|
||||
<module name="ArrayTypeStyle"/>
|
||||
<module name="CommentsIndentation"/>
|
||||
<module name="Indentation"/>
|
||||
<module name="OuterTypeFilename"/>
|
||||
<module name="UpperEll"/>
|
||||
|
||||
<!-- Modifiers -->
|
||||
<module name="ModifierOrder"/>
|
||||
<!-- I think we want this, just maybe not right now.
|
||||
<module name="RedundantModifier"/>
|
||||
-->
|
||||
|
||||
<!-- Naming conventions -->
|
||||
<module name="CatchParameterName">
|
||||
<property name="format" value="^(e\d*|t\d*|ex\d*|err\d*)$"/>
|
||||
</module>
|
||||
<module name="ClassTypeParameterName"/>
|
||||
<module name="InterfaceTypeParameterName"/>
|
||||
<module name="LocalFinalVariableName"/>
|
||||
<module name="LocalVariableName"/>
|
||||
<module name="MemberName"/>
|
||||
<module name="MethodName">
|
||||
<property name="applyToProtected" value="false"/>
|
||||
<property name="applyToPackage" value="false"/>
|
||||
<property name="applyToPrivate" value="false"/>
|
||||
</module>
|
||||
<module name="MethodTypeParameterName"/>
|
||||
<module name="PackageName"/>
|
||||
<module name="ParameterName"/>
|
||||
<module name="StaticVariableName"/>
|
||||
<module name="TypeName"/>
|
||||
|
||||
<!-- Whitespace -->
|
||||
<module name="EmptyForInitializerPad"/>
|
||||
<module name="EmptyForIteratorPad"/>
|
||||
<module name="GenericWhitespace"/>
|
||||
<module name="MethodParamPad"/>
|
||||
<module name="NoLineWrap"/>
|
||||
<module name="NoWhitespaceAfter">
|
||||
<property name="tokens" value="AT, INC, DEC, UNARY_MINUS, UNARY_PLUS, BNOT, LNOT, DOT, ARRAY_DECLARATOR, INDEX_OP, METHOD_REF"/>
|
||||
</module>
|
||||
<module name="NoWhitespaceBefore">
|
||||
<property name="allowLineBreaks" value="true"/>
|
||||
<property name="tokens" value="COMMA, SEMI, POST_INC, POST_DEC, DOT, ELLIPSIS, METHOD_REF"/>
|
||||
</module>
|
||||
<module name="OperatorWrap">
|
||||
<property name="option" value="eol"/>
|
||||
</module>
|
||||
<module name="ParenPad"/>
|
||||
<module name="SeparatorWrap">
|
||||
<property name="option" value="eol"/>
|
||||
<property name="tokens" value="COMMA"/>
|
||||
</module>
|
||||
<module name="SeparatorWrap">
|
||||
<property name="option" value="nl"/>
|
||||
<property name="tokens" value="DOT"/>
|
||||
</module>
|
||||
<module name="TypecastParenPad">
|
||||
<property name="option" value="nospace"/>
|
||||
</module>
|
||||
<module name="WhitespaceAfter">
|
||||
<property name="tokens" value="SEMI"/>
|
||||
</module>
|
||||
|
||||
</module>
|
||||
</module>
|
|
@ -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;
|
||||
|
||||
/**
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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<Long> 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<byte[]> 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<byte[]> 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();
|
||||
|
|
|
@ -179,4 +179,6 @@ class JNIUtil {
|
|||
return OS.OSX;
|
||||
throw new IllegalStateException("Unknown or unsupported OS: " + osname);
|
||||
}
|
||||
|
||||
private JNIUtil() {}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -82,7 +82,7 @@ abstract class NativeFuture<T> extends CompletableFuture<T> 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<T> extends CompletableFuture<T> 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");
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) + "\"") + ")";
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ package com.apple.foundationdb;
|
|||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.apple.foundationdb.tuple.Tuple;
|
||||
|
||||
/**
|
||||
|
|
|
@ -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 <I,O> CompletableFuture<O> applySafely( Function<I, ? extends CompletableFuture<O>> func, I value ) {
|
||||
public static <I,O> CompletableFuture<O> applySafely(Function<I, ? extends CompletableFuture<O>> 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 <V> type of the items returned by the iterable
|
||||
*
|
||||
* @return a future that is ready once the asynchronous operation completes
|
||||
*/
|
||||
public static <V> CompletableFuture<Void> forEach(final AsyncIterable<V> iterable, final Consumer<? super V> 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 <V> type of the items returned by the iterable
|
||||
*
|
||||
* @return a future that is ready once the asynchronous operation completes
|
||||
*/
|
||||
public static <V> CompletableFuture<Void> forEach(final AsyncIterable<V> iterable, final Consumer<? super V> 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 <V> type of the items returned by the iterator
|
||||
*
|
||||
* @return a future that is ready once the asynchronous operation completes
|
||||
*/
|
||||
public static <V> CompletableFuture<Void> forEach(final AsyncIterator<V> iterator, final Consumer<? super V> 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 <V> type of the items returned by the iterator
|
||||
*
|
||||
* @return a future that is ready once the asynchronous operation completes
|
||||
*/
|
||||
public static <V> CompletableFuture<Void> forEach(final AsyncIterator<V> iterator, final Consumer<? super V> consumer, final Executor executor) {
|
||||
return iterator.onHasNext().thenComposeAsync(hasAny -> {
|
||||
if (hasAny) {
|
||||
|
@ -387,16 +443,65 @@ public class AsyncUtil {
|
|||
});
|
||||
}
|
||||
|
||||
public static <V, T> CompletableFuture<T> composeHandle(CompletableFuture<V> future, BiFunction<V,Throwable,? extends CompletableFuture<T>> 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 <V> return type of original future
|
||||
* @param <T> return type of final future
|
||||
*
|
||||
* @return future with same completion properties as the future returned by the handler
|
||||
*/
|
||||
public static <V, T> CompletableFuture<T> composeHandle(CompletableFuture<V> future, BiFunction<V,Throwable,? extends CompletableFuture<T>> handler) {
|
||||
return future.handle(handler).thenCompose(Function.identity());
|
||||
}
|
||||
|
||||
public static <V, T> CompletableFuture<T> composeHandleAsync(CompletableFuture<V> future, BiFunction<V,Throwable,? extends CompletableFuture<T>> 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 <V> return type of original future
|
||||
* @param <T> return type of final future
|
||||
*
|
||||
* @return future with same completion properties as the future returned by the handler
|
||||
*/
|
||||
public static <V, T> CompletableFuture<T> composeHandleAsync(CompletableFuture<V> future, BiFunction<V,Throwable,? extends CompletableFuture<T>> handler) {
|
||||
return composeHandleAsync(future, handler, DEFAULT_EXECUTOR);
|
||||
}
|
||||
|
||||
public static <V, T> CompletableFuture<T> composeHandleAsync(CompletableFuture<V> future, BiFunction<V,Throwable,? extends CompletableFuture<T>> 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 <V> return type of original future
|
||||
* @param <T> return type of final future
|
||||
*
|
||||
* @return future with same completion properties as the future returned by the handler
|
||||
*/
|
||||
public static <V, T> CompletableFuture<T> composeHandleAsync(CompletableFuture<V> future, BiFunction<V,Throwable,? extends CompletableFuture<T>> handler, Executor executor) {
|
||||
return future.handleAsync(handler, executor).thenCompose(Function.identity());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -66,8 +66,7 @@ import com.apple.foundationdb.tuple.Tuple;
|
|||
* access to subspaces.
|
||||
* </p>
|
||||
*/
|
||||
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<String> 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<CompletableFuture<Node>> 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<CompletableFuture<Node>> 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<String> parentPath = PathUtil.popBack(newPathCopy);
|
||||
return new NodeFinder(parentPath).find(tr).thenComposeAsync(parentNode -> {
|
||||
if(!parentNode.exists())
|
||||
throw new NoSuchDirectoryException(toAbsolutePath(parentPath));
|
||||
final List<String> 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<String> 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<CompletableFuture<Void>> 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<CompletableFuture<Void>> 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<Void> removeFromParent(final Transaction tr, final List<String> 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<String> 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<String> 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<String> 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<String> 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<String> 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();
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,28 +45,28 @@ import com.apple.foundationdb.subspace.Subspace;
|
|||
* </p>
|
||||
*/
|
||||
public class DirectorySubspace extends Subspace implements Directory {
|
||||
private final List<String> path;
|
||||
private final byte[] layer;
|
||||
private final DirectoryLayer directoryLayer;
|
||||
private final List<String> path;
|
||||
private final byte[] layer;
|
||||
private final DirectoryLayer directoryLayer;
|
||||
|
||||
DirectorySubspace(List<String> path, byte[] prefix, DirectoryLayer directoryLayer) {
|
||||
this(path, prefix, directoryLayer, EMPTY_BYTES);
|
||||
}
|
||||
DirectorySubspace(List<String> path, byte[] prefix, DirectoryLayer directoryLayer) {
|
||||
this(path, prefix, directoryLayer, EMPTY_BYTES);
|
||||
}
|
||||
|
||||
DirectorySubspace(List<String> path, byte[] prefix, DirectoryLayer directoryLayer, byte[] layer) {
|
||||
super(prefix);
|
||||
this.path = path;
|
||||
this.layer = layer;
|
||||
this.directoryLayer = directoryLayer;
|
||||
}
|
||||
DirectorySubspace(List<String> 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<String> 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<String> getPath() {
|
||||
return Collections.unmodifiableList(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getLayer() {
|
||||
return Arrays.copyOf(layer, layer.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DirectoryLayer getDirectoryLayer() {
|
||||
return directoryLayer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<DirectorySubspace> createOrOpen(TransactionContext tcx, List<String> subpath, byte[] otherLayer) {
|
||||
return directoryLayer.createOrOpen(tcx, getPartitionSubpath(subpath), otherLayer);
|
||||
}
|
||||
@Override
|
||||
public CompletableFuture<DirectorySubspace> createOrOpen(TransactionContext tcx, List<String> subpath, byte[] otherLayer) {
|
||||
return directoryLayer.createOrOpen(tcx, getPartitionSubpath(subpath), otherLayer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<DirectorySubspace> open(ReadTransactionContext tcx, List<String> subpath, byte[] otherLayer) {
|
||||
return directoryLayer.open(tcx, getPartitionSubpath(subpath), otherLayer);
|
||||
}
|
||||
@Override
|
||||
public CompletableFuture<DirectorySubspace> open(ReadTransactionContext tcx, List<String> subpath, byte[] otherLayer) {
|
||||
return directoryLayer.open(tcx, getPartitionSubpath(subpath), otherLayer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<DirectorySubspace> create(TransactionContext tcx, List<String> subpath, byte[] otherLayer, byte[] prefix) {
|
||||
return directoryLayer.create(tcx, getPartitionSubpath(subpath), otherLayer, prefix);
|
||||
}
|
||||
@Override
|
||||
public CompletableFuture<DirectorySubspace> create(TransactionContext tcx, List<String> subpath, byte[] otherLayer, byte[] prefix) {
|
||||
return directoryLayer.create(tcx, getPartitionSubpath(subpath), otherLayer, prefix);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<List<String>> list(ReadTransactionContext tcx, List<String> subpath) {
|
||||
return directoryLayer.list(tcx, getPartitionSubpath(subpath));
|
||||
}
|
||||
@Override
|
||||
public CompletableFuture<List<String>> list(ReadTransactionContext tcx, List<String> subpath) {
|
||||
return directoryLayer.list(tcx, getPartitionSubpath(subpath));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<DirectorySubspace> move(TransactionContext tcx, List<String> oldSubpath, List<String> newSubpath) {
|
||||
return directoryLayer.move(tcx, getPartitionSubpath(oldSubpath), getPartitionSubpath(newSubpath));
|
||||
}
|
||||
@Override
|
||||
public CompletableFuture<DirectorySubspace> move(TransactionContext tcx, List<String> oldSubpath, List<String> newSubpath) {
|
||||
return directoryLayer.move(tcx, getPartitionSubpath(oldSubpath), getPartitionSubpath(newSubpath));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<DirectorySubspace> moveTo(TransactionContext tcx, List<String> newAbsolutePath) {
|
||||
@Override
|
||||
public CompletableFuture<DirectorySubspace> moveTo(TransactionContext tcx, List<String> newAbsolutePath) {
|
||||
DirectoryLayer dir = getLayerForPath(EMPTY_PATH);
|
||||
int partitionLen = dir.getPath().size();
|
||||
List<String> 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<Void> remove(TransactionContext tcx, List<String> subpath) {
|
||||
@Override
|
||||
public CompletableFuture<Void> remove(TransactionContext tcx, List<String> subpath) {
|
||||
DirectoryLayer dir = getLayerForPath(subpath);
|
||||
return dir.remove(tcx, getPartitionSubpath(subpath, dir));
|
||||
}
|
||||
return dir.remove(tcx, getPartitionSubpath(subpath, dir));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Boolean> removeIfExists(TransactionContext tcx, List<String> subpath) {
|
||||
@Override
|
||||
public CompletableFuture<Boolean> removeIfExists(TransactionContext tcx, List<String> subpath) {
|
||||
DirectoryLayer dir = getLayerForPath(subpath);
|
||||
return dir.removeIfExists(tcx, getPartitionSubpath(subpath, dir));
|
||||
}
|
||||
return dir.removeIfExists(tcx, getPartitionSubpath(subpath, dir));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Boolean> exists(ReadTransactionContext tcx, List<String> subpath) {
|
||||
@Override
|
||||
public CompletableFuture<Boolean> exists(ReadTransactionContext tcx, List<String> subpath) {
|
||||
DirectoryLayer dir = getLayerForPath(subpath);
|
||||
return dir.exists(tcx, getPartitionSubpath(subpath, dir));
|
||||
}
|
||||
return dir.exists(tcx, getPartitionSubpath(subpath, dir));
|
||||
}
|
||||
|
||||
private List<String> getPartitionSubpath(List<String> path) {
|
||||
return getPartitionSubpath(path, directoryLayer);
|
||||
|
|
|
@ -42,4 +42,6 @@ class DirectoryUtil {
|
|||
sb.append(')');
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private DirectoryUtil() {}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -92,4 +92,6 @@ public class PathUtil {
|
|||
|
||||
return new LinkedList<String>(path.subList(0, path.size() - 1));
|
||||
}
|
||||
|
||||
private PathUtil() {}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
* </p>
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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<Tuple>, Iterable<Object> {
|
|||
*
|
||||
* @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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"));
|
||||
}
|
||||
}
|
|
@ -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<Void> apply(Transaction tr) {
|
||||
return tr.getRange(Range.startsWith(prefix)).asList().thenApplyAsync(new Function<List<KeyValue>, Void>() {
|
||||
@Override
|
||||
public Void apply(List<KeyValue> 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<Object, Void>() {
|
||||
@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<StackEntry, Void>() {
|
||||
@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<Object, CompletableFuture<Void>>() {
|
||||
@Override
|
||||
public CompletableFuture<Void> apply(Object param) {
|
||||
WaitEmpty retryable = new WaitEmpty((byte[])param);
|
||||
return inst.context.db.runAsync(retryable).thenApply(new Function<Void, Void>() {
|
||||
@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<Object, Void>() {
|
||||
@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<Object, Void>() {
|
||||
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<List<Object>, CompletableFuture<Void>>() {
|
||||
@Override
|
||||
public CompletableFuture<Void> apply(final List<Object> 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<Transaction, CompletableFuture<Void>>() {
|
||||
@Override
|
||||
public CompletableFuture<Void> 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<Object, CompletableFuture<Void>>() {
|
||||
@Override
|
||||
public CompletableFuture<Void> apply(final Object param) {
|
||||
//System.out.println(inst.context.preStr + " - " + "Clearing: '" + ByteArrayUtil.printable((byte[])param) + "'");
|
||||
return executeMutation(inst, new Function<Transaction, CompletableFuture<Void>>() {
|
||||
@Override
|
||||
public CompletableFuture<Void> 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<List<Object>, CompletableFuture<Void>>() {
|
||||
@Override
|
||||
public CompletableFuture<Void> apply(final List<Object> params) {
|
||||
return executeMutation(inst, new Function<Transaction, CompletableFuture<Void>>() {
|
||||
@Override
|
||||
public CompletableFuture<Void> 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<Object, CompletableFuture<Void>>() {
|
||||
@Override
|
||||
public CompletableFuture<Void> apply(final Object param) {
|
||||
return executeMutation(inst, new Function<Transaction, CompletableFuture<Void>>() {
|
||||
@Override
|
||||
public CompletableFuture<Void> 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<List<Object>, CompletableFuture<Void>>() {
|
||||
@Override
|
||||
public CompletableFuture<Void> apply(final List<Object> params) {
|
||||
final MutationType optype = MutationType.valueOf((String)params.get(0));
|
||||
return executeMutation(inst,
|
||||
new Function<Transaction, CompletableFuture<Void>>() {
|
||||
@Override
|
||||
public CompletableFuture<Void> 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<List<Object>, Void>() {
|
||||
@Override
|
||||
public Void apply(List<Object> 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<List<Object>, Void>() {
|
||||
@Override
|
||||
public Void apply(List<Object> 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<Object, Void>() {
|
||||
@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<Object, Void>() {
|
||||
@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<Object, Void>() {
|
||||
@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<List<Object>, CompletableFuture<Void>>() {
|
||||
@Override
|
||||
public CompletableFuture<Void> apply(List<Object> 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<List<KeyValue>> range = inst.readTcx.readAsync(readTr -> readTr.getRange((byte[])params.get(0), (byte[])params.get(1), limit, reverse, mode).asList());
|
||||
return pushRange(inst, range);
|
||||
}
|
||||
});
|
||||
CompletableFuture<List<KeyValue>> 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<List<Object>, CompletableFuture<Void>>() {
|
||||
@Override
|
||||
public CompletableFuture<Void> apply(List<Object> 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<List<KeyValue>> range = inst.readTcx.readAsync(readTr -> readTr.getRange(start, end, limit, reverse, mode).asList());
|
||||
return pushRange(inst, range, (byte[])params.get(9));
|
||||
}
|
||||
});
|
||||
CompletableFuture<List<KeyValue>> 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<List<Object>, CompletableFuture<Void>>() {
|
||||
@Override
|
||||
public CompletableFuture<Void> apply(List<Object> 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<List<KeyValue>> range = inst.readTcx.readAsync(readTr -> readTr.getRange(Range.startsWith((byte[])params.get(0)), limit, reverse, mode).asList());
|
||||
return pushRange(inst, range);
|
||||
}
|
||||
CompletableFuture<List<KeyValue>> 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<List<Object>, Void>() {
|
||||
@Override
|
||||
public Void apply(List<Object> 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<Long, Void>() {
|
||||
@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<Object, CompletableFuture<Void>>() {
|
||||
@Override
|
||||
public CompletableFuture<Void> 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<Void> 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<Void> 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<List<Object>, Void>() {
|
||||
@Override
|
||||
public Void apply(List<Object> 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<List<Object>, Void>() {
|
||||
@Override
|
||||
public Void apply(List<Object> 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<Object, CompletableFuture<Void>>() {
|
||||
@Override
|
||||
public CompletableFuture<Void> 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<List<Object>, Void>() {
|
||||
@Override
|
||||
public Void apply(List<Object> 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<List<Object>, CompletableFuture<Void>>() {
|
||||
@Override
|
||||
public CompletableFuture<Void> apply(List<Object> 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<List<Object>, Void>() {
|
||||
@Override
|
||||
public Void apply(List<Object> 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<Object, Void>() {
|
||||
@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<Object, CompletableFuture<Void>>() {
|
||||
@Override
|
||||
public CompletableFuture<Void> 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<List<Object>, Void>() {
|
||||
@Override
|
||||
public Void apply(List<Object> 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<Object, CompletableFuture<Void>>() {
|
||||
@Override
|
||||
public CompletableFuture<Void> apply(Object param) {
|
||||
final int listSize = StackUtils.getInt(param);
|
||||
return inst.popParams(listSize).thenApply(new Function<List<Object>, Void>() {
|
||||
@Override
|
||||
public Void apply(List<Object> rawElements) {
|
||||
List<Tuple> tuples = new ArrayList<Tuple>(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<Tuple> 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<Object, Void>() {
|
||||
@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<Object, Void>() {
|
||||
@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<Object, Void>() {
|
||||
@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<Object, Void>() {
|
||||
@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<Void> executeMutation(final Instruction inst, Function<Transaction, CompletableFuture<Void>> r) {
|
||||
// run this with a retry loop
|
||||
return inst.tcx.runAsync(r).thenApplyAsync(new Function<Void, Void>() {
|
||||
@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<byte[]> executeGetKey(final CompletableFuture<byte[]> keyFuture, final byte[] prefixFilter) {
|
||||
return keyFuture.thenApplyAsync(new Function<byte[], byte[]>() {
|
||||
@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<Void> 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<KeyValue> list) {
|
||||
List<byte[]> o = new LinkedList<byte[]>();
|
||||
List<byte[]> 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<Void> executeRemainingOperations() {
|
||||
final Function<Void, CompletableFuture<Void>> processNext = new Function<Void, CompletableFuture<Void>>() {
|
||||
@Override
|
||||
public CompletableFuture<Void> apply(Void ignore) {
|
||||
instructionIndex++;
|
||||
return executeRemainingOperations();
|
||||
}
|
||||
final Function<Void, CompletableFuture<Void>> 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<List<KeyValue>, CompletableFuture<Void>>() {
|
||||
@Override
|
||||
public CompletableFuture<Void> apply(List<KeyValue> 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<Object> future = (CompletableFuture<Object>)item;
|
||||
final CompletableFuture<?> future = (CompletableFuture<?>)item;
|
||||
CompletableFuture<Object> flattened = flatten(future);
|
||||
|
||||
return flattened.thenApplyAsync(new Function<Object, StackEntry>() {
|
||||
@Override
|
||||
public StackEntry apply(Object o) {
|
||||
return new StackEntry(idx, o);
|
||||
}
|
||||
});
|
||||
return flattened.thenApplyAsync(o -> new StackEntry(idx, o));
|
||||
}
|
||||
|
||||
private static CompletableFuture<Object> flatten(final CompletableFuture<Object> future) {
|
||||
CompletableFuture<Object> f = future.thenApplyAsync(new Function<Object, Object>() {
|
||||
@Override
|
||||
public Object apply(Object o) {
|
||||
if(o == null)
|
||||
return "RESULT_NOT_PRESENT".getBytes();
|
||||
return o;
|
||||
}
|
||||
private static CompletableFuture<Object> flatten(final CompletableFuture<?> future) {
|
||||
CompletableFuture<Object> f = future.thenApply(o -> {
|
||||
if(o == null)
|
||||
return "RESULT_NOT_PRESENT".getBytes();
|
||||
return o;
|
||||
});
|
||||
|
||||
return AsyncUtil.composeExceptionally(f, new Function<Throwable, CompletableFuture<Object>>() {
|
||||
@Override
|
||||
public CompletableFuture<Object> apply(Throwable t) {
|
||||
FDBException e = StackUtils.getRootFDBException(t);
|
||||
if(e != null) {
|
||||
return CompletableFuture.completedFuture(StackUtils.getErrorBytes(e));
|
||||
}
|
||||
|
||||
CompletableFuture<Object> error = new CompletableFuture<Object>();
|
||||
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<Object> 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() {}
|
||||
}
|
||||
|
|
|
@ -44,78 +44,59 @@ public class BlockingBenchmark {
|
|||
|
||||
Transaction tr = database.createTransaction();
|
||||
tr.setReadVersion(100000);
|
||||
final Function<Long,Long> identity = new Function<Long, Long>() {
|
||||
@Override
|
||||
public Long apply(Long o) {
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
System.out.println("readVersion().join():");
|
||||
runTests(tr, new Function<CompletableFuture<Long>, Void>() {
|
||||
@Override
|
||||
public Void apply(CompletableFuture<Long> 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<CompletableFuture<Long>, Void>() {
|
||||
@Override
|
||||
public Void apply(CompletableFuture<Long> 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<CompletableFuture<Long>, Void>() {
|
||||
@Override
|
||||
public Void apply(CompletableFuture<Long> 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<CompletableFuture<Long>, Void>() {
|
||||
@Override
|
||||
public Void apply(CompletableFuture<Long> 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<CompletableFuture<Long>, Void>() {
|
||||
@Override
|
||||
public Void apply(CompletableFuture<Long> 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() {}
|
||||
}
|
||||
|
|
|
@ -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<Transaction, CompletableFuture<Void>>() {
|
||||
@Override
|
||||
public CompletableFuture<Void> apply(final Transaction r) {
|
||||
attemptCount.addAndGet(1);
|
||||
final String key = "test:" + random.nextInt();
|
||||
return r.get($(key)).thenComposeAsync(new Function<byte[], CompletableFuture<Void>>() {
|
||||
@Override
|
||||
public CompletableFuture<Void> apply(byte[] o) {
|
||||
r.set($(key), $("value"));
|
||||
return r.get($(key)).thenApplyAsync(new Function<byte[], Void>() {
|
||||
@Override
|
||||
public Void apply(byte[] o) {
|
||||
getCompleteCount.addAndGet(1);
|
||||
semaphore.release();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}).exceptionally(new Function<Throwable, Void>() {
|
||||
@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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<Thread> children = new LinkedList<>();
|
||||
static private Map<String, Transaction> transactionMap = new HashMap<>();
|
||||
static private Map<Transaction, AtomicInteger> transactionRefCounts = new HashMap<>();
|
||||
private static Map<String, Transaction> transactionMap = new HashMap<>();
|
||||
private static Map<Transaction, AtomicInteger> 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<Object> future = (CompletableFuture<Object>)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<List<Object>> popParams(int num) {
|
||||
final List<Object> params = new LinkedList<>();
|
||||
final List<Object> params = new ArrayList<>(num);
|
||||
CompletableFuture<Void> done = new CompletableFuture<>();
|
||||
popParams(num, params, done);
|
||||
|
||||
return done.thenApplyAsync((x) -> params);
|
||||
return done.thenApply(x -> params);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -25,54 +25,59 @@ import java.util.Collections;
|
|||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
public class ContinuousSample <T extends Number & Comparable<T>> {
|
||||
public ContinuousSample( int sampleSize ) {
|
||||
public class ContinuousSample<T extends Number & Comparable<T>> {
|
||||
public ContinuousSample(int sampleSize) {
|
||||
this.sampleSize = sampleSize;
|
||||
this.samples = new ArrayList<T>(sampleSize);
|
||||
this.samples = new ArrayList<>(sampleSize);
|
||||
this.populationSize = 0;
|
||||
this.sorted = true;
|
||||
}
|
||||
|
||||
public ContinuousSample<T> 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 <T extends Number & Comparable<T>> {
|
|||
private long populationSize;
|
||||
private boolean sorted;
|
||||
private List<T> 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;
|
||||
}
|
||||
|
|
|
@ -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<Transaction, Void>() {
|
||||
@Override
|
||||
public Void apply(Transaction tr) {
|
||||
List<String> 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<String> 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() {}
|
||||
}
|
||||
|
|
|
@ -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<List<Tuple>> pop() {
|
||||
return AsyncUtil.whileTrue(new Supplier<CompletableFuture<Boolean>>() {
|
||||
@Override
|
||||
public CompletableFuture<Boolean> get() {
|
||||
if(num-- == 0) {
|
||||
return CompletableFuture.completedFuture(false);
|
||||
}
|
||||
return inst.popParam()
|
||||
.thenComposeAsync(new Function<Object, CompletableFuture<List<Object>>>() {
|
||||
@Override
|
||||
public CompletableFuture<List<Object>> apply(Object count) {
|
||||
return inst.popParams(StackUtils.getInt(count));
|
||||
}
|
||||
})
|
||||
.thenApplyAsync(new Function<List<Object>, Boolean>() {
|
||||
@Override
|
||||
public Boolean apply(List<Object> 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<Void, List<Tuple>>() {
|
||||
@Override
|
||||
public List<Tuple> apply(Void ignore) {
|
||||
return tuples;
|
||||
}
|
||||
});
|
||||
.thenApply(ignore -> tuples);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -77,42 +60,26 @@ class DirectoryUtil {
|
|||
}
|
||||
|
||||
static CompletableFuture<Tuple> popTuple(Instruction inst) {
|
||||
return popTuples(inst, 1)
|
||||
.thenApplyAsync(new Function<List<Tuple>, Tuple>() {
|
||||
@Override
|
||||
public Tuple apply(List<Tuple> tuples) {
|
||||
return tuples.get(0);
|
||||
}
|
||||
});
|
||||
return popTuples(inst, 1).thenApply(tuples -> tuples.get(0));
|
||||
}
|
||||
|
||||
static CompletableFuture<List<List<String>>> popPaths(Instruction inst, int num) {
|
||||
return popTuples(inst, num)
|
||||
.thenApplyAsync(new Function<List<Tuple>, List<List<String>>>() {
|
||||
@Override
|
||||
public List<List<String>> apply(List<Tuple> tuples) {
|
||||
List<List<String>> paths = new ArrayList<List<String>>();
|
||||
for(Tuple t : tuples) {
|
||||
List<String> path = new ArrayList<String>();
|
||||
for(int i = 0; i < t.size(); ++i)
|
||||
path.add(t.getString(i));
|
||||
return popTuples(inst, num).thenApplyAsync(tuples -> {
|
||||
List<List<String>> paths = new ArrayList<>(tuples.size());
|
||||
for(Tuple t : tuples) {
|
||||
List<String> 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<List<String>> popPath(Instruction inst) {
|
||||
return popPaths(inst, 1)
|
||||
.thenApplyAsync(new Function<List<List<String>>, List<String>>() {
|
||||
@Override
|
||||
public List<String> apply(List<List<String>> paths) {
|
||||
return paths.get(0);
|
||||
}
|
||||
});
|
||||
return popPaths(inst, 1).thenApply(paths -> paths.get(0));
|
||||
}
|
||||
|
||||
static void pushError(Instruction inst, Throwable t, List<Object> dirList) {
|
||||
|
@ -123,4 +90,6 @@ class DirectoryUtil {
|
|||
if(op.createsDirectory)
|
||||
dirList.add(null);
|
||||
}
|
||||
|
||||
private DirectoryUtil() {}
|
||||
}
|
||||
|
|
|
@ -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<Transaction, Void>() {
|
||||
@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<Transaction, Void>) 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<Transaction, String>() {
|
||||
@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() {}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<Transaction, Void>() {
|
||||
@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() {}
|
||||
}
|
||||
|
|
|
@ -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<byte[]> keys = LocalityUtil.getBoundaryKeys(database, new byte[0], new byte[] { (byte)255 } );
|
||||
CloseableAsyncIterator<byte[]> keys = LocalityUtil.getBoundaryKeys(database, new byte[0], new byte[] { (byte)255 });
|
||||
CompletableFuture<List<byte[]>> collection = AsyncUtil.collect(keys);
|
||||
List<byte[]> 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() {}
|
||||
}
|
||||
|
|
|
@ -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<KeyValue> it = range.iterator();
|
||||
final CompletableFuture<KeyValue> f = it.onHasNext().thenApplyAsync(
|
||||
new Function<Boolean, KeyValue>() {
|
||||
@Override
|
||||
public KeyValue apply(Boolean o) {
|
||||
if(!o) {
|
||||
return null;
|
||||
}
|
||||
return it.next();
|
||||
}
|
||||
}
|
||||
);
|
||||
f.whenCompleteAsync(new BiConsumer<KeyValue, Throwable>() {
|
||||
@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<KeyValue> 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() {}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -55,22 +55,19 @@ public class RangeTest {
|
|||
Database db = fdb.open();
|
||||
|
||||
try {
|
||||
db.run(new Function<Transaction, Void>() {
|
||||
@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<Transaction, Void>) 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<KeyValue> entryList = tr.getRange(
|
||||
AsyncIterable<KeyValue> entryList = tr.getRange(
|
||||
KeySelector.firstGreaterOrEqual("apple".getBytes()),
|
||||
KeySelector.firstGreaterOrEqual("banana".getBytes()),4);
|
||||
List<KeyValue> entries = entryList.asList().join();
|
||||
|
@ -187,4 +184,6 @@ public class RangeTest {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
private RangeTest() {}
|
||||
}
|
||||
|
|
|
@ -94,4 +94,5 @@ public class SerialInsertion {
|
|||
}
|
||||
}
|
||||
|
||||
private SerialInsertion() {}
|
||||
}
|
||||
|
|
|
@ -133,4 +133,6 @@ public class SerialIteration {
|
|||
}
|
||||
return counter;
|
||||
}
|
||||
|
||||
private SerialIteration() {}
|
||||
}
|
||||
|
|
|
@ -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<Transaction, Void>() {
|
||||
@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() {}
|
||||
}
|
||||
|
|
|
@ -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<Object> 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<Object> 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<Transaction, Void>() {
|
||||
@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<Object> params = inst.popParams(1).join();
|
||||
//System.out.println(inst.context.preStr + " - " + "Clearing: '" + ByteArrayUtil.printable((byte[]) params.get(0)) + "'");
|
||||
executeMutation(inst,
|
||||
new Function<Transaction, Void>() {
|
||||
@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<Object> params = inst.popParams(2).join();
|
||||
executeMutation(inst,
|
||||
new Function<Transaction, Void>() {
|
||||
@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<Object> params = inst.popParams(1).join();
|
||||
executeMutation(inst,
|
||||
new Function<Transaction, Void>() {
|
||||
@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<Object> params = inst.popParams(3).join();
|
||||
final MutationType optype = MutationType.valueOf((String)params.get(0));
|
||||
executeMutation(inst,
|
||||
new Function<Transaction, Void>() {
|
||||
@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() {}
|
||||
}
|
||||
|
||||
|
|
|
@ -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() {}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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<Transaction, Void>() {
|
||||
@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<byte[], byte[]> 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<byte[], byte[]> 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() {}
|
||||
}
|
||||
|
|
|
@ -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<byte[]> 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() {}
|
||||
}
|
||||
|
|
|
@ -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() {}
|
||||
}
|
||||
|
|
|
@ -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() {}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!DOCTYPE suppressions PUBLIC
|
||||
"-//Puppy Crawl//DTD Suppressions 1.1//EN"
|
||||
"http://checkstyle.sourceforge.net/dtds/suppressions_1_1.dtd">
|
||||
|
||||
<suppressions>
|
||||
<!-- These files are auto generated. Ignore those files for style checks. -->
|
||||
<suppress files=".+Options\.java" checks=".*"/>
|
||||
<suppress files=".+ConflictRangeType\.java" checks=".*"/>
|
||||
<suppress files=".+FDBException\.java" checks=".*"/>
|
||||
<suppress files=".+MutationType\.java" checks=".*"/>
|
||||
<suppress files=".+StreamingMode\.java" checks=".*"/>
|
||||
</suppressions>
|
Loading…
Reference in New Issue