You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by ju...@apache.org on 2011/09/27 21:55:30 UTC
svn commit: r1176577 - in /jackrabbit/branches/2.2: ./ jackrabbit-core/
jackrabbit-core/src/main/java/org/apache/jackrabbit/core/
jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/
jackrabbit-core/src/main/java/org/apache/jackra...
Author: jukka
Date: Tue Sep 27 19:55:29 2011
New Revision: 1176577
URL: http://svn.apache.org/viewvc?rev=1176577&view=rev
Log:
2.2: Merged revision 1176546 (JCR-2272)
Added:
jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/DummyUpdateEventChannel.java
- copied unchanged from r1176546, jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/DummyUpdateEventChannel.java
Modified:
jackrabbit/branches/2.2/ (props changed)
jackrabbit/branches/2.2/RELEASE-NOTES.txt
jackrabbit/branches/2.2/jackrabbit-core/pom.xml
jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/BatchedItemOperations.java
jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/HierarchyManagerImpl.java
jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemImpl.java
jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemManager.java
jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java
jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/PropertyImpl.java
jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/BundleDbPersistenceManager.java
jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/ItemState.java
jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/LocalItemStateManager.java
jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SessionItemStateManager.java
jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java
jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/UpdatableItemStateManager.java
jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/InternalVersionManagerImpl.java
jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/NodeStateEx.java
jackrabbit/branches/2.2/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ConcurrentImportTest.java
jackrabbit/branches/2.2/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/TestAll.java
jackrabbit/branches/2.2/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/persistence/util/BundleBindingTest.java
Propchange: jackrabbit/branches/2.2/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Tue Sep 27 19:55:29 2011
@@ -1,5 +1,6 @@
/jackrabbit/branches/1.5:794012,794100,794102
+/jackrabbit/branches/JCR-2272:1173165-1176545
/jackrabbit/sandbox/JCR-1456:774917-886178
/jackrabbit/sandbox/JCR-2170:812417-816332
/jackrabbit/sandbox/tripod-JCR-2209:795441-795863
-/jackrabbit/trunk:1038201,1038203,1038205,1038657,1039064,1039347,1039408,1039422-1039423,1039888,1039946,1040033,1040090,1040459,1040601,1040606,1040661,1040958,1041379,1041439,1041761,1042643,1042647,1042978-1042982,1043084-1043086,1043088,1043343,1043357-1043358,1043430,1043554,1043616,1043618,1043637,1043656,1043893,1043897,1044239,1044312,1044451,1044613,1049473,1049491,1049514,1049518,1049520,1049859,1049870,1049874,1049878,1049880,1049883,1049889,1049891,1049894-1049895,1049899-1049901,1049909-1049911,1049915-1049916,1049919,1049923,1049925,1049931,1049936,1049939,1050212,1050298,1050346,1050551,1055068,1055070-1055071,1055116-1055117,1055127,1055134,1055164,1055498,1060431,1060434,1060753,1063756,1064670,1065599,1065622,1066059,1066071,1069831,1071562,1071573,1071680,1074140,1079314,1079317,1080186,1080540,1087304,1088991,1089032,1089053,1089436,1092106,1092117,1092683,1097363,1097513-1097514,1098963-1098964,1099033,1099172,1100242,1100286,1101046,1102601,1104027,112
8175,1130192,1130228,1132993,1136353,1136360,1138511,1141141,1141717,1143396,1143738,1144332,1144338,1144695,1152258,1155431,1157175,1165609,1173196,1174822,1174887,1176423,1176465,1176515
+/jackrabbit/trunk:1038201,1038203,1038205,1038657,1039064,1039347,1039408,1039422-1039423,1039888,1039946,1040033,1040090,1040459,1040601,1040606,1040661,1040958,1041379,1041439,1041761,1042643,1042647,1042978-1042982,1043084-1043086,1043088,1043343,1043357-1043358,1043430,1043554,1043616,1043618,1043637,1043656,1043893,1043897,1044239,1044312,1044451,1044613,1049473,1049491,1049514,1049518,1049520,1049859,1049870,1049874,1049878,1049880,1049883,1049889,1049891,1049894-1049895,1049899-1049901,1049909-1049911,1049915-1049916,1049919,1049923,1049925,1049931,1049936,1049939,1050212,1050298,1050346,1050551,1055068,1055070-1055071,1055116-1055117,1055127,1055134,1055164,1055498,1060431,1060434,1060753,1063756,1064670,1065599,1065622,1066059,1066071,1069831,1071562,1071573,1071680,1074140,1079314,1079317,1080186,1080540,1087304,1088991,1089032,1089053,1089436,1092106,1092117,1092683,1097363,1097513-1097514,1098963-1098964,1099033,1099172,1100242,1100286,1101046,1102601,1104027,112
8175,1130192,1130228,1132993,1136353,1136360,1138511,1141141,1141717,1143396,1143738,1144332,1144338,1144695,1152258,1155431,1157175,1165609,1173196,1174822,1174887,1176423,1176465,1176515,1176546
Modified: jackrabbit/branches/2.2/RELEASE-NOTES.txt
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/RELEASE-NOTES.txt?rev=1176577&r1=1176576&r2=1176577&view=diff
==============================================================================
--- jackrabbit/branches/2.2/RELEASE-NOTES.txt (original)
+++ jackrabbit/branches/2.2/RELEASE-NOTES.txt Tue Sep 27 19:55:29 2011
@@ -26,6 +26,7 @@ Changes in this release
Bug fixes
+ [JCR-2272] Errors during concurrent session import of nodes with same UUIDs
[JCR-2962] InputStream not being explicitly closed
[JCR-2967] SessionItemStateManager.getIdOfRootTransientNodeState() ...
[JCR-2969] FileDataStore garbage collection can throw a ...
Modified: jackrabbit/branches/2.2/jackrabbit-core/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/pom.xml?rev=1176577&r1=1176576&r2=1176577&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/pom.xml (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/pom.xml Tue Sep 27 19:55:29 2011
@@ -100,7 +100,6 @@
<name>known.issues</name>
<value>
org.apache.jackrabbit.core.xml.DocumentViewTest#testMultiValue
-org.apache.jackrabbit.core.ConcurrentImportTest
org.apache.jackrabbit.core.data.GarbageCollectorTest#testGC
org.apache.jackrabbit.core.data.GarbageCollectorTest#testCloseSessionWhileRunningGc
org.apache.jackrabbit.core.integration.ConcurrentQueryTest#testConcurrentQueryWithDeletes
Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/BatchedItemOperations.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/BatchedItemOperations.java?rev=1176577&r1=1176576&r2=1176577&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/BatchedItemOperations.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/BatchedItemOperations.java Tue Sep 27 19:55:29 2011
@@ -1101,10 +1101,6 @@ public class BatchedItemOperations exten
NodeId errorId = parent.getChildNodeEntry(nodeName, 1).getId();
throw new ItemExistsException(safeGetJCRPath(errorId));
}
- if (id == null) {
- // create new id
- id = new NodeId();
- }
if (nodeTypeName == null) {
// no primary node type specified,
// try default primary type from definition
@@ -1123,7 +1119,7 @@ public class BatchedItemOperations exten
}
// now add new child node entry to parent
- parent.addChildNodeEntry(nodeName, id);
+ parent.addChildNodeEntry(nodeName, node.getNodeId());
EffectiveNodeType ent = getEffectiveNodeType(node);
@@ -1602,7 +1598,7 @@ public class BatchedItemOperations exten
NodeState newState;
try {
- NodeId id;
+ NodeId id = null;
EffectiveNodeType ent = getEffectiveNodeType(srcState);
boolean referenceable = ent.includesNodeType(NameConstants.MIX_REFERENCEABLE);
boolean versionable = ent.includesNodeType(NameConstants.MIX_SIMPLE_VERSIONABLE);
@@ -1620,17 +1616,10 @@ public class BatchedItemOperations exten
sharedState.addShare(destParentId);
return sharedState;
}
- // always create new uuid
- id = new NodeId();
- if (referenceable) {
- // remember uuid mapping
- refTracker.mappedId(srcState.getNodeId(), id);
- }
break;
case CLONE:
if (!referenceable) {
// non-referenceable node: always create new uuid
- id = new NodeId();
break;
}
// use same uuid as source node
@@ -1649,7 +1638,6 @@ public class BatchedItemOperations exten
case CLONE_REMOVE_EXISTING:
if (!referenceable) {
// non-referenceable node: always create new uuid
- id = new NodeId();
break;
}
// use same uuid as source node
@@ -1686,6 +1674,11 @@ public class BatchedItemOperations exten
"unknown flag for copying node state: " + flag);
}
newState = stateMgr.createNew(id, srcState.getNodeTypeName(), destParentId);
+ id = newState.getNodeId();
+ if (flag == COPY && referenceable) {
+ // remember uuid mapping
+ refTracker.mappedId(srcState.getNodeId(), id);
+ }
// copy node state
newState.setMixinTypeNames(srcState.getMixinTypeNames());
if (shareable) {
Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/HierarchyManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/HierarchyManagerImpl.java?rev=1176577&r1=1176576&r2=1176577&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/HierarchyManagerImpl.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/HierarchyManagerImpl.java Tue Sep 27 19:55:29 2011
@@ -464,7 +464,7 @@ public class HierarchyManagerImpl implem
if (entry == null) {
String msg = "failed to resolve name of " + id;
log.debug(msg);
- throw new RepositoryException(msg);
+ throw new ItemNotFoundException(msg);
}
return entry.getName();
}
Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemImpl.java?rev=1176577&r1=1176576&r2=1176577&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemImpl.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemImpl.java Tue Sep 27 19:55:29 2011
@@ -124,7 +124,7 @@ public abstract class ItemImpl implement
protected abstract ItemState getOrCreateTransientItemState() throws RepositoryException;
- protected abstract void makePersistent() throws InvalidItemStateException;
+ protected abstract void makePersistent() throws RepositoryException;
/**
* Marks this instance as 'removed' and notifies its listeners.
Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemManager.java?rev=1176577&r1=1176576&r2=1176577&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemManager.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemManager.java Tue Sep 27 19:55:29 2011
@@ -1105,7 +1105,6 @@ public class ItemManager implements Item
itemDestroyed(destroyed.getId(), data);
data.setStatus(ItemImpl.STATUS_DESTROYED);
- data.setState(null);
}
}
Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java?rev=1176577&r1=1176576&r2=1176577&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java Tue Sep 27 19:55:29 2011
@@ -499,19 +499,8 @@ public class NodeImpl extends ItemImpl i
NodeId id)
throws RepositoryException {
// create a new node state
- NodeState nodeState;
- try {
- if (id == null) {
- id = new NodeId();
- }
- nodeState =
- stateMgr.createTransientNodeState(id, nodeType.getQName(),
- getNodeId(), ItemState.STATUS_NEW);
- } catch (ItemStateException ise) {
- String msg = "failed to add child node " + name + " to " + this;
- log.debug(msg);
- throw new RepositoryException(msg, ise);
- }
+ NodeState nodeState = stateMgr.createTransientNodeState(
+ id, nodeType.getQName(), getNodeId(), ItemState.STATUS_NEW);
// create Node instance wrapping new node state
NodeImpl node;
@@ -850,29 +839,15 @@ public class NodeImpl extends ItemImpl i
return sessionContext.getNodeTypeManager().getPropertyDefinition(pd);
}
- protected void makePersistent() throws InvalidItemStateException {
+ protected void makePersistent() throws RepositoryException {
if (!isTransient()) {
log.debug(this + " (" + id + "): there's no transient state to persist");
return;
}
NodeState transientState = data.getNodeState();
+ NodeState localState = stateMgr.makePersistent(transientState);
- NodeState localState = (NodeState) transientState.getOverlayedState();
- if (localState == null) {
- // this node is 'new'
- localState = stateMgr.createNew(transientState);
- }
-
- synchronized (localState) {
- // copy state from transient state:
- localState.copy(transientState, true);
- // make state persistent
- stateMgr.store(localState);
- }
-
- // tell state manager to disconnect item state
- stateMgr.disconnectTransientItemState(transientState);
// swap transient state with local state
data.setState(localState);
// reset status
@@ -900,16 +875,12 @@ public class NodeImpl extends ItemImpl i
// JCR-2503: Re-create transient state in the state manager,
// because it was removed
synchronized (data) {
- try {
- thisState = stateMgr.createTransientNodeState(
- (NodeId) transientState.getId(),
- transientState.getNodeTypeName(),
- transientState.getParentId(),
- NodeState.STATUS_NEW);
- data.setState(thisState);
- } catch (ItemStateException e) {
- throw new RepositoryException(e);
- }
+ thisState = stateMgr.createTransientNodeState(
+ (NodeId) transientState.getId(),
+ transientState.getNodeTypeName(),
+ transientState.getParentId(),
+ NodeState.STATUS_NEW);
+ data.setState(thisState);
}
}
Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/PropertyImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/PropertyImpl.java?rev=1176577&r1=1176576&r2=1176577&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/PropertyImpl.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/PropertyImpl.java Tue Sep 27 19:55:29 2011
@@ -142,7 +142,11 @@ public class PropertyImpl extends ItemIm
PropertyState persistentState = (PropertyState) transientState.getOverlayedState();
if (persistentState == null) {
// this property is 'new'
- persistentState = stateMgr.createNew(transientState);
+ try {
+ persistentState = stateMgr.createNew(transientState);
+ } catch (ItemStateException e) {
+ throw new InvalidItemStateException(e);
+ }
}
synchronized (persistentState) {
Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/BundleDbPersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/BundleDbPersistenceManager.java?rev=1176577&r1=1176576&r2=1176577&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/BundleDbPersistenceManager.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/BundleDbPersistenceManager.java Tue Sep 27 19:55:29 2011
@@ -491,6 +491,10 @@ public class BundleDbPersistenceManager
} catch (SQLException e2) {
DbUtility.logException("rollback failed", e2);
}
+
+ // if we got here due to a constraint violation and we
+ // are running in test mode, we really want to stop
+ assert !isIntegrityConstraintViolation(e.getCause());
}
failures++;
log.error("Failed to persist ChangeLog (stacktrace on DEBUG log level), blockOnConnectionLoss = "
@@ -509,6 +513,15 @@ public class BundleDbPersistenceManager
throw lastException;
}
+ private boolean isIntegrityConstraintViolation(Throwable t) {
+ if (t instanceof SQLException) {
+ String state = ((SQLException) t).getSQLState();
+ return state != null && state.startsWith("23");
+ } else {
+ return false;
+ }
+ }
+
/**
* {@inheritDoc}
*/
@@ -1081,11 +1094,21 @@ public class BundleDbPersistenceManager
Object[] params = createParams(bundle.getId(), out.toByteArray(), true);
conHelper.update(sql, params);
} catch (Exception e) {
- String msg = "failed to write bundle: " + bundle.getId();
+ String msg;
+
+ if (isIntegrityConstraintViolation(e)) {
+ // we should never get an integrity constraint violation here
+ // other PMs may not be able to detect this and end up with
+ // corrupted data
+ msg = "FATAL error while writing the bundle: " + bundle.getId();
+ } else {
+ msg = "failed to write bundle: " + bundle.getId();
+ }
+
log.error(msg, e);
throw new ItemStateException(msg, e);
}
- }
+ }
/**
* {@inheritDoc}
Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/ItemState.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/ItemState.java?rev=1176577&r1=1176576&r2=1176577&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/ItemState.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/ItemState.java Tue Sep 27 19:55:29 2011
@@ -132,7 +132,7 @@ public abstract class ItemState {
throw new IllegalArgumentException(msg);
}
this.isTransient = isTransient;
- connect(overlayedState);
+ this.overlayedState = overlayedState;
}
/**
@@ -176,11 +176,13 @@ public abstract class ItemState {
/**
* Connect this state to some underlying overlayed state.
*/
- protected void connect(ItemState overlayedState) {
- if (this.overlayedState != null) {
- if (this.overlayedState != overlayedState) {
- throw new IllegalStateException("Item state already connected to another underlying state: " + this);
- }
+ public void connect(ItemState overlayedState)
+ throws ItemStateException {
+ if (this.overlayedState != null
+ && this.overlayedState != overlayedState) {
+ throw new ItemStateException(
+ "Item state already connected to another"
+ + " underlying state: " + this);
}
this.overlayedState = overlayedState;
}
@@ -189,9 +191,9 @@ public abstract class ItemState {
* Reconnect this state to the overlayed state that it has been
* disconnected from earlier.
*/
- protected void reconnect() {
+ protected void reconnect() throws ItemStateException {
if (this.overlayedState == null) {
- throw new IllegalStateException(
+ throw new ItemStateException(
"Item state cannot be reconnected because there's no"
+ " underlying state to reconnect to: " + this);
}
Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/LocalItemStateManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/LocalItemStateManager.java?rev=1176577&r1=1176576&r2=1176577&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/LocalItemStateManager.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/LocalItemStateManager.java Tue Sep 27 19:55:29 2011
@@ -16,7 +16,9 @@
*/
package org.apache.jackrabbit.core.state;
+import javax.jcr.InvalidItemStateException;
import javax.jcr.ReferentialIntegrityException;
+import javax.jcr.RepositoryException;
import org.apache.jackrabbit.core.id.ItemId;
import org.apache.jackrabbit.core.id.NodeId;
@@ -251,21 +253,66 @@ public class LocalItemStateManager
/**
* {@inheritDoc}
*/
- public NodeState createNew(NodeId id, Name nodeTypeName,
- NodeId parentId)
- throws IllegalStateException {
+ public NodeState createNew(
+ NodeId id, Name nodeTypeName, NodeId parentId)
+ throws RepositoryException {
if (!editMode) {
- throw new IllegalStateException("Not in edit mode");
+ throw new RepositoryException("Not in edit mode");
+ }
+
+ boolean nonRandomId = true;
+ if (id == null) {
+ id = new NodeId();
+ nonRandomId = false;
}
- NodeState state = new NodeState(id, nodeTypeName, parentId,
- ItemState.STATUS_NEW, false);
+ NodeState state = new NodeState(
+ id, nodeTypeName, parentId, ItemState.STATUS_NEW, false);
changeLog.added(state);
state.setContainer(this);
+
+ if (nonRandomId && !changeLog.deleted(id)
+ && sharedStateMgr.hasItemState(id)) {
+ throw new InvalidItemStateException(
+ "Node " + id + " already exists");
+ }
+
return state;
}
/**
+ * Returns the local node state below the given transient one. If given
+ * a fresh new node state, then a new local state is created and added
+ * to the change log.
+ *
+ * @param transientState transient state
+ * @return local node state
+ * @throws RepositoryException if the local state could not be created
+ */
+ public NodeState getOrCreateLocalState(NodeState transientState)
+ throws RepositoryException {
+ NodeState localState = (NodeState) transientState.getOverlayedState();
+ if (localState == null) {
+ // The transient node state is new, create a new local state
+ localState = new NodeState(
+ transientState.getNodeId(),
+ transientState.getNodeTypeName(),
+ transientState.getParentId(),
+ ItemState.STATUS_NEW,
+ false);
+ changeLog.added(localState);
+ localState.setContainer(this);
+ try {
+ transientState.connect(localState);
+ } catch (ItemStateException e) {
+ // should never happen
+ throw new RepositoryException(e);
+ }
+ }
+ return localState;
+ }
+
+ /**
* {@inheritDoc}
*/
public PropertyState createNew(Name propName, NodeId parentId)
@@ -407,10 +454,20 @@ public class LocalItemStateManager
try {
local = changeLog.get(created.getId());
if (local != null) {
- // underlying state has been permanently created
- local.pull();
- local.setStatus(ItemState.STATUS_EXISTING);
- cache.cache(local);
+ if (local.isNode() && local.getOverlayedState() != created) {
+ // mid-air collision of concurrent node state creation
+ // with same id (JCR-2272)
+ if (local.getStatus() == ItemState.STATUS_NEW) {
+ local.setStatus(ItemState.STATUS_UNDEFINED); // we need a state that is != NEW
+ }
+ } else {
+ if (local.getOverlayedState() == created) {
+ // underlying state has been permanently created
+ local.pull();
+ local.setStatus(ItemState.STATUS_EXISTING);
+ cache.cache(local);
+ }
+ }
}
} catch (NoSuchItemStateException e) {
/* ignore */
Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SessionItemStateManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SessionItemStateManager.java?rev=1176577&r1=1176576&r2=1176577&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SessionItemStateManager.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SessionItemStateManager.java Tue Sep 27 19:55:29 2011
@@ -53,7 +53,7 @@ public class SessionItemStateManager
/**
* State manager that allows updates
*/
- private final UpdatableItemStateManager stateMgr;
+ private final LocalItemStateManager stateMgr;
/**
* Hierarchy manager
@@ -217,27 +217,13 @@ public class SessionItemStateManager
/**
* {@inheritDoc}
*/
- public NodeState createNew(NodeId id, Name nodeTypeName,
- NodeId parentId)
- throws IllegalStateException {
+ public NodeState createNew(
+ NodeId id, Name nodeTypeName, NodeId parentId)
+ throws RepositoryException {
return stateMgr.createNew(id, nodeTypeName, parentId);
}
/**
- * Customized variant of {@link #createNew(NodeId, Name, NodeId)} that
- * connects the newly created persistent state with the transient state.
- */
- public NodeState createNew(NodeState transientState)
- throws IllegalStateException {
-
- NodeState persistentState = createNew(transientState.getNodeId(),
- transientState.getNodeTypeName(),
- transientState.getParentId());
- transientState.connect(persistentState);
- return persistentState;
- }
-
- /**
* {@inheritDoc}
*/
public PropertyState createNew(Name propName, NodeId parentId)
@@ -250,8 +236,7 @@ public class SessionItemStateManager
* connects the newly created persistent state with the transient state.
*/
public PropertyState createNew(PropertyState transientState)
- throws IllegalStateException {
-
+ throws ItemStateException {
PropertyState persistentState = createNew(transientState.getName(),
transientState.getParentId());
transientState.connect(persistentState);
@@ -564,20 +549,27 @@ public class SessionItemStateManager
* @param parentId
* @param initialStatus
* @return
- * @throws ItemStateException
+ * @throws RepositoryException
*/
public NodeState createTransientNodeState(NodeId id, Name nodeTypeName, NodeId parentId, int initialStatus)
- throws ItemStateException {
+ throws RepositoryException {
+ if (initialStatus == ItemState.STATUS_NEW && id != null
+ && hasItemState(id)) {
+ throw new InvalidItemStateException(
+ "Node " + id + " already exists");
+ }
+
// check map; synchronized to ensure an entry is not created twice.
synchronized (transientStore) {
- if (transientStore.containsKey(id)) {
- String msg = "there's already a node state instance with id " + id;
- log.debug(msg);
- throw new ItemStateException(msg);
+ if (id == null) {
+ id = new NodeId();
+ } else if (transientStore.containsKey(id)) {
+ throw new RepositoryException(
+ "There is already a transient state for node " + id);
}
- NodeState state = new NodeState(id, nodeTypeName, parentId,
- initialStatus, true);
+ NodeState state = new NodeState(
+ id, nodeTypeName, parentId, initialStatus, true);
// put transient state in the map
transientStore.put(state.getId(), state);
state.setContainer(this);
@@ -971,4 +963,32 @@ public class SessionItemStateManager
return false;
}
}
+
+ /**
+ * Pushes the given transient state to the change log so it'll be
+ * persisted when the change log is committed. The transient state
+ * is replaced with the local state that has been pushed to the
+ * change log.
+ *
+ * @param transientState transient state
+ * @return the local state to be persisted
+ * @throws RepositoryException if the transiet state can not be persisted
+ */
+ public NodeState makePersistent(NodeState transientState)
+ throws RepositoryException {
+ NodeState localState = stateMgr.getOrCreateLocalState(transientState);
+
+ synchronized (localState) {
+ // copy state from transient state:
+ localState.copy(transientState, true);
+ // make state persistent
+ store(localState);
+ }
+
+ // disconnect the transient item state
+ disconnectTransientItemState(transientState);
+
+ return localState;
+ }
+
}
Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java?rev=1176577&r1=1176576&r2=1176577&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java Tue Sep 27 19:55:29 2011
@@ -179,9 +179,13 @@ public class SharedItemStateManager
private ISMLocking ismLocking;
/**
- * Update event channel.
+ * Update event channel. By default this is a dummy channel that simply
+ * ignores all events (so we don't need to check for null all the time),
+ * but in clustered environments the
+ * {@link #setEventChannel(UpdateEventChannel)} method should be called
+ * during initialization to connect this SISM instance with the cluster.
*/
- private UpdateEventChannel eventChannel;
+ private UpdateEventChannel eventChannel = new DummyUpdateEventChannel();
/**
* Creates a new <code>SharedItemStateManager</code> instance.
@@ -554,15 +558,13 @@ public class SharedItemStateManager
virtualNodeReferences = new ChangeLog[virtualProviders.length];
- /* let listener know about change */
- if (eventChannel != null) {
- eventChannel.updateCreated(this);
- }
+ // let listener know about change
+ eventChannel.updateCreated(this);
try {
writeLock = acquireWriteLock(local);
} finally {
- if (writeLock == null && eventChannel != null) {
+ if (writeLock == null) {
eventChannel.updateCancelled(this);
}
}
@@ -680,6 +682,16 @@ public class SharedItemStateManager
shared.deleted(state.getOverlayedState());
}
for (ItemState state : local.addedStates()) {
+ if (state.isNode() && state.getStatus() != ItemState.STATUS_NEW) {
+ // another node with same id had been created
+ // in the meantime, probably caused by mid-air collision
+ // of concurrent versioning operations (JCR-2272)
+ String msg = state.getId()
+ + " has been created externally (status "
+ + state.getStatus() + ")";
+ log.debug(msg);
+ throw new StaleItemStateException(msg);
+ }
state.connect(createInstance(state));
shared.added(state.getOverlayedState());
}
@@ -713,10 +725,8 @@ public class SharedItemStateManager
/* create event states */
events.createEventStates(rootNodeId, local, SharedItemStateManager.this);
- /* let listener know about change */
- if (eventChannel != null) {
- eventChannel.updatePrepared(this);
- }
+ // let listener know about change
+ eventChannel.updatePrepared(this);
if (VALIDATE_HIERARCHY) {
log.info("Validating change-set hierarchy");
@@ -786,13 +796,15 @@ public class SharedItemStateManager
/* dispatch the events */
events.dispatch();
-
- /* let listener know about finished operation */
- if (eventChannel != null) {
- String path = events.getSession().getUserID() + "@" + events.getCommonPath();
- eventChannel.updateCommitted(this, path);
- }
} finally {
+ // Let listener know about finished operation. This needs
+ // to happen in the finally block so that the cluster lock
+ // always gets released, even if a post-store() exception
+ // is thrown from the code above. See also JCR-2272.
+ String path = events.getSession().getUserID()
+ + "@" + events.getCommonPath();
+ eventChannel.updateCommitted(this, path);
+
if (writeLock != null) {
// exception occurred before downgrading lock
writeLock.release();
@@ -809,10 +821,8 @@ public class SharedItemStateManager
*/
public void cancel() {
try {
- /* let listener know about canceled operation */
- if (eventChannel != null) {
- eventChannel.updateCancelled(this);
- }
+ // let listener know about canceled operation
+ eventChannel.updateCancelled(this);
local.disconnect();
Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/UpdatableItemStateManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/UpdatableItemStateManager.java?rev=1176577&r1=1176576&r2=1176577&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/UpdatableItemStateManager.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/UpdatableItemStateManager.java Tue Sep 27 19:55:29 2011
@@ -20,6 +20,7 @@ import org.apache.jackrabbit.spi.Name;
import org.apache.jackrabbit.core.id.NodeId;
import javax.jcr.ReferentialIntegrityException;
+import javax.jcr.RepositoryException;
/**
* Identifies an <code>ItemStateManager</code> that allows updating
@@ -52,14 +53,15 @@ public interface UpdatableItemStateManag
* i.e. not yet existing state. Call {@link #store}
* on the returned object to make it persistent.
*
- * @param id the id of the node
+ * @param id the id of the node, or <code>null</code> for a new node id
* @param nodeTypeName The node type name
* @param parentId parent node's id
* @return a node state
- * @throws IllegalStateException if the manager is not in edit mode.
+ * @throws RepositoryException if the node state can not be created
*/
- NodeState createNew(NodeId id, Name nodeTypeName,
- NodeId parentId) throws IllegalStateException;
+ NodeState createNew(
+ NodeId id, Name nodeTypeName, NodeId parentId)
+ throws RepositoryException;
/**
* Creates a {@link PropertyState} instance representing new,
@@ -120,4 +122,5 @@ public interface UpdatableItemStateManag
* Disposes this <code>UpdatableItemStateManager</code> and frees resources.
*/
void dispose();
+
}
Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/InternalVersionManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/InternalVersionManagerImpl.java?rev=1176577&r1=1176576&r2=1176577&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/InternalVersionManagerImpl.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/InternalVersionManagerImpl.java Tue Sep 27 19:55:29 2011
@@ -22,6 +22,7 @@ import java.util.Collection;
import java.util.List;
import java.util.Map;
+import javax.jcr.InvalidItemStateException;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
@@ -255,7 +256,8 @@ public class InternalVersionManagerImpl
});
if (state == null) {
- throw new VersionException("History already exists for node " + node.getNodeId());
+ throw new InvalidItemStateException(
+ "History already exists for node " + node.getNodeId());
}
Name root = NameConstants.JCR_ROOTVERSION;
return new VersionHistoryInfo(
Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/NodeStateEx.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/NodeStateEx.java?rev=1176577&r1=1176576&r2=1176577&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/NodeStateEx.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/NodeStateEx.java Tue Sep 27 19:55:29 2011
@@ -427,7 +427,9 @@ public class NodeStateEx {
ItemState state = stateMgr.getItemState(propId);
stateMgr.destroy(state);
nodeState.removePropertyName(name);
- nodeState.setStatus(ItemState.STATUS_EXISTING_MODIFIED);
+ if (nodeState.getStatus() != ItemState.STATUS_NEW) {
+ nodeState.setStatus(ItemState.STATUS_EXISTING_MODIFIED);
+ }
return true;
}
} catch (ItemStateException e) {
@@ -556,9 +558,6 @@ public class NodeStateEx {
throws RepositoryException {
NodeId parentId = nodeState.getNodeId();
// create a new node state
- if (id == null) {
- id = new NodeId();
- }
NodeState state = stateMgr.createNew(id, nodeTypeName, parentId);
// create Node instance wrapping new node state
@@ -566,7 +565,7 @@ public class NodeStateEx {
node.setPropertyValue(NameConstants.JCR_PRIMARYTYPE, InternalValue.create(nodeTypeName));
// add new child node entry
- nodeState.addChildNodeEntry(name, id);
+ nodeState.addChildNodeEntry(name, state.getNodeId());
if (nodeState.getStatus() == ItemState.STATUS_EXISTING) {
nodeState.setStatus(ItemState.STATUS_EXISTING_MODIFIED);
}
Modified: jackrabbit/branches/2.2/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ConcurrentImportTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ConcurrentImportTest.java?rev=1176577&r1=1176576&r2=1176577&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ConcurrentImportTest.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ConcurrentImportTest.java Tue Sep 27 19:55:29 2011
@@ -20,18 +20,18 @@ import java.util.UUID;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.Node;
import javax.jcr.ImportUUIDBehavior;
import javax.jcr.InvalidItemStateException;
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.spi.Name;
+import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
-import org.xml.sax.Attributes;
import org.xml.sax.helpers.AttributesImpl;
-import org.apache.jackrabbit.spi.Name;
-import org.apache.jackrabbit.JcrConstants;
/**
* <code>ConcurrentVersioningTest</code> contains test cases that run version
@@ -87,10 +87,13 @@ public class ConcurrentImportTest extend
}
try {
session.refresh(false);
- addNode(test, uuid, JcrConstants.NT_UNSTRUCTURED, uuid, mixins);
try {
+ addNode(test, uuid,
+ JcrConstants.NT_UNSTRUCTURED, uuid,
+ mixins);
session.save();
- log.println("Added " + test.getPath() + "/" + uuid);
+ log.println("Added " + test.getPath() + "/"
+ + uuid);
log.flush();
} catch (InvalidItemStateException e) {
log.println("Ignoring expected error: " + e.toString());
Modified: jackrabbit/branches/2.2/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/TestAll.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/TestAll.java?rev=1176577&r1=1176576&r2=1176577&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/TestAll.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/TestAll.java Tue Sep 27 19:55:29 2011
@@ -48,8 +48,7 @@ public class TestAll extends TestCase {
suite.addTestSuite(ReplaceTest.class);
// test related to NodeStateMerger
- // temporarily disabled see JCR-2272 and JCR-2295
- // suite.addTestSuite(ConcurrentImportTest.class);
+ suite.addTestSuite(ConcurrentImportTest.class);
suite.addTestSuite(ConcurrentAddRemoveMoveTest.class);
suite.addTestSuite(ConcurrentAddRemovePropertyTest.class);
suite.addTestSuite(ConcurrentMixinModificationTest.class);
Modified: jackrabbit/branches/2.2/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/persistence/util/BundleBindingTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/persistence/util/BundleBindingTest.java?rev=1176577&r1=1176576&r2=1176577&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/persistence/util/BundleBindingTest.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/persistence/util/BundleBindingTest.java Tue Sep 27 19:55:29 2011
@@ -425,7 +425,7 @@ public class BundleBindingTest extends T
0, 70, -53, 75, -124 };
NodePropBundle result = binding.readBundle(new ByteArrayInputStream(
- corrupted), NodeId.randomId());
+ corrupted), new NodeId());
Iterator<PropertyEntry> iterator = result.getPropertyEntries()
.iterator();