Search in sources :

Example 1 with Operation

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;
    }
}
Also used : Operation(org.apache.jackrabbit.oak.plugins.document.UpdateOp.Operation) Key(org.apache.jackrabbit.oak.plugins.document.UpdateOp.Key)

Example 2 with Operation

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());
    }
}
Also used : SQLException(java.sql.SQLException) UpdateOp(org.apache.jackrabbit.oak.plugins.document.UpdateOp) Connection(java.sql.Connection) Stopwatch(com.google.common.base.Stopwatch) Operation(org.apache.jackrabbit.oak.plugins.document.UpdateOp.Operation) CheckForNull(javax.annotation.CheckForNull)

Example 3 with Operation

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;
}
Also used : Utils.resolveCommitRevision(org.apache.jackrabbit.oak.plugins.document.util.Utils.resolveCommitRevision) Operation(org.apache.jackrabbit.oak.plugins.document.UpdateOp.Operation) Map(java.util.Map) NavigableMap(java.util.NavigableMap) SortedMap(java.util.SortedMap) TreeMap(java.util.TreeMap) Key(org.apache.jackrabbit.oak.plugins.document.UpdateOp.Key)

Example 4 with Operation

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);
        }
    }
}
Also used : Operation(org.apache.jackrabbit.oak.plugins.document.UpdateOp.Operation) MemoryDocumentStore(org.apache.jackrabbit.oak.plugins.document.memory.MemoryDocumentStore) Map(java.util.Map) Key(org.apache.jackrabbit.oak.plugins.document.UpdateOp.Key) Test(org.junit.Test)

Example 5 with Operation

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;
                }
        }
    }
}
Also used : Operation(org.apache.jackrabbit.oak.plugins.document.UpdateOp.Operation) TreeMap(java.util.TreeMap) TreeMap(java.util.TreeMap) Map(java.util.Map) Key(org.apache.jackrabbit.oak.plugins.document.UpdateOp.Key)

Aggregations

Operation (org.apache.jackrabbit.oak.plugins.document.UpdateOp.Operation)14 Key (org.apache.jackrabbit.oak.plugins.document.UpdateOp.Key)12 Map (java.util.Map)7 Test (org.junit.Test)6 MemoryDocumentStore (org.apache.jackrabbit.oak.plugins.document.memory.MemoryDocumentStore)4 NodeBuilder (org.apache.jackrabbit.oak.spi.state.NodeBuilder)4 TreeMap (java.util.TreeMap)3 Stopwatch (com.google.common.base.Stopwatch)2 BasicDBObject (com.mongodb.BasicDBObject)2 BulkWriteOperation (com.mongodb.BulkWriteOperation)2 Connection (java.sql.Connection)2 SQLException (java.sql.SQLException)2 SortedMap (java.util.SortedMap)2 Nonnull (javax.annotation.Nonnull)2 CommitFailedException (org.apache.jackrabbit.oak.api.CommitFailedException)2 Revision (org.apache.jackrabbit.oak.plugins.document.Revision)2 UpdateOp (org.apache.jackrabbit.oak.plugins.document.UpdateOp)2 NodeState (org.apache.jackrabbit.oak.spi.state.NodeState)2 DBCollection (com.mongodb.DBCollection)1 DBObject (com.mongodb.DBObject)1