Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 124 additions & 0 deletions src/main/java/net/spy/memcached/v2/AsyncArcusCommands.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@
import net.spy.memcached.collection.CollectionUpdate;
import net.spy.memcached.collection.ElementFlagFilter;
import net.spy.memcached.collection.ElementValueType;
import net.spy.memcached.collection.ListCreate;
import net.spy.memcached.collection.ListDelete;
import net.spy.memcached.collection.ListGet;
import net.spy.memcached.collection.ListInsert;
import net.spy.memcached.internal.result.GetsResultImpl;
import net.spy.memcached.ops.APIType;
import net.spy.memcached.ops.BTreeGetBulkOperation;
Expand All @@ -83,6 +87,7 @@
import net.spy.memcached.v2.vo.BTreeUpdateElement;
import net.spy.memcached.v2.vo.BopDeleteArgs;
import net.spy.memcached.v2.vo.BopGetArgs;
import net.spy.memcached.v2.vo.GetArgs;
import net.spy.memcached.v2.vo.SMGetElements;

public class AsyncArcusCommands<T> implements AsyncArcusCommandsIF<T> {
Expand Down Expand Up @@ -1536,4 +1541,123 @@ public void complete() {

return future;
}

public ArcusFuture<Boolean> lopCreate(String key, ElementValueType type,
CollectionAttributes attributes) {
if (attributes == null) {
throw new IllegalArgumentException("CollectionAttributes cannot be null");
}

ListCreate create = new ListCreate(TranscoderUtils.examineFlags(type),
attributes.getExpireTime(), attributes.getMaxCount(),
attributes.getOverflowAction(), attributes.getReadable(), false);
return collectionCreate(key, create);
}

public ArcusFuture<Boolean> lopInsert(String key, int index, T value) {
return lopInsert(key, index, value, null);
}

public ArcusFuture<Boolean> lopInsert(String key, int index, T value,
CollectionAttributes attributes) {
ListInsert<T> insert = new ListInsert<>(value, null, attributes);
return collectionInsert(key, String.valueOf(index), insert);
}

public ArcusFuture<T> lopGet(String key, int index, GetArgs args) {
AbstractArcusResult<T> result = new AbstractArcusResult<>(new AtomicReference<>());
ArcusFutureImpl<T> future = new ArcusFutureImpl<>(result);
ListGet get = new ListGet(index, args.isWithDelete(), args.isDropIfEmpty());
ArcusClient client = arcusClientSupplier.get();

CollectionGetOperation.Callback cb = new CollectionGetOperation.Callback() {
@Override
public void receivedStatus(OperationStatus status) {
switch (status.getStatusCode()) {
case SUCCESS:
break;
case ERR_NOT_FOUND:
case ERR_NOT_FOUND_ELEMENT:
result.set(null);
break;
case CANCELLED:
future.internalCancel();
break;
default:
/* TYPE_MISMATCH / UNREADABLE / NOT_SUPPORTED or unknown statement */
result.addError(key, status);
}
}

@Override
public void complete() {
future.complete();
}

@Override
public void gotData(String subKey, int flags, byte[] data, byte[] eFlag) {
CachedData cachedData = new CachedData(flags, data, tcForCollection.getMaxSize());
result.set(tcForCollection.decode(cachedData));
}
};
Operation op = client.getOpFact().collectionGet(key, get, cb);
future.setOp(op);
client.addOp(key, op);

return future;
}

public ArcusFuture<List<T>> lopGet(String key, int from, int to, GetArgs args) {
AbstractArcusResult<List<T>> result =
new AbstractArcusResult<>(new AtomicReference<>(new ArrayList<>()));
ArcusFutureImpl<List<T>> future = new ArcusFutureImpl<>(result);
ListGet get = new ListGet(from, to, args.isWithDelete(), args.isDropIfEmpty());
ArcusClient client = arcusClientSupplier.get();

CollectionGetOperation.Callback cb = new CollectionGetOperation.Callback() {
@Override
public void receivedStatus(OperationStatus status) {
switch (status.getStatusCode()) {
case SUCCESS:
case ERR_NOT_FOUND_ELEMENT:
break;
case ERR_NOT_FOUND:
result.set(null);
break;
case CANCELLED:
future.internalCancel();
break;
default:
/* TYPE_MISMATCH / UNREADABLE / NOT_SUPPORTED or unknown statement */
result.addError(key, status);
}
}

@Override
public void complete() {
future.complete();
}

@Override
public void gotData(String subKey, int flags, byte[] data, byte[] eFlag) {
CachedData cachedData = new CachedData(flags, data, tcForCollection.getMaxSize());
result.get().add(tcForCollection.decode(cachedData));
}
};
Operation op = client.getOpFact().collectionGet(key, get, cb);
future.setOp(op);
client.addOp(key, op);

return future;
}

public ArcusFuture<Boolean> lopDelete(String key, int index, boolean dropIfEmpty) {
ListDelete delete = new ListDelete(index, dropIfEmpty, false);
return collectionDelete(key, delete);
}

public ArcusFuture<Boolean> lopDelete(String key, int from, int to, boolean dropIfEmpty) {
ListDelete delete = new ListDelete(from, to, dropIfEmpty, false);
return collectionDelete(key, delete);
}
}
89 changes: 84 additions & 5 deletions src/main/java/net/spy/memcached/v2/AsyncArcusCommandsIF.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import net.spy.memcached.v2.vo.BTreeUpdateElement;
import net.spy.memcached.v2.vo.BopDeleteArgs;
import net.spy.memcached.v2.vo.BopGetArgs;
import net.spy.memcached.v2.vo.GetArgs;
import net.spy.memcached.v2.vo.SMGetElements;

