@Override public boolean offer(E e) { if (e == null) { throw new NullPointerException("Unsupported null value"); } if (!JsonValue.checkType(e)) { throw new IllegalArgumentException("Unsupported value type."); } bucket.mutateIn(id).arrayPrepend("", e, false).execute(); return true; }
@Override public void add(int index, E element) { //fail fast on negative values, as they are interpreted as "starting from the back of the array" otherwise if (index < 0) { throw new IndexOutOfBoundsException("Index: " + index); } if (!JsonValue.checkType(element)) { throw new IllegalArgumentException("Unsupported value type."); } try { bucket.mutateIn(id).arrayInsert("["+index+"]", element).execute(); } catch (MultiMutationException ex) { if (ex.firstFailureStatus() == ResponseStatus.SUBDOC_PATH_NOT_FOUND || ex.firstFailureStatus() == ResponseStatus.SUBDOC_PATH_INVALID) { throw new IndexOutOfBoundsException("Index: " + index); } throw ex; } }
DocumentFragment<Mutation> itrRemoveResult = bucket.mutateIn(id) .withCas(cas) .remove(path)
private void upsertXattrs(String documentId, Map<String, Object> content) { bucket.mutateIn(documentId) .upsert(XATTR_NAME, content, new SubdocOptionsBuilder().xattr(true)) .execute(); }
@Override public V remove(Object key) { if (key == null) { throw new NullPointerException("Unsupported null key"); } String idx = String.valueOf(key); for(int i = 0; i < MAX_OPTIMISTIC_LOCKING_ATTEMPTS; i++) { try { DocumentFragment<Lookup> current = bucket.lookupIn(id).get(idx).execute(); long returnCas = current.cas(); Object result = current.content(idx); DocumentFragment<Mutation> updated = bucket.mutateIn(id).remove(idx).withCas(returnCas).execute(); return (V) result; } catch (CASMismatchException ex) { //will have to retry get-and-remove } catch (MultiMutationException ex) { if (ex.firstFailureStatus() == ResponseStatus.SUBDOC_PATH_NOT_FOUND) { return null; } throw ex; } } throw new ConcurrentModificationException("Couldn't perform remove in less than " + MAX_OPTIMISTIC_LOCKING_ATTEMPTS + " iterations"); }
@Override public V put(String key, V value) { if (key == null) { throw new NullPointerException("Unsupported null key"); } if (!JsonValue.checkType(value)) { throw new IllegalArgumentException("Unsupported value type."); } for(int i = 0; i < MAX_OPTIMISTIC_LOCKING_ATTEMPTS; i++) { try { DocumentFragment<Lookup> current = bucket.lookupIn(id).get(key).execute(); long returnCas = current.cas(); Object result = null; if (current.exists(key)) { result = current.content(key); } bucket.mutateIn(id).upsert(key, value, false).withCas(returnCas).execute(); return (V) result; } catch (CASMismatchException ex) { //will need to retry get-and-set } } throw new ConcurrentModificationException("Couldn't perform put in less than " + MAX_OPTIMISTIC_LOCKING_ATTEMPTS + " iterations"); }
@Override public E remove(int index) { //fail fast on negative values, as they are interpreted as "starting from the back of the array" otherwise if (index < 0) { throw new IndexOutOfBoundsException("Index: " + index); } String idx = "[" + index + "]"; for(int i = 0; i < MAX_OPTIMISTIC_LOCKING_ATTEMPTS; i++) { try { DocumentFragment<Lookup> current = bucket.lookupIn(id).get(idx).execute(); long returnCas = current.cas(); Object result = current.content(idx); DocumentFragment<Mutation> updated = bucket.mutateIn(id).remove(idx).withCas(returnCas).execute(); return (E) result; } catch (CASMismatchException ex) { //will have to retry get-and-remove } catch (MultiMutationException ex) { if (ex.firstFailureStatus() == ResponseStatus.SUBDOC_PATH_NOT_FOUND) { throw new IndexOutOfBoundsException("Index: " + index); } throw ex; } } throw new ConcurrentModificationException("Couldn't perform remove in less than " + MAX_OPTIMISTIC_LOCKING_ATTEMPTS + " iterations"); }
@Override public E set(int index, E element) { //fail fast on negative values, as they are interpreted as "starting from the back of the array" otherwise if (index < 0) { throw new IndexOutOfBoundsException("Index: " + index); } if (!JsonValue.checkType(element)) { throw new IllegalArgumentException("Unsupported value type."); } String idx = "["+index+"]"; for(int i = 0; i < MAX_OPTIMISTIC_LOCKING_ATTEMPTS; i++) { try { DocumentFragment<Lookup> current = bucket.lookupIn(id).get(idx).execute(); long returnCas = current.cas(); Object result = current.content(idx); bucket.mutateIn(id).replace(idx, element).withCas(returnCas).execute(); return (E) result; } catch (CASMismatchException ex) { //will need to retry get-and-set } catch (MultiMutationException ex) { if (ex.firstFailureStatus() == ResponseStatus.SUBDOC_PATH_NOT_FOUND || ex.firstFailureStatus() == ResponseStatus.SUBDOC_PATH_INVALID) { throw new IndexOutOfBoundsException("Index: " + index); } throw ex; } } throw new ConcurrentModificationException("Couldn't perform set in less than " + MAX_OPTIMISTIC_LOCKING_ATTEMPTS + " iterations"); }
} else { DocumentFragment<Mutation> result = bucket .mutateIn(id).remove(path).withCas(cas).execute(); return true;
@Override public E poll() { String idx = "[-1]"; //FIFO queue as offer uses ARRAY_PREPEND for(int i = 0; i < MAX_OPTIMISTIC_LOCKING_ATTEMPTS; i++) { try { DocumentFragment<Lookup> current = bucket.lookupIn(id).get(idx).execute(); long returnCas = current.cas(); Object result = current.content(idx); DocumentFragment<Mutation> updated = bucket.mutateIn(id).remove(idx).withCas(returnCas).execute(); return (E) result; } catch (CASMismatchException ex) { //will have to retry get-and-remove } catch (MultiMutationException ex) { if (ex.firstFailureStatus() == ResponseStatus.SUBDOC_PATH_NOT_FOUND) { return null; //the queue is empty } throw ex; } } throw new ConcurrentModificationException("Couldn't perform poll in less than " + MAX_OPTIMISTIC_LOCKING_ATTEMPTS + " iterations"); }
@Override public boolean add(T t) { enforcePrimitive(t); for (int i = 0; i < MAX_OPTIMISTIC_LOCKING_ATTEMPTS; i++) { try { JsonArrayDocument current = bucket.get(id, JsonArrayDocument.class); long cas = current.cas(); //Care not to use toList, as it will convert internal JsonObject/JsonArray to Map/List boolean absent = true; for (Object in : current.content()) { if (safeEquals(in, t)) { absent = false; break; } } if (absent) { DocumentFragment<Mutation> result = bucket.mutateIn(id) .arrayAppend("", t, true) //append at the root array .withCas(cas) .execute(); return true; } else { return false; } } catch (CASMismatchException e) { //retry } } throw new ConcurrentModificationException("Couldn't perform add in less than " + MAX_OPTIMISTIC_LOCKING_ATTEMPTS + " iterations"); }