use of org.apache.jackrabbit.oak.plugins.document.UpdateOp.Key in project jackrabbit-oak by apache.
the class UpdateUtils method checkConditions.
public static boolean checkConditions(@Nonnull Document doc, @Nonnull Map<Key, Condition> conditions) {
for (Map.Entry<Key, Condition> entry : conditions.entrySet()) {
Condition c = entry.getValue();
Key k = entry.getKey();
Object value = doc.get(k.getName());
Revision r = k.getRevision();
if (c.type == Condition.Type.EXISTS) {
if (r == null) {
throw new IllegalStateException("EXISTS must not contain null revision");
}
if (value == null) {
if (Boolean.TRUE.equals(c.value)) {
return false;
}
} else {
if (value instanceof Map) {
Map<?, ?> map = (Map<?, ?>) value;
if (Boolean.TRUE.equals(c.value)) {
if (!map.containsKey(r)) {
return false;
}
} else {
if (map.containsKey(r)) {
return false;
}
}
} else {
return false;
}
}
} else if (c.type == Condition.Type.EQUALS || c.type == Condition.Type.NOTEQUALS) {
if (r != null) {
if (value instanceof Map) {
value = ((Map) value).get(r);
} else {
value = null;
}
}
boolean equal = Objects.equal(value, c.value);
if (c.type == Condition.Type.EQUALS && !equal) {
return false;
} else if (c.type == Condition.Type.NOTEQUALS && equal) {
return false;
}
} else {
throw new IllegalArgumentException("Unknown condition: " + c.type);
}
}
return true;
}
use of org.apache.jackrabbit.oak.plugins.document.UpdateOp.Key in project jackrabbit-oak by apache.
the class DocumentSplitTest method cascadingWithSplitRatio.
// OAK-1692
@Test
public void cascadingWithSplitRatio() {
String id = Utils.getIdFromPath("/test");
mk.commit("/", "+\"test\":{}", null, null);
DocumentStore store = mk.getDocumentStore();
int clusterId = mk.getNodeStore().getClusterId();
UpdateOp op = new UpdateOp(id, false);
// create some baggage from another cluster node
for (int i = 0; i < 4000; i++) {
Revision r = Revision.newRevision(2);
op.setMapEntry("prop", r, "some long test value with many characters");
NodeDocument.setRevision(op, r, "c");
}
store.findAndUpdate(NODES, op);
NodeDocument doc = store.find(NODES, id);
assertNotNull(doc);
assertTrue(doc.getMemory() > DOC_SIZE_THRESHOLD);
// some fake previous doc references to trigger UpdateOp
// for an intermediate document
TreeSet<Revision> prev = Sets.newTreeSet(StableRevisionComparator.INSTANCE);
for (int i = 0; i < PREV_SPLIT_FACTOR; i++) {
Revision low = Revision.newRevision(clusterId);
Revision high = Revision.newRevision(clusterId);
prev.add(high);
NodeDocument.setPrevious(op, new Range(high, low, 0));
}
store.findAndUpdate(NODES, op);
doc = store.find(NODES, id);
assertNotNull(doc);
List<UpdateOp> splitOps = Lists.newArrayList(doc.split(mk.getNodeStore(), mk.getNodeStore().getHeadRevision(), NO_BINARY));
assertEquals(2, splitOps.size());
// first update op is for the new intermediate doc
op = splitOps.get(0);
String newPrevId = Utils.getPreviousIdFor("/test", prev.last(), 1);
assertEquals(newPrevId, op.getId());
// second update op is for the main document
op = splitOps.get(1);
assertEquals(id, op.getId());
for (Map.Entry<Key, Operation> entry : op.getChanges().entrySet()) {
Revision r = entry.getKey().getRevision();
assertNotNull(r);
assertEquals(clusterId, r.getClusterId());
if (entry.getKey().getName().equals("_prev")) {
if (entry.getValue().type == REMOVE_MAP_ENTRY) {
assertTrue(prev.contains(r));
} else if (entry.getValue().type == SET_MAP_ENTRY) {
assertEquals(newPrevId, Utils.getPreviousIdFor("/test", r, 1));
} else {
fail("unexpected update operation " + entry);
}
} else {
fail("unexpected update operation " + entry);
}
}
}
use of org.apache.jackrabbit.oak.plugins.document.UpdateOp.Key in project jackrabbit-oak by apache.
the class UpdateUtils method applyChanges.
/**
* Apply the changes to the in-memory document.
*
* @param doc
* the target document.
* @param update
* the changes to apply.
*/
public static void applyChanges(@Nonnull Document doc, @Nonnull UpdateOp update) {
doc.put(Document.ID, update.getId());
for (Entry<Key, Operation> e : checkNotNull(update).getChanges().entrySet()) {
Key k = e.getKey();
Operation op = e.getValue();
switch(op.type) {
case SET:
{
doc.put(k.toString(), op.value);
break;
}
case REMOVE:
{
doc.remove(k.toString());
break;
}
case MAX:
{
Comparable newValue = (Comparable) op.value;
Object old = doc.get(k.toString());
//noinspection unchecked
if (old == null || newValue.compareTo(old) > 0) {
doc.put(k.toString(), op.value);
}
break;
}
case INCREMENT:
{
Object old = doc.get(k.toString());
Long x = (Long) op.value;
if (old == null) {
old = 0L;
}
doc.put(k.toString(), ((Long) old) + x);
break;
}
case SET_MAP_ENTRY:
{
Object old = doc.get(k.getName());
@SuppressWarnings("unchecked") Map<Revision, Object> m = (Map<Revision, Object>) old;
if (m == null) {
m = new TreeMap<Revision, Object>(StableRevisionComparator.REVERSE);
doc.put(k.getName(), m);
}
if (k.getRevision() == null) {
throw new IllegalArgumentException("Cannot set map entry " + k.getName() + " with null revision");
}
m.put(k.getRevision(), op.value);
break;
}
case REMOVE_MAP_ENTRY:
{
Object old = doc.get(k.getName());
@SuppressWarnings("unchecked") Map<Revision, Object> m = (Map<Revision, Object>) old;
if (m != null) {
m.remove(k.getRevision());
}
break;
}
}
}
}
use of org.apache.jackrabbit.oak.plugins.document.UpdateOp.Key in project jackrabbit-oak by apache.
the class RDBDocumentSerializer method asString.
/**
* Serializes the changes in the {@link UpdateOp} into a JSON array; each
* entry is another JSON array holding operation, key, revision, and value.
*/
public String asString(UpdateOp update) {
StringBuilder sb = new StringBuilder("[");
boolean needComma = false;
for (Map.Entry<Key, Operation> change : update.getChanges().entrySet()) {
Operation op = change.getValue();
Key key = change.getKey();
// exclude properties that are serialized into special columns
if (columnProperties.contains(key.getName()) && null == key.getRevision())
continue;
if (needComma) {
sb.append(",");
}
sb.append("[");
if (op.type == UpdateOp.Operation.Type.INCREMENT) {
sb.append("\"+\",");
} else if (op.type == UpdateOp.Operation.Type.SET || op.type == UpdateOp.Operation.Type.SET_MAP_ENTRY) {
sb.append("\"=\",");
} else if (op.type == UpdateOp.Operation.Type.MAX) {
sb.append("\"M\",");
} else if (op.type == UpdateOp.Operation.Type.REMOVE || op.type == UpdateOp.Operation.Type.REMOVE_MAP_ENTRY) {
sb.append("\"*\",");
} else {
throw new DocumentStoreException("Can't serialize " + update.toString() + " for JSON append");
}
appendJsonString(sb, key.getName());
sb.append(",");
Revision rev = key.getRevision();
if (rev != null) {
appendJsonString(sb, rev.toString());
sb.append(",");
}
appendJsonValue(sb, op.value);
sb.append("]");
needComma = true;
}
return sb.append("]").toString();
}
use of org.apache.jackrabbit.oak.plugins.document.UpdateOp.Key in project jackrabbit-oak by apache.
the class MongoDocumentStore method createUpdate.
/**
* Creates a MongoDB update object from the given UpdateOp.
*
* @param updateOp the update op.
* @param includeId whether to include the SET id operation
* @return the DBObject.
*/
@Nonnull
private static DBObject createUpdate(UpdateOp updateOp, boolean includeId) {
BasicDBObject setUpdates = new BasicDBObject();
BasicDBObject maxUpdates = new BasicDBObject();
BasicDBObject incUpdates = new BasicDBObject();
BasicDBObject unsetUpdates = new BasicDBObject();
// always increment modCount
updateOp.increment(Document.MOD_COUNT, 1);
if (includeId) {
setUpdates.append(Document.ID, updateOp.getId());
}
// other updates
for (Entry<Key, Operation> entry : updateOp.getChanges().entrySet()) {
Key k = entry.getKey();
Operation op = entry.getValue();
switch(op.type) {
case SET:
case SET_MAP_ENTRY:
{
setUpdates.append(k.toString(), op.value);
break;
}
case MAX:
{
maxUpdates.append(k.toString(), op.value);
break;
}
case INCREMENT:
{
incUpdates.append(k.toString(), op.value);
break;
}
case REMOVE:
case REMOVE_MAP_ENTRY:
{
unsetUpdates.append(k.toString(), "1");
break;
}
}
}
BasicDBObject update = new BasicDBObject();
if (!setUpdates.isEmpty()) {
update.append("$set", setUpdates);
}
if (!maxUpdates.isEmpty()) {
update.append("$max", maxUpdates);
}
if (!incUpdates.isEmpty()) {
update.append("$inc", incUpdates);
}
if (!unsetUpdates.isEmpty()) {
update.append("$unset", unsetUpdates);
}
return update;
}
Aggregations