added packWithVersionstamp to subspace ; some testing/javadocs tweaks

This commit is contained in:
Alec Grieser 2017-10-11 10:53:51 -07:00
parent f95553aca2
commit 9fd934e002
10 changed files with 105 additions and 37 deletions

View File

@ -28,6 +28,7 @@ import java.util.Arrays;
import com.apple.cie.foundationdb.Range;
import com.apple.cie.foundationdb.tuple.ByteArrayUtil;
import com.apple.cie.foundationdb.tuple.Tuple;
import com.apple.cie.foundationdb.tuple.Versionstamp;
/**
* {@code Subspace} provide a convenient way to use {@link Tuple}s to define namespaces for
@ -60,8 +61,11 @@ public class Subspace
/**
* Constructor for a subspace formed with the specified prefix {@link Tuple}.
* Note that the {@link Tuple} {@code prefix} should not contain any incomplete
* {@link Versionstamp}s as any of its entries.
*
* @param prefix a {@link Tuple} used to form the subspace
* @throws IllegalArgumentException if {@code prefix} contains any incomplete {@link Versionstamp}s
*/
public Subspace(Tuple prefix) {
this(prefix, EMPTY_BYTES);
@ -81,10 +85,12 @@ public class Subspace
* Constructor for a subspace formed with both a prefix {@link Tuple} and a
* prefix byte string. The prefix {@code Tuple} will be prepended to all
* {@code Tuples} packed by the {@code Subspace}, and the byte string prefix
* will be prepended to the packed result.
* will be prepended to the packed result. Note that the {@link Tuple} {@code prefix}
* should not contain any incomplete {@link Versionstamp}s as any of its entries.
*
* @param prefix a {@code Tuple} used to form the subspace
* @param rawPrefix a byte array used as the prefix for all packed keys
* @throws IllegalArgumentException if {@code prefix} contains any incomplete {@link Versionstamp}s
*/
public Subspace(Tuple prefix, byte[] rawPrefix) {
this.rawPrefix = join(rawPrefix, prefix.pack());
@ -181,6 +187,24 @@ public class Subspace
return join(rawPrefix, tuple.pack());
}
/**
* Gets the key encoding the specified tuple in this {@code Subspace} for use with
* {@link com.apple.cie.foundationdb.MutationType#SET_VERSIONSTAMPED_KEY MutationType.SET_VERSIONSTAMPED_KEY}.
* There must be exactly one incomplete {@link Versionstamp} included in the given {@link Tuple}. It will
* create a key that is within this {@code Subspace} that can be provided as the {@code key} argument to
* {@link com.apple.cie.foundationdb.Transaction#mutate(com.apple.cie.foundationdb.MutationType, byte[], byte[]) Transaction.mutate()}
* with the {@link com.apple.cie.foundationdb.MutationType#SET_VERSIONSTAMPED_KEY SET_VERSIONSTAMPED_KEY}
* mutation. This will throw an {@link IllegalArgumentException} if the {@link Tuple} does not
* contain an incomplete {@link Versionstamp} or if it contains multiple.
*
* @param tuple the {@code Tuple} to be packed
* @return the key encoding the specified tuple in this {@code Subspace}
* @throws IllegalArgumentException if {@code tuple} does not contain exactly one incomplete {@link Versionstamp}
*/
public byte[] packWithVersionstamp(Tuple tuple) {
return tuple.packWithVersionstamp(rawPrefix);
}
/**
* Gets the {@link Tuple} encoded by the given key, with this {@code Subspace}'s prefix {@link Tuple} and
* {@code raw prefix} removed.

View File

@ -304,7 +304,7 @@ public class Tuple implements Comparable<Tuple>, Iterable<Object> {
public byte[] pack(byte[] prefix) {
TupleUtil.EncodeResult encoded = TupleUtil.pack(elements, prefix);
if(encoded.versionPos > 0) {
throw new IllegalStateException("Incomplete Versionstamp included in vanilla tuple pack");
throw new IllegalArgumentException("Incomplete Versionstamp included in vanilla tuple pack");
}
return encoded.data;
}
@ -316,6 +316,7 @@ public class Tuple implements Comparable<Tuple>, Iterable<Object> {
* but it does not add any prefix to the array.
*
* @return a serialized representation of this {@code Tuple} for use with versionstamp ops.
* @throws IllegalArgumentException if there is not exactly one incomplete {@link Versionstamp} included in this {@code Tuple}
*/
public byte[] packWithVersionstamp() {
return packWithVersionstamp(null);
@ -330,17 +331,18 @@ public class Tuple implements Comparable<Tuple>, Iterable<Object> {
* is then prepended to the array, and then the index of the serialized incomplete
* {@link Versionstamp} is appended as a little-endian integer. This can then be passed
* as the key to
* {@link com.apple.cie.foundationdb.Transaction#mutate(com.apple.cie.foundationdb.MutationType, byte[], byte[]) Transaction.mutate}
* {@link com.apple.cie.foundationdb.Transaction#mutate(com.apple.cie.foundationdb.MutationType, byte[], byte[]) Transaction.mutate()}
* with the {@code SET_VERSIONSTAMPED_KEY} {@link com.apple.cie.foundationdb.MutationType}, and the transaction's
* version will then be filled in at commit time.
*
* @param prefix additional byte-array prefix to prepend to serialized bytes.
* @return a serialized representation of this {@code Tuple} for use with versionstamp ops.
* @throws IllegalArgumentException if there is not exactly one incomplete {@link Versionstamp} included in this {@code Tuple}
*/
public byte[] packWithVersionstamp(byte[] prefix) {
TupleUtil.EncodeResult encoded = TupleUtil.pack(elements, prefix);
if(encoded.versionPos < 0) {
throw new IllegalStateException("No incomplete Versionstamp included in tuple pack with versionstamp");
throw new IllegalArgumentException("No incomplete Versionstamp included in tuple pack with versionstamp");
}
return ByteBuffer.allocate(encoded.data.length + 2).order(ByteOrder.LITTLE_ENDIAN)
.put(encoded.data)

View File

@ -312,7 +312,7 @@ class TupleUtil {
EncodeResult childResult = encode(t, true);
if(childResult.versionPos > 0) {
if(versionPos > 0) {
throw new IllegalStateException("Multiple incomplete Versionstamps included in Tuple");
throw new IllegalArgumentException("Multiple incomplete Versionstamps included in Tuple");
}
versionPos = lenSoFar + childResult.versionPos;
}
@ -529,7 +529,7 @@ class TupleUtil {
EncodeResult result = encode(t);
if(result.versionPos > 0) {
if(versionPos > 0) {
throw new IllegalStateException("Multiple incomplete Versionstamps included in Tuple");
throw new IllegalArgumentException("Multiple incomplete Versionstamps included in Tuple");
}
versionPos = result.versionPos + lenSoFar;
}

View File

@ -488,11 +488,16 @@ public class AsyncStackTester {
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.fromItems(elements).packWithVersionstamp(prefix);
byte[] coded = tuple.packWithVersionstamp(prefix);
inst.push("OK".getBytes());
inst.push(coded);
} catch(IllegalStateException e) {
} catch(IllegalArgumentException e) {
if(e.getMessage().startsWith("No incomplete")) {
inst.push("ERROR: NONE".getBytes());
} else {

View File

@ -342,16 +342,20 @@ public class StackTester {
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");
List<Object> elements = inst.popParams(tupleSize).join();
try {
byte[] coded = Tuple.fromItems(elements).packWithVersionstamp(prefix);
inst.push("OK".getBytes());
inst.push(coded);
} catch(IllegalStateException e) {
if(e.getMessage().startsWith("No incomplete")) {
inst.push("ERROR: NONE".getBytes());
} else {
inst.push("ERROR: MULTIPLE".getBytes());
Tuple tuple = Tuple.fromItems(inst.popParams(tupleSize).join());
if(!tuple.hasIncompleteVersionstamp() && Math.random() < 0.5) {
inst.push("ERROR: NONE".getBytes());
} else {
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());
}
}
}
}

View File

@ -28,6 +28,7 @@ import java.util.Arrays;
import com.apple.cie.foundationdb.Range;
import com.apple.cie.foundationdb.tuple.ByteArrayUtil;
import com.apple.cie.foundationdb.tuple.Tuple;
import com.apple.cie.foundationdb.tuple.Versionstamp;
/**
* {@code Subspace} provide a convenient way to use {@link Tuple}s to define namespaces for
@ -60,8 +61,11 @@ public class Subspace
/**
* Constructor for a subspace formed with the specified prefix {@link Tuple}.
* Note that the {@link Tuple} {@code prefix} should not contain any incomplete
* {@link Versionstamp}s as any of its entries.
*
* @param prefix a {@link Tuple} used to form the subspace
* @throws IllegalArgumentException if {@code prefix} contains any incomplete {@link Versionstamp}s
*/
public Subspace(Tuple prefix) {
this(prefix, EMPTY_BYTES);
@ -81,10 +85,12 @@ public class Subspace
* Constructor for a subspace formed with both a prefix {@link Tuple} and a
* prefix byte string. The prefix {@code Tuple} will be prepended to all
* {@code Tuples} packed by the {@code Subspace}, and the byte string prefix
* will be prepended to the packed result.
* will be prepended to the packed result. Note that the {@link Tuple} {@code prefix}
* should not contain any incomplete {@link Versionstamp}s as any of its entries.
*
* @param prefix a {@code Tuple} used to form the subspace
* @param rawPrefix a byte array used as the prefix for all packed keys
* @throws IllegalArgumentException if {@code prefix} contains any incomplete {@link Versionstamp}s
*/
public Subspace(Tuple prefix, byte[] rawPrefix) {
this.rawPrefix = join(rawPrefix, prefix.pack());
@ -178,7 +184,25 @@ public class Subspace
* @return the key encoding the specified tuple in this {@code Subspace}
*/
public byte[] pack(Tuple tuple) {
return join(rawPrefix, tuple.pack());
return tuple.pack(rawPrefix);
}
/**
* Gets the key encoding the specified tuple in this {@code Subspace} for use with
* {@link com.apple.cie.foundationdb.MutationType#SET_VERSIONSTAMPED_KEY MutationType.SET_VERSIONSTAMPED_KEY}.
* There must be exactly one incomplete {@link Versionstamp} included in the given {@link Tuple}. It will
* create a key that is within this {@code Subspace} that can be provided as the {@code key} argument to
* {@link com.apple.cie.foundationdb.Transaction#mutate(com.apple.cie.foundationdb.MutationType, byte[], byte[]) Transaction.mutate()}
* with the {@link com.apple.cie.foundationdb.MutationType#SET_VERSIONSTAMPED_KEY SET_VERSIONSTAMPED_KEY}
* mutation. This will throw an {@link IllegalArgumentException} if the {@link Tuple} does not
* contain an incomplete {@link Versionstamp} or if it contains multiple.
*
* @param tuple the {@code Tuple} to be packed
* @return the key encoding the specified tuple in this {@code Subspace}
* @throws IllegalArgumentException if {@code tuple} does not contain exactly one incomplete {@link Versionstamp}
*/
public byte[] packWithVersionstamp(Tuple tuple) {
return tuple.packWithVersionstamp(rawPrefix);
}
/**

View File

@ -301,7 +301,7 @@ public class Tuple implements Comparable<Tuple>, Iterable<Object> {
public byte[] pack(byte[] prefix) {
TupleUtil.EncodeResult encoded = TupleUtil.pack(elements, prefix);
if(encoded.versionPos > 0) {
throw new IllegalStateException("Incomplete Versionstamp included in vanilla tuple pack");
throw new IllegalArgumentException("Incomplete Versionstamp included in vanilla tuple pack");
}
return encoded.data;
}
@ -328,7 +328,7 @@ public class Tuple implements Comparable<Tuple>, Iterable<Object> {
* is then prepended to the array, and then the index of the serialized incomplete
* {@link Versionstamp} is appended as a little-endian integer. This can then be passed
* as the key to
* {@link com.apple.cie.foundationdb.Transaction#mutate(com.apple.cie.foundationdb.MutationType, byte[], byte[]) Transaction.mutate}
* {@link com.apple.cie.foundationdb.Transaction#mutate(com.apple.cie.foundationdb.MutationType, byte[], byte[]) Transaction.mutate()}
* with the {@code SET_VERSIONSTAMPED_KEY} {@link com.apple.cie.foundationdb.MutationType}, and the transaction's
* version will then be filled in at commit time.
*
@ -339,7 +339,7 @@ public class Tuple implements Comparable<Tuple>, Iterable<Object> {
public byte[] packWithVersionstamp(byte[] prefix) {
TupleUtil.EncodeResult encoded = TupleUtil.pack(elements, prefix);
if(encoded.versionPos < 0) {
throw new IllegalStateException("No incomplete Versionstamp included in tuple pack with versionstamp");
throw new IllegalArgumentException("No incomplete Versionstamp included in tuple pack with versionstamp");
}
return ByteBuffer.allocate(encoded.data.length + 2).order(ByteOrder.LITTLE_ENDIAN)
.put(encoded.data)

View File

@ -535,7 +535,7 @@ class TupleUtil {
EncodeResult result = encode(t);
if(result.versionPos > 0) {
if(versionPos > 0) {
throw new IllegalStateException("Multiple incomplete Versionstamps included in Tuple");
throw new IllegalArgumentException("Multiple incomplete Versionstamps included in Tuple");
}
versionPos = result.versionPos + lenSoFar;
}

View File

@ -36,6 +36,7 @@ import com.apple.cie.foundationdb.Range;
import com.apple.cie.foundationdb.ReadTransaction;
import com.apple.cie.foundationdb.StreamingMode;
import com.apple.cie.foundationdb.Transaction;
import com.apple.cie.foundationdb.async.AsyncUtil;
import com.apple.cie.foundationdb.async.Function;
import com.apple.cie.foundationdb.async.Future;
import com.apple.cie.foundationdb.async.ReadyFuture;
@ -525,12 +526,17 @@ public class AsyncStackTester {
return inst.popParams(tupleSize).flatMap(new Function<List<Object>, Future<Void>>() {
@Override
public Future<Void> apply(List<Object> elements) {
Tuple tuple = Tuple.fromItems(elements);
if(!tuple.hasIncompleteVersionstamp() && Math.random() < 0.5) {
inst.push("ERROR: NONE".getBytes());
return ReadyFuture.DONE;
}
try {
byte[] coded = Tuple.fromItems(elements).packWithVersionstamp(prefix);
byte[] coded = tuple.packWithVersionstamp(prefix);
//System.out.println(inst.context.preStr + " - " + " -> result '" + ByteArrayUtil.printable(coded) + "'");
inst.push("OK".getBytes());
inst.push(coded);
} catch(IllegalStateException e) {
} catch(IllegalArgumentException e) {
//System.out.println(inst.context.preStr + " - " + " -> result '" + e.getMessage() + "'");
if(e.getMessage().startsWith("No incomplete"))
inst.push("ERROR: NONE".getBytes());
@ -737,7 +743,6 @@ public class AsyncStackTester {
}
});
}
}
return logStack(inst.context.db, entries, prefix);

View File

@ -371,16 +371,20 @@ public class StackTester {
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");
List<Object> elements = inst.popParams(tupleSize).get();
try {
byte[] coded = Tuple.fromItems(elements).packWithVersionstamp(prefix);
inst.push("OK".getBytes());
inst.push(coded);
} catch(IllegalStateException e) {
if(e.getMessage().startsWith("No incomplete")) {
inst.push("ERROR: NONE".getBytes());
} else {
inst.push("ERROR: MULTIPLE".getBytes());
Tuple tuple = Tuple.fromItems(inst.popParams(tupleSize).get());
if(!tuple.hasIncompleteVersionstamp() && Math.random() < 0.5) {
inst.push("ERROR: NONE".getBytes());
} else {
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());
}
}
}
//System.out.println(inst.context.preStr + " - " + " -> result '" + ByteArrayUtil.printable(coded) + "'");