use of java.util.ConcurrentModificationException 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;
}
use of java.util.ConcurrentModificationException in project jackrabbit by apache.
the class VersionIteratorImpl method nextVersion.
/**
* {@inheritDoc}
*/
public Version nextVersion() {
if (versions.isEmpty()) {
throw new NoSuchElementException();
}
NodeId id = versions.removeFirst();
pos++;
try {
return (Version) session.getNodeById(id);
} catch (RepositoryException e) {
throw new ConcurrentModificationException("Unable to provide element: " + e.toString());
}
}
use of java.util.ConcurrentModificationException in project hazelcast by hazelcast.
the class TransactionalMultiMapProxySupport method removeAllInternal.
Collection<MultiMapRecord> removeAllInternal(Data key) {
checkObjectNotNull(key);
long timeout = tx.getTimeoutMillis();
long ttl = extendTimeout(timeout);
Collection<MultiMapRecord> coll = txMap.get(key);
MultiMapTransactionLogRecord logRecord;
if (coll == null) {
MultiMapResponse response = lockAndGet(key, timeout, ttl);
if (response == null) {
throw new ConcurrentModificationException("Transaction couldn't obtain lock " + getThreadId());
}
coll = createCollection(response.getRecordCollection(getNodeEngine()));
logRecord = new MultiMapTransactionLogRecord(getPartitionId(key), key, name, ttl, getThreadId());
tx.add(logRecord);
} else {
logRecord = (MultiMapTransactionLogRecord) tx.get(getRecordLogKey(key));
}
txMap.put(key, createCollection());
TxnRemoveAllOperation operation = new TxnRemoveAllOperation(name, key, coll);
logRecord.addOperation(operation);
return coll;
}
use of java.util.ConcurrentModificationException in project hazelcast by hazelcast.
the class TransactionalMultiMapProxySupport method putInternal.
boolean putInternal(Data key, Data value) {
checkObjectNotNull(key);
checkObjectNotNull(value);
Collection<MultiMapRecord> coll = txMap.get(key);
long recordId = -1;
long timeout = tx.getTimeoutMillis();
long ttl = extendTimeout(timeout);
MultiMapTransactionLogRecord logRecord;
if (coll == null) {
MultiMapResponse response = lockAndGet(key, timeout, ttl);
if (response == null) {
throw new ConcurrentModificationException("Transaction couldn't obtain lock " + getThreadId());
}
recordId = response.getNextRecordId();
coll = createCollection(response.getRecordCollection(getNodeEngine()));
txMap.put(key, coll);
logRecord = new MultiMapTransactionLogRecord(getPartitionId(key), key, name, ttl, getThreadId());
tx.add(logRecord);
} else {
logRecord = (MultiMapTransactionLogRecord) tx.get(getRecordLogKey(key));
}
MultiMapRecord record = new MultiMapRecord(config.isBinary() ? value : toObjectIfNeeded(value));
if (coll.add(record)) {
if (recordId == -1) {
recordId = nextId(key);
}
record.setRecordId(recordId);
TxnPutOperation operation = new TxnPutOperation(name, key, value, recordId);
logRecord.addOperation(operation);
return true;
}
return false;
}
use of java.util.ConcurrentModificationException in project hazelcast by hazelcast.
the class TransactionalMultiMapProxySupport method removeInternal.
boolean removeInternal(Data key, Data value) {
checkObjectNotNull(key);
checkObjectNotNull(value);
Collection<MultiMapRecord> coll = txMap.get(key);
long timeout = tx.getTimeoutMillis();
long ttl = extendTimeout(timeout);
MultiMapTransactionLogRecord logRecord;
if (coll == null) {
MultiMapResponse response = lockAndGet(key, timeout, ttl);
if (response == null) {
throw new ConcurrentModificationException("Transaction couldn't obtain lock " + getThreadId());
}
coll = createCollection(response.getRecordCollection(getNodeEngine()));
txMap.put(key, coll);
logRecord = new MultiMapTransactionLogRecord(getPartitionId(key), key, name, ttl, getThreadId());
tx.add(logRecord);
} else {
logRecord = (MultiMapTransactionLogRecord) tx.get(getRecordLogKey(key));
}
MultiMapRecord record = new MultiMapRecord(config.isBinary() ? value : toObjectIfNeeded(value));
Iterator<MultiMapRecord> iterator = coll.iterator();
long recordId = -1;
while (iterator.hasNext()) {
MultiMapRecord r = iterator.next();
if (r.equals(record)) {
iterator.remove();
recordId = r.getRecordId();
break;
}
}
if (recordId != -1) {
TxnRemoveOperation operation = new TxnRemoveOperation(name, key, recordId, value);
logRecord.addOperation(operation);
return true;
}
return false;
}
Aggregations