use of org.apache.jackrabbit.oak.plugins.document.UpdateOp.Operation in project jackrabbit-oak by apache.
the class RDBDocumentStore method hasChangesToCollisions.
private static boolean hasChangesToCollisions(UpdateOp update) {
if (!USECMODCOUNT) {
return false;
} else {
for (Entry<Key, Operation> e : checkNotNull(update).getChanges().entrySet()) {
Key k = e.getKey();
Operation op = e.getValue();
if (op.type == Operation.Type.SET_MAP_ENTRY) {
if (NodeDocument.COLLISIONS.equals(k.getName())) {
return true;
}
}
}
return false;
}
}
use of org.apache.jackrabbit.oak.plugins.document.UpdateOp.Operation in project jackrabbit-oak by apache.
the class RDBDocumentStore method internalUpdate.
@CheckForNull
private <T extends Document> void internalUpdate(Collection<T> collection, List<String> ids, UpdateOp update) {
if (isAppendableUpdate(update, true) && !requiresPreviousState(update)) {
Operation modOperation = update.getChanges().get(MODIFIEDKEY);
long modified = getModifiedFromOperation(modOperation);
boolean modifiedIsConditional = modOperation == null || modOperation.type != UpdateOp.Operation.Type.SET;
String appendData = ser.asString(update);
for (List<String> chunkedIds : Lists.partition(ids, CHUNKSIZE)) {
if (collection == Collection.NODES) {
for (String key : chunkedIds) {
nodesCache.invalidate(key);
}
}
Connection connection = null;
RDBTableMetaData tmd = getTable(collection);
boolean success = false;
try {
Stopwatch watch = startWatch();
connection = this.ch.getRWConnection();
success = db.batchedAppendingUpdate(connection, tmd, chunkedIds, modified, modifiedIsConditional, appendData);
connection.commit();
//Internally 'db' would make multiple calls and number of those
//remote calls would not be captured
stats.doneUpdate(watch.elapsed(TimeUnit.NANOSECONDS), collection, chunkedIds.size());
} catch (SQLException ex) {
success = false;
this.ch.rollbackConnection(connection);
} finally {
this.ch.closeConnection(connection);
}
if (success) {
if (collection == Collection.NODES) {
for (String id : chunkedIds) {
nodesCache.invalidate(id);
}
}
} else {
for (String id : chunkedIds) {
UpdateOp up = update.copy();
up = up.shallowCopy(id);
internalCreateOrUpdate(collection, up, false, true);
}
}
}
} else {
Stopwatch watch = startWatch();
for (String id : ids) {
UpdateOp up = update.copy();
up = up.shallowCopy(id);
internalCreateOrUpdate(collection, up, false, true);
}
stats.doneUpdate(watch.elapsed(TimeUnit.NANOSECONDS), collection, ids.size());
}
}
use of org.apache.jackrabbit.oak.plugins.document.UpdateOp.Operation in project jackrabbit-oak by apache.
the class NodeDocument method isConflicting.
/**
* Returns <code>true</code> if the given operation is conflicting with this
* document.
*
* @param op the update operation.
* @param baseRevision the base revision for the update operation.
* @param commitRevision the commit revision of the update operation.
* @param enableConcurrentAddRemove feature flag for OAK-2673.
* @return <code>true</code> if conflicting, <code>false</code> otherwise.
*/
boolean isConflicting(@Nonnull UpdateOp op, @Nonnull RevisionVector baseRevision, @Nonnull Revision commitRevision, boolean enableConcurrentAddRemove) {
// did existence of node change after baseRevision?
// only check local deleted map, which contains the most
// recent values
Map<Revision, String> deleted = getLocalDeleted();
boolean allowConflictingDeleteChange = enableConcurrentAddRemove && allowConflictingDeleteChange(op);
for (Map.Entry<Revision, String> entry : deleted.entrySet()) {
if (entry.getKey().equals(commitRevision)) {
continue;
}
if (baseRevision.isRevisionNewer(entry.getKey())) {
boolean newerDeleted = Boolean.parseBoolean(entry.getValue());
if (!allowConflictingDeleteChange || op.isDelete() != newerDeleted) {
return true;
}
}
}
for (Map.Entry<Key, Operation> entry : op.getChanges().entrySet()) {
if (entry.getValue().type != Operation.Type.SET_MAP_ENTRY) {
continue;
}
String name = entry.getKey().getName();
if (DELETED.equals(name) && !allowConflictingDeleteChange) {
// any other concurrent change
return true;
}
if (!Utils.isPropertyName(name)) {
continue;
}
// was this property touched after baseRevision?
for (Revision rev : getChanges(name, baseRevision)) {
if (rev.equals(commitRevision)) {
continue;
}
if (baseRevision.isRevisionNewer(rev)) {
return true;
}
}
}
return false;
}
use of org.apache.jackrabbit.oak.plugins.document.UpdateOp.Operation 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.Operation 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;
}
}
}
}
Aggregations