Search in sources :

Example 1 with StaleItemStateException

use of org.apache.jackrabbit.core.state.StaleItemStateException in project jackrabbit by apache.

the class ItemSaveOperation method perform.

public Object perform(SessionContext context) throws RepositoryException {
    SessionItemStateManager stateMgr = context.getItemStateManager();
    /**
         * build list of transient (i.e. new & modified) states that
         * should be persisted
         */
    Collection<ItemState> dirty;
    try {
        dirty = getTransientStates(context.getItemStateManager());
    } catch (ConcurrentModificationException e) {
        String msg = "Concurrent modification; session is closed";
        log.error(msg, e);
        context.getSessionImpl().logout();
        throw e;
    }
    if (dirty.size() == 0) {
        // no transient items, nothing to do here
        return this;
    }
    /**
         * build list of transient descendants in the attic
         * (i.e. those marked as 'removed')
         */
    Collection<ItemState> removed = getRemovedStates(context.getItemStateManager());
    // All affected item states. The keys are used to look up whether
    // an item is affected, and the values are iterated through below
    Map<ItemId, ItemState> affected = new HashMap<ItemId, ItemState>(dirty.size() + removed.size());
    for (ItemState state : dirty) {
        affected.put(state.getId(), state);
    }
    for (ItemState state : removed) {
        affected.put(state.getId(), state);
    }
    /**
         * make sure that this save operation is totally 'self-contained'
         * and independent; items within the scope of this save operation
         * must not have 'external' dependencies;
         * (e.g. moving a node requires that the target node including both
         * old and new parents are saved)
         */
    for (ItemState transientState : affected.values()) {
        if (transientState.isNode()) {
            NodeState nodeState = (NodeState) transientState;
            Set<NodeId> dependentIDs = new HashSet<NodeId>();
            if (nodeState.hasOverlayedState()) {
                NodeState overlayedState = (NodeState) nodeState.getOverlayedState();
                NodeId oldParentId = overlayedState.getParentId();
                NodeId newParentId = nodeState.getParentId();
                if (oldParentId != null) {
                    if (newParentId == null) {
                        // to dependencies
                        if (overlayedState.isShareable()) {
                            dependentIDs.addAll(overlayedState.getSharedSet());
                        } else {
                            dependentIDs.add(oldParentId);
                        }
                    } else {
                        if (!oldParentId.equals(newParentId)) {
                            // node has been moved to a new location,
                            // add old and new parent to dependencies
                            dependentIDs.add(oldParentId);
                            dependentIDs.add(newParentId);
                        } else {
                            // the node has been renamed (JCR-1034)
                            if (!affected.containsKey(newParentId) && stateMgr.hasTransientItemState(newParentId)) {
                                try {
                                    NodeState parent = (NodeState) stateMgr.getTransientItemState(newParentId);
                                    // check parent's renamed child node entries
                                    for (ChildNodeEntry cne : parent.getRenamedChildNodeEntries()) {
                                        if (cne.getId().equals(nodeState.getId())) {
                                            // node has been renamed,
                                            // add parent to dependencies
                                            dependentIDs.add(newParentId);
                                        }
                                    }
                                } catch (ItemStateException ise) {
                                    // should never get here
                                    log.warn("failed to retrieve transient state: " + newParentId, ise);
                                }
                            }
                        }
                    }
                }
            }
            // removed child node entries
            for (ChildNodeEntry cne : nodeState.getRemovedChildNodeEntries()) {
                dependentIDs.add(cne.getId());
            }
            // added child node entries
            for (ChildNodeEntry cne : nodeState.getAddedChildNodeEntries()) {
                dependentIDs.add(cne.getId());
            }
            // are within the scope of this save operation
            for (NodeId id : dependentIDs) {
                if (!affected.containsKey(id)) {
                    // otherwise ignore them
                    if (stateMgr.hasTransientItemState(id) || stateMgr.hasTransientItemStateInAttic(id)) {
                        // need to save dependency as well
                        String msg = context.getItemManager().safeGetJCRPath(id) + " needs to be saved as well.";
                        log.debug(msg);
                        throw new ConstraintViolationException(msg);
                    }
                }
            }
        }
    }
    // validate access and node type constraints
    // (this will also validate child removals)
    validateTransientItems(context, dirty, removed);
    // start the update operation
    try {
        stateMgr.edit();
    } catch (IllegalStateException e) {
        throw new RepositoryException("Unable to start edit operation", e);
    }
    boolean succeeded = false;
    try {
        // process transient items marked as 'removed'
        removeTransientItems(context.getItemStateManager(), removed);
        // process transient items that have change in mixins
        processShareableNodes(context.getRepositoryContext().getNodeTypeRegistry(), dirty);
        // initialize version histories for new nodes (might generate new transient state)
        if (initVersionHistories(context, dirty)) {
            // re-build the list of transient states because the previous call
            // generated new transient state
            dirty = getTransientStates(context.getItemStateManager());
        }
        // process 'new' or 'modified' transient states
        persistTransientItems(context.getItemManager(), dirty);
        // item state which is not referenced by any node instance.
        for (ItemState transientState : dirty) {
            // dispose the transient state, it is no longer used
            stateMgr.disposeTransientItemState(transientState);
        }
        // end update operation
        stateMgr.update();
        // update operation succeeded
        succeeded = true;
    } catch (StaleItemStateException e) {
        throw new InvalidItemStateException("Unable to update a stale item: " + this, e);
    } catch (ItemStateException e) {
        throw new RepositoryException("Unable to update item: " + this, e);
    } finally {
        if (!succeeded) {
            // update operation failed, cancel all modifications
            stateMgr.cancel();
            // JCR-288: if an exception has been thrown during
            // update() the transient changes have already been
            // applied by persistTransientItems() and we need to
            // restore transient state, i.e. undo the effect of
            // persistTransientItems()
            restoreTransientItems(context, dirty);
        }
    }
    // items in store().
    for (ItemState transientState : removed) {
        // dispose the transient state, it is no longer used
        stateMgr.disposeTransientItemStateInAttic(transientState);
    }
    return this;
}
Also used : ConcurrentModificationException(java.util.ConcurrentModificationException) NodeState(org.apache.jackrabbit.core.state.NodeState) HashMap(java.util.HashMap) InvalidItemStateException(javax.jcr.InvalidItemStateException) ChildNodeEntry(org.apache.jackrabbit.core.state.ChildNodeEntry) RepositoryException(javax.jcr.RepositoryException) ItemId(org.apache.jackrabbit.core.id.ItemId) InvalidItemStateException(javax.jcr.InvalidItemStateException) ItemStateException(org.apache.jackrabbit.core.state.ItemStateException) StaleItemStateException(org.apache.jackrabbit.core.state.StaleItemStateException) StaleItemStateException(org.apache.jackrabbit.core.state.StaleItemStateException) ItemState(org.apache.jackrabbit.core.state.ItemState) NodeId(org.apache.jackrabbit.core.id.NodeId) ConstraintViolationException(javax.jcr.nodetype.ConstraintViolationException) SessionItemStateManager(org.apache.jackrabbit.core.state.SessionItemStateManager) HashSet(java.util.HashSet)

Example 2 with StaleItemStateException

use of org.apache.jackrabbit.core.state.StaleItemStateException in project jackrabbit by apache.

the class ConcurrentVersioningWithTransactionsTest method testConcurrentRestoreInTransaction.

public void testConcurrentRestoreInTransaction() throws RepositoryException {
    runTask(new Task() {

        public void execute(Session session, Node test) throws RepositoryException {
            int i = 0;
            try {
                Node n = test.addNode("test");
                n.addMixin(mixVersionable);
                session.save();
                // create 3 version
                List versions = new ArrayList();
                for (i = 0; i < 3; i++) {
                    n.checkout();
                    versions.add(n.checkin());
                }
                // do random restores
                Random rand = new Random();
                for (i = 0; i < NUM_OPERATIONS / CONCURRENCY; i++) {
                    Version v = (Version) versions.get(rand.nextInt(versions.size()));
                    n.restore(v, true);
                }
                n.checkout();
            } catch (Exception e) {
                final String threadName = Thread.currentThread().getName();
                final Throwable deepCause = getLevel2Cause(e);
                if (deepCause != null && deepCause instanceof StaleItemStateException) {
                // ignore
                } else {
                    throw new RepositoryException(threadName + ", i=" + i + ":" + e.getClass().getName(), e);
                }
            }
        }
    }, CONCURRENCY);
}
Also used : Random(java.util.Random) Version(javax.jcr.version.Version) StaleItemStateException(org.apache.jackrabbit.core.state.StaleItemStateException) Node(javax.jcr.Node) ArrayList(java.util.ArrayList) RepositoryException(javax.jcr.RepositoryException) List(java.util.List) ArrayList(java.util.ArrayList) RepositoryException(javax.jcr.RepositoryException) StaleItemStateException(org.apache.jackrabbit.core.state.StaleItemStateException) InvalidItemStateException(javax.jcr.InvalidItemStateException) Session(javax.jcr.Session)

Example 3 with StaleItemStateException

use of org.apache.jackrabbit.core.state.StaleItemStateException in project jackrabbit by apache.

the class ConcurrentLockingWithTransactionsTest method testConcurrentCreateAndLockUnLockInTransaction.