public interface AsyncArcusCommandsIF<T> {
Expand Down Expand Up @@ -73,7 +74,7 @@ public interface AsyncArcusCommandsIF<T> {
* @param value the new value to set if the CAS ID matches
* @param casId the CAS ID obtained from {@link #gets(String)}
* @return {@code Boolean.True} if compared and set successfully,
* {@code Boolean.False} if the key does not exist or CAS ID does not match
* {@code Boolean.False} if the key does not exist or CAS ID does not match
*/
ArcusFuture<Boolean> cas(String key, int exp, T value, long casId);

Expand All @@ -99,7 +100,7 @@ public interface AsyncArcusCommandsIF<T> {
* Sets multiple key-value pairs.
*
* @param items map of keys and values to store
* @param exp expiration time in seconds
* @param exp expiration time in seconds
* @return Map of key to Boolean result
*/
ArcusFuture<Map<String, Boolean>> multiSet(Map<String, T> items, int exp);
Expand All @@ -108,7 +109,7 @@ public interface AsyncArcusCommandsIF<T> {
* Add multiple key-value pairs if they do not exist.
*
* @param items map of keys and values to store
* @param exp expiration time in seconds
* @param exp expiration time in seconds
* @return Map of key to Boolean result
*/
ArcusFuture<Map<String, Boolean>> multiAdd(Map<String, T> items, int exp);
Expand All @@ -117,7 +118,7 @@ public interface AsyncArcusCommandsIF<T> {
* Replace multiple key-value pairs if they exist.
*
* @param items map of keys and values to store
* @param exp expiration time in seconds
* @param exp expiration time in seconds
* @return Map of key to Boolean result
*/
ArcusFuture<Map<String, Boolean>> multiReplace(Map<String, T> items, int exp);
Expand Down Expand Up @@ -431,7 +432,7 @@ ArcusFuture<SMGetElements<T>> bopSortMergeGet(List<String> keys, BKey from, BKey
* ({@code delta} is ignored) (&ge; 0)
* @param eFlag eFlag of the element to create, or {@code null} if not needed
* @return the new value after decrement,
* or {@code initial} if the element did not exist.
* or {@code initial} if the element did not exist.
*/
ArcusFuture<Long> bopDecr(String key, BKey bKey, int delta, long initial, byte[] eFlag);

Expand Down Expand Up @@ -475,4 +476,82 @@ ArcusFuture<SMGetElements<T>> bopSortMergeGet(List<String> keys, BKey from, BKey
* or {@code null} if the key is not found.
*/
ArcusFuture<Long> bopCount(String key, BKey from, BKey to, ElementFlagFilter eFlagFilter);

/**
* Create a list with the given attributes.
*
* @param key key of the list to create
* @param type element value type
* @param attributes initial attributes of the list
* @return {@code true} if created, {@code false} if the key already exists.
*/
ArcusFuture<Boolean> lopCreate(String key, ElementValueType type,
CollectionAttributes attributes);

/**
* Insert an element at the given index into a list.
*
* @param key key of the list
* @param index index at which to insert the element
* @param value the value to insert
* @return {@code true} if the element was inserted, {@code null} if the key is not found.
*/
ArcusFuture<Boolean> lopInsert(String key, int index, T value);

/**
* Insert an element at the given index into a list.
* If the list does not exist, it is created with the given attributes.
*
* @param key key of the list
* @param index index at which to insert the element
* @param value the value to insert
* @param attributes attributes to use when creating the list, or {@code null} to not create
* @return {@code true} if the element was inserted, {@code null} if the key is not found.
*/
ArcusFuture<Boolean> lopInsert(String key, int index, T value, CollectionAttributes attributes);

/**
* Get an element at the given index from a list.
*
* @param key key of the list
* @param index index of the element to get
* @param args arguments for get operation
* @return the element value, {@code null} if the key or element is not found.
*/
ArcusFuture<T> lopGet(String key, int index, GetArgs args);

/**
* Get elements in an index range from a list.
*
* @param key key of the list
* @param from index range start (inclusive)
* @param to index range end (inclusive)
* @param args arguments for get operation
* @return list of element values in order, an empty list if no elements are found in the range,
* {@code null} if the key is not found.
*/
ArcusFuture<List<T>> lopGet(String key, int from, int to, GetArgs args);

/**
* Delete an element at the given index from a list.
*
* @param key key of the list
* @param index index of the element to delete
* @param dropIfEmpty whether to delete the list if it becomes empty after deletion
* @return {@code true} if the element was deleted, {@code null} if the key is not found,
* {@code false} if the element is not found.
*/
ArcusFuture<Boolean> lopDelete(String key, int index, boolean dropIfEmpty);

/**
* Delete elements in an index range from a list.
*
* @param key key of the list
* @param from index range start (inclusive)
* @param to index range end (inclusive)
* @param dropIfEmpty whether to delete the list if it becomes empty after deletion
* @return {@code true} if at least one element was deleted, {@code null} if the key is not found,
* {@code false} if no elements are found in the range.
*/
ArcusFuture<Boolean> lopDelete(String key, int from, int to, boolean dropIfEmpty);
}
42 changes: 42 additions & 0 deletions src/main/java/net/spy/memcached/v2/vo/GetArgs.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package net.spy.memcached.v2.vo;

public final class GetArgs {

public static final GetArgs DEFAULT = new GetArgs.Builder().build();

private final boolean withDelete;
private final boolean dropIfEmpty;

public boolean isWithDelete() {
return withDelete;
}

public boolean isDropIfEmpty() {
return dropIfEmpty;
}

private GetArgs(boolean withDelete, boolean dropIfEmpty) {
this.withDelete = withDelete;
this.dropIfEmpty = dropIfEmpty;
}

public static class Builder {
private boolean withDelete = false;
private boolean dropIfEmpty = false;

public Builder withDelete() {
this.withDelete = true;
return this;
}

public Builder dropIfEmpty() {
this.dropIfEmpty = true;
return this;
}

public GetArgs build() {
return new GetArgs(withDelete, dropIfEmpty);
}
}

}
Loading
Loading