public void testConcurrentCreateAndLockUnLockInTransaction() throws RepositoryException {
    runTask(new Task() {

        public void execute(Session session, Node test) throws RepositoryException {
            // add versionable nodes
            for (int i = 0; i < NUM_OPERATIONS / CONCURRENCY; i++) {
                try {
                    final UserTransaction utx = new UserTransactionImpl(test.getSession());
                    utx.begin();
                    Node n = test.addNode("test" + i);
                    n.addMixin(mixLockable);
                    session.save();
                    Lock l = n.lock(false, true);
                    n.unlock();
                    utx.commit();
                } catch (Exception e) {
                    final String threadName = Thread.currentThread().getName();
                    final Throwable deepCause = getLevel2Cause(e);
                    if (deepCause != null && deepCause instanceof StaleItemStateException) {
                    // ignore
                    } else {
                        throw new RepositoryException(threadName + ", i=" + i + ":" + e.getClass().getName(), e);
                    }
                }
            }
        }
    }, CONCURRENCY);
}
Also used : UserTransaction(javax.transaction.UserTransaction) StaleItemStateException(org.apache.jackrabbit.core.state.StaleItemStateException) Node(javax.jcr.Node) UserTransactionImpl(org.apache.jackrabbit.core.UserTransactionImpl) RepositoryException(javax.jcr.RepositoryException) RepositoryException(javax.jcr.RepositoryException) StaleItemStateException(org.apache.jackrabbit.core.state.StaleItemStateException) Session(javax.jcr.Session) Lock(javax.jcr.lock.Lock)

Example 4 with StaleItemStateException

use of org.apache.jackrabbit.core.state.StaleItemStateException in project jackrabbit by apache.

the class ItemSaveOperation method removeTransientItems.

/**
     * walk through list of transient items marked 'removed' and
     * definitively remove each one
     */
private void removeTransientItems(SessionItemStateManager sism, Iterable<ItemState> states) throws StaleItemStateException {
    for (ItemState transientState : states) {
        ItemState persistentState = transientState.getOverlayedState();
        // permanently invalidate all Item instances wrapping it
        assert persistentState != null;
        if (transientState.getModCount() != persistentState.getModCount()) {
            throw new StaleItemStateException(transientState.getId() + " has been modified externally");
        }
        sism.destroy(persistentState);
    }
}
Also used : StaleItemStateException(org.apache.jackrabbit.core.state.StaleItemStateException) ItemState(org.apache.jackrabbit.core.state.ItemState)

Example 5 with StaleItemStateException

use of org.apache.jackrabbit.core.state.StaleItemStateException in project jackrabbit by apache.

the class ConcurrentLockingWithTransactionsTest method testConcurrentRefreshInTransaction.

public void testConcurrentRefreshInTransaction() throws RepositoryException {
    runTask(new Task() {

        public void execute(Session session, Node test) throws RepositoryException {
            int i = 0;
            try {
                Node n = test.addNode("test");
                n.addMixin(mixLockable);
                session.save();
                for (i = 0; i < NUM_OPERATIONS / CONCURRENCY; i++) {
                    Lock lock = n.lock(false, true);
                    final UserTransaction utx = new UserTransactionImpl(test.getSession());
                    utx.begin();
                    lock.refresh();
                    utx.commit();
                    n.unlock();
                }
            } catch (Exception e) {
                final String threadName = Thread.currentThread().getName();
                final Throwable deepCause = getLevel2Cause(e);
                if (deepCause != null && deepCause instanceof StaleItemStateException) {
                // ignore
                } else {
                    throw new RepositoryException(threadName + ", i=" + i + ":" + e.getClass().getName(), e);
                }
            }
        }
    }, CONCURRENCY);
}
Also used : UserTransaction(javax.transaction.UserTransaction) StaleItemStateException(org.apache.jackrabbit.core.state.StaleItemStateException) Node(javax.jcr.Node) UserTransactionImpl(org.apache.jackrabbit.core.UserTransactionImpl) RepositoryException(javax.jcr.RepositoryException) RepositoryException(javax.jcr.RepositoryException) StaleItemStateException(org.apache.jackrabbit.core.state.StaleItemStateException) Session(javax.jcr.Session) Lock(javax.jcr.lock.Lock)

Aggregations

StaleItemStateException (org.apache.jackrabbit.core.state.StaleItemStateException)5 RepositoryException (javax.jcr.RepositoryException)4 Node (javax.jcr.Node)3 Session (javax.jcr.Session)3 InvalidItemStateException (javax.jcr.InvalidItemStateException)2 Lock (javax.jcr.lock.Lock)2 UserTransaction (javax.transaction.UserTransaction)2 UserTransactionImpl (org.apache.jackrabbit.core.UserTransactionImpl)2 ItemState (org.apache.jackrabbit.core.state.ItemState)2 ArrayList (java.util.ArrayList)1 ConcurrentModificationException (java.util.ConcurrentModificationException)1 HashMap (java.util.HashMap)1 HashSet (java.util.HashSet)1 List (java.util.List)1 Random (java.util.Random)1 ConstraintViolationException (javax.jcr.nodetype.ConstraintViolationException)1 Version (javax.jcr.version.Version)1 ItemId (org.apache.jackrabbit.core.id.ItemId)1 NodeId (org.apache.jackrabbit.core.id.NodeId)1 ChildNodeEntry (org.apache.jackrabbit.core.state.ChildNodeEntry)1