Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Fluegge2010-07-02 10:19:59 -0400
committerMartin Fluegge2010-07-02 10:19:59 -0400
commit8d1e34b3540343643dc1506f6759d9d10200fe91 (patch)
tree294aedcfce81604c8792bc8a5b7b9c711f18edc9
parentd96c0290752f02785e0a65a6f2370cdf167e6203 (diff)
downloadcdo-8d1e34b3540343643dc1506f6759d9d10200fe91.tar.gz
cdo-8d1e34b3540343643dc1506f6759d9d10200fe91.tar.xz
cdo-8d1e34b3540343643dc1506f6759d9d10200fe91.zip
[316444] Provide an option to prevent containment cycles
https://bugs.eclipse.org/bugs/show_bug.cgi?id=316444
-rw-r--r--plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/id/CDOIDRevisionDeltaLockWrapper.java64
-rw-r--r--plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/BaseCDORevision.java3
-rw-r--r--plugins/org.eclipse.emf.cdo.examples.server/META-INF/MANIFEST.MF4
-rw-r--r--plugins/org.eclipse.emf.cdo.server.db/META-INF/MANIFEST.MF20
-rw-r--r--plugins/org.eclipse.emf.cdo.server.hibernate/META-INF/MANIFEST.MF14
-rw-r--r--plugins/org.eclipse.emf.cdo.server.net4j/META-INF/MANIFEST.MF10
-rw-r--r--plugins/org.eclipse.emf.cdo.server.objectivity/META-INF/MANIFEST.MF20
-rw-r--r--plugins/org.eclipse.emf.cdo.server/META-INF/MANIFEST.MF22
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/LockManager.java6
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/TransactionCommitContext.java112
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalLockManager.java5
-rw-r--r--plugins/org.eclipse.emf.cdo.tests.db/META-INF/MANIFEST.MF2
-rw-r--r--plugins/org.eclipse.emf.cdo.tests.hibernate/META-INF/MANIFEST.MF6
-rw-r--r--plugins/org.eclipse.emf.cdo.tests.objectivity/META-INF/MANIFEST.MF4
-rw-r--r--plugins/org.eclipse.emf.cdo.tests/META-INF/MANIFEST.MF4
-rw-r--r--plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AllConfigs.java2
-rw-r--r--plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_316444_Test.java561
-rw-r--r--plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/impl/RepositoryConfig.java46
-rw-r--r--plugins/org.gastro.server/META-INF/MANIFEST.MF12
19 files changed, 853 insertions, 64 deletions
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/id/CDOIDRevisionDeltaLockWrapper.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/id/CDOIDRevisionDeltaLockWrapper.java
new file mode 100644
index 0000000000..45d1daf163
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/id/CDOIDRevisionDeltaLockWrapper.java
@@ -0,0 +1,64 @@
+package org.eclipse.emf.cdo.internal.common.id;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.id.CDOIDAndBranch;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionDelta;
+
+/**
+ * @author Martin Fluegge
+ */
+public class CDOIDRevisionDeltaLockWrapper implements CDOIDAndBranch
+{
+ private Object key;
+
+ private InternalCDORevisionDelta delta;
+
+ public CDOIDRevisionDeltaLockWrapper(Object key, InternalCDORevisionDelta delta)
+ {
+ this.key = key;
+ this.delta = delta;
+ }
+
+ public void setKey(Object key)
+ {
+ this.key = key;
+ }
+
+ public Object getKey()
+ {
+ return key;
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ return key.equals(obj);
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return key.hashCode();
+ }
+
+ public void setDelta(InternalCDORevisionDelta delta)
+ {
+ this.delta = delta;
+ }
+
+ public InternalCDORevisionDelta getDelta()
+ {
+ return delta;
+ }
+
+ public CDOID getID()
+ {
+ return key instanceof CDOIDAndBranch ? ((CDOIDAndBranch)key).getID() : (CDOID)key;
+ }
+
+ public CDOBranch getBranch()
+ {
+ return key instanceof CDOIDAndBranch ? ((CDOIDAndBranch)key).getBranch() : null;
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/BaseCDORevision.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/BaseCDORevision.java
index f0e3326ccd..c3079405be 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/BaseCDORevision.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/BaseCDORevision.java
@@ -81,6 +81,9 @@ public abstract class BaseCDORevision extends AbstractCDORevision
private CDOID resourceID;
+ /**
+ * On a client, between a local modification and the commit the value of this <i>ID</i> can be an EObject.
+ */
private Object containerID;
private int containingFeatureID;
diff --git a/plugins/org.eclipse.emf.cdo.examples.server/META-INF/MANIFEST.MF b/plugins/org.eclipse.emf.cdo.examples.server/META-INF/MANIFEST.MF
index ebeb1d6030..809efa279b 100644
--- a/plugins/org.eclipse.emf.cdo.examples.server/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.emf.cdo.examples.server/META-INF/MANIFEST.MF
@@ -8,8 +8,8 @@ Bundle-Localization: plugin
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Bundle-ClassPath: .
Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.4.0,4.0.0)",
- org.eclipse.emf.cdo.server.db;bundle-version="[3.0.0,4.0.0)";visibility:=reexport,
- org.eclipse.emf.cdo.server.net4j;bundle-version="[3.0.0,4.0.0)",
+ org.eclipse.emf.cdo.server.db;bundle-version="[4.0.0,5.0.0)";visibility:=reexport,
+ org.eclipse.emf.cdo.server.net4j;bundle-version="[4.0.0,5.0.0)",
org.eclipse.net4j.db.h2;bundle-version="[3.0.0,4.0.0)",
org.eclipse.net4j.jvm;bundle-version="[3.0.0,4.0.0)",
org.eclipse.net4j.tcp;bundle-version="[3.0.0,4.0.0)"
diff --git a/plugins/org.eclipse.emf.cdo.server.db/META-INF/MANIFEST.MF b/plugins/org.eclipse.emf.cdo.server.db/META-INF/MANIFEST.MF
index 33710bba1b..a876bc72e1 100644
--- a/plugins/org.eclipse.emf.cdo.server.db/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.emf.cdo.server.db/META-INF/MANIFEST.MF
@@ -1,7 +1,7 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: org.eclipse.emf.cdo.server.db;singleton:=true
-Bundle-Version: 3.0.100.qualifier
+Bundle-Version: 4.0.0.qualifier
Bundle-Name: %pluginName
Bundle-Vendor: %providerName
Bundle-Localization: plugin
@@ -11,12 +11,12 @@ Bundle-RequiredExecutionEnvironment: J2SE-1.5
Bundle-ClassPath: .
Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.4.0,4.0.0)",
org.eclipse.net4j.db;bundle-version="[3.0.0,4.0.0)";visibility:=reexport,
- org.eclipse.emf.cdo.server;bundle-version="[3.0.0,4.0.0)";visibility:=reexport
-Export-Package: org.eclipse.emf.cdo.server.db;version="3.0.100",
- org.eclipse.emf.cdo.server.db.mapping;version="3.0.100",
- org.eclipse.emf.cdo.server.internal.db;version="3.0.100";x-friends:="org.eclipse.emf.cdo.tests,org.eclipse.emf.cdo.tests.db",
- org.eclipse.emf.cdo.server.internal.db.bundle;version="3.0.100";x-internal:=true,
- org.eclipse.emf.cdo.server.internal.db.jdbc;version="3.0.100";x-friends:="org.eclipse.emf.cdo.tests,org.eclipse.emf.cdo.tests.db",
- org.eclipse.emf.cdo.server.internal.db.mapping;version="3.0.100";x-friends:="org.eclipse.emf.cdo.tests,org.eclipse.emf.cdo.tests.db",
- org.eclipse.emf.cdo.server.internal.db.mapping.horizontal;version="3.0.100";x-friends:="org.eclipse.emf.cdo.tests,org.eclipse.emf.cdo.tests.db",
- org.eclipse.emf.cdo.server.internal.db.messages;version="3.0.100";x-internal:=true
+ org.eclipse.emf.cdo.server;bundle-version="[4.0.0,5.0.0)";visibility:=reexport
+Export-Package: org.eclipse.emf.cdo.server.db;version="4.0.0",
+ org.eclipse.emf.cdo.server.db.mapping;version="4.0.0",
+ org.eclipse.emf.cdo.server.internal.db;version="4.0.0";x-friends:="org.eclipse.emf.cdo.tests,org.eclipse.emf.cdo.tests.db",
+ org.eclipse.emf.cdo.server.internal.db.bundle;version="4.0.0";x-internal:=true,
+ org.eclipse.emf.cdo.server.internal.db.jdbc;version="4.0.0";x-friends:="org.eclipse.emf.cdo.tests,org.eclipse.emf.cdo.tests.db",
+ org.eclipse.emf.cdo.server.internal.db.mapping;version="4.0.0";x-friends:="org.eclipse.emf.cdo.tests,org.eclipse.emf.cdo.tests.db",
+ org.eclipse.emf.cdo.server.internal.db.mapping.horizontal;version="4.0.0";x-friends:="org.eclipse.emf.cdo.tests,org.eclipse.emf.cdo.tests.db",
+ org.eclipse.emf.cdo.server.internal.db.messages;version="4.0.0";x-internal:=true
diff --git a/plugins/org.eclipse.emf.cdo.server.hibernate/META-INF/MANIFEST.MF b/plugins/org.eclipse.emf.cdo.server.hibernate/META-INF/MANIFEST.MF
index e0d2fa7e5c..ed2faf1d40 100644
--- a/plugins/org.eclipse.emf.cdo.server.hibernate/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.emf.cdo.server.hibernate/META-INF/MANIFEST.MF
@@ -1,7 +1,7 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: org.eclipse.emf.cdo.server.hibernate;singleton:=true
-Bundle-Version: 3.0.0.qualifier
+Bundle-Version: 4.0.0.qualifier
Bundle-Name: %pluginName
Bundle-Vendor: %providerName
Bundle-Localization: plugin
@@ -11,13 +11,13 @@ Bundle-RequiredExecutionEnvironment: J2SE-1.5
Bundle-ClassPath: .
Eclipse-BuddyPolicy: registered
Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.4.0,4.0.0)",
- org.eclipse.emf.cdo.server;bundle-version="[3.0.0,4.0.0)";visibility:=reexport,
+ org.eclipse.emf.cdo.server;bundle-version="[4.0.0,5.0.0)";visibility:=reexport,
org.eclipse.net4j.db;bundle-version="[3.0.0,4.0.0)";visibility:=reexport
-Export-Package: org.eclipse.emf.cdo.server.hibernate;version="3.0.0",
- org.eclipse.emf.cdo.server.internal.hibernate;version="3.0.0";x-friends:="org.eclipse.emf.cdo.server.hibernate.teneo,org.eclipse.emf.cdo.tests.hibernate",
- org.eclipse.emf.cdo.server.internal.hibernate.bundle;version="3.0.0";x-internal:=true,
- org.eclipse.emf.cdo.server.internal.hibernate.info;version="3.0.0";x-friends:="org.eclipse.emf.cdo.server.hibernate.teneo,org.eclipse.emf.cdo.tests.hibernate",
- org.eclipse.emf.cdo.server.internal.hibernate.tuplizer;version="3.0.0";x-friends:="org.eclipse.emf.cdo.server.hibernate.teneo,org.eclipse.emf.cdo.tests.hibernate"
+Export-Package: org.eclipse.emf.cdo.server.hibernate;version="4.0.0",
+ org.eclipse.emf.cdo.server.internal.hibernate;version="4.0.0";x-friends:="org.eclipse.emf.cdo.server.hibernate.teneo,org.eclipse.emf.cdo.tests.hibernate",
+ org.eclipse.emf.cdo.server.internal.hibernate.bundle;version="4.0.0";x-internal:=true,
+ org.eclipse.emf.cdo.server.internal.hibernate.info;version="4.0.0";x-friends:="org.eclipse.emf.cdo.server.hibernate.teneo,org.eclipse.emf.cdo.tests.hibernate",
+ org.eclipse.emf.cdo.server.internal.hibernate.tuplizer;version="4.0.0";x-friends:="org.eclipse.emf.cdo.server.hibernate.teneo,org.eclipse.emf.cdo.tests.hibernate"
Import-Package: org.hibernate;version="[3.3.2,4.0.0)",
org.hibernate.cfg;version="[3.3.2,4.0.0)",
org.hibernate.collection;version="[3.3.2,4.0.0)",
diff --git a/plugins/org.eclipse.emf.cdo.server.net4j/META-INF/MANIFEST.MF b/plugins/org.eclipse.emf.cdo.server.net4j/META-INF/MANIFEST.MF
index 35b9348d00..77d28f4ccd 100644
--- a/plugins/org.eclipse.emf.cdo.server.net4j/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.emf.cdo.server.net4j/META-INF/MANIFEST.MF
@@ -1,7 +1,7 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: org.eclipse.emf.cdo.server.net4j;singleton:=true
-Bundle-Version: 3.0.0.qualifier
+Bundle-Version: 4.0.0.qualifier
Bundle-Name: %pluginName
Bundle-Vendor: %providerName
Bundle-Localization: plugin
@@ -10,8 +10,8 @@ Bundle-Activator: org.eclipse.emf.cdo.server.internal.net4j.bundle.OM$Activator
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Bundle-ClassPath: .
Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.4.0,4.0.0)";resolution:=optional,
- org.eclipse.emf.cdo.server;bundle-version="[3.0.0,4.0.0)";visibility:=reexport,
+ org.eclipse.emf.cdo.server;bundle-version="[4.0.0,5.0.0)";visibility:=reexport,
org.eclipse.net4j;bundle-version="[3.0.0,4.0.0)";visibility:=reexport
-Export-Package: org.eclipse.emf.cdo.server.internal.net4j.bundle;version="3.0.0";x-internal:=true,
- org.eclipse.emf.cdo.server.internal.net4j.protocol;version="3.0.0";x-friends:="org.eclipse.emf.cdo.tests",
- org.eclipse.emf.cdo.server.net4j;version="3.0.0"
+Export-Package: org.eclipse.emf.cdo.server.internal.net4j.bundle;version="4.0.0";x-internal:=true,
+ org.eclipse.emf.cdo.server.internal.net4j.protocol;version="4.0.0";x-friends:="org.eclipse.emf.cdo.tests",
+ org.eclipse.emf.cdo.server.net4j;version="4.0.0"
diff --git a/plugins/org.eclipse.emf.cdo.server.objectivity/META-INF/MANIFEST.MF b/plugins/org.eclipse.emf.cdo.server.objectivity/META-INF/MANIFEST.MF
index a71f823b34..56aed142e8 100644
--- a/plugins/org.eclipse.emf.cdo.server.objectivity/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.emf.cdo.server.objectivity/META-INF/MANIFEST.MF
@@ -2,23 +2,23 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.emf.cdo.server.objectivity;singleton:=true
-Bundle-Version: 3.0.100.qualifier
+Bundle-Version: 4.0.0.qualifier
Bundle-Activator: org.eclipse.emf.cdo.server.internal.objectivity.bundle.OM$Activator
Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.4.0,4.0.0)",
- org.eclipse.emf.cdo.server;bundle-version="[3.0.0,4.0.0)";visibility:=reexport
+ org.eclipse.emf.cdo.server;bundle-version="[4.0.0,5.0.0)";visibility:=reexport
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Bundle-Vendor: %providerName
Bundle-Localization: plugin
Bundle-ClassPath: .
-Export-Package: org.eclipse.emf.cdo.server.internal.objectivity;version="3.0.100",
- org.eclipse.emf.cdo.server.internal.objectivity.bundle;version="3.0.100",
- org.eclipse.emf.cdo.server.internal.objectivity.clustering;version="3.0.100",
- org.eclipse.emf.cdo.server.internal.objectivity.db;version="3.0.100",
- org.eclipse.emf.cdo.server.internal.objectivity.mapper;version="3.0.100",
- org.eclipse.emf.cdo.server.internal.objectivity.schema;version="3.0.100",
- org.eclipse.emf.cdo.server.internal.objectivity.utils;version="3.0.100",
- org.eclipse.emf.cdo.server.objectivity;version="3.0.100"
+Export-Package: org.eclipse.emf.cdo.server.internal.objectivity;version="4.0.0",
+ org.eclipse.emf.cdo.server.internal.objectivity.bundle;version="4.0.0",
+ org.eclipse.emf.cdo.server.internal.objectivity.clustering;version="4.0.0",
+ org.eclipse.emf.cdo.server.internal.objectivity.db;version="4.0.0",
+ org.eclipse.emf.cdo.server.internal.objectivity.mapper;version="4.0.0",
+ org.eclipse.emf.cdo.server.internal.objectivity.schema;version="4.0.0",
+ org.eclipse.emf.cdo.server.internal.objectivity.utils;version="4.0.0",
+ org.eclipse.emf.cdo.server.objectivity;version="4.0.0"
Import-Package: com.objy.as;version="3.0.0",
com.objy.as.app;version="3.0.0",
com.objy.db;version="3.0.0",
diff --git a/plugins/org.eclipse.emf.cdo.server/META-INF/MANIFEST.MF b/plugins/org.eclipse.emf.cdo.server/META-INF/MANIFEST.MF
index 931da88f7b..a833b79e5f 100644
--- a/plugins/org.eclipse.emf.cdo.server/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.emf.cdo.server/META-INF/MANIFEST.MF
@@ -1,7 +1,7 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: org.eclipse.emf.cdo.server;singleton:=true
-Bundle-Version: 3.0.100.qualifier
+Bundle-Version: 4.0.0.qualifier
Bundle-Name: %pluginName
Bundle-Vendor: %providerName
Bundle-Localization: plugin
@@ -12,13 +12,13 @@ Bundle-ClassPath: .
Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.4.0,4.0.0)";resolution:=optional,
org.eclipse.emf.cdo;bundle-version="[3.0.0,4.0.0)";visibility:=reexport,
org.eclipse.net4j.util;bundle-version="[3.1.0,4.0.0)";visibility:=reexport
-Export-Package: org.eclipse.emf.cdo.internal.server;version="3.0.100";x-friends:="org.eclipse.emf.cdo.server.db,org.eclipse.emf.cdo.server.net4j,org.eclipse.emf.cdo.tests",
- org.eclipse.emf.cdo.internal.server.bundle;version="3.0.100";x-internal:=true,
- org.eclipse.emf.cdo.internal.server.embedded;version="3.0.100";x-friends:="org.eclipse.emf.cdo.tests",
- org.eclipse.emf.cdo.internal.server.mem;version="3.0.100";x-friends:="org.eclipse.emf.cdo.tests",
- org.eclipse.emf.cdo.internal.server.messages;version="3.0.100";x-internal:=true,
- org.eclipse.emf.cdo.internal.server.syncing;version="3.0.100";x-friends:="org.eclipse.emf.cdo.tests",
- org.eclipse.emf.cdo.server;version="3.0.100",
- org.eclipse.emf.cdo.server.embedded;version="3.0.100",
- org.eclipse.emf.cdo.server.mem;version="3.0.100",
- org.eclipse.emf.cdo.spi.server;version="3.0.100"
+Export-Package: org.eclipse.emf.cdo.internal.server;version="4.0.0";x-friends:="org.eclipse.emf.cdo.server.db,org.eclipse.emf.cdo.server.net4j,org.eclipse.emf.cdo.tests",
+ org.eclipse.emf.cdo.internal.server.bundle;version="4.0.0";x-internal:=true,
+ org.eclipse.emf.cdo.internal.server.embedded;version="4.0.0";x-friends:="org.eclipse.emf.cdo.tests",
+ org.eclipse.emf.cdo.internal.server.mem;version="4.0.0";x-friends:="org.eclipse.emf.cdo.tests",
+ org.eclipse.emf.cdo.internal.server.messages;version="4.0.0";x-internal:=true,
+ org.eclipse.emf.cdo.internal.server.syncing;version="4.0.0";x-friends:="org.eclipse.emf.cdo.tests",
+ org.eclipse.emf.cdo.server;version="4.0.0",
+ org.eclipse.emf.cdo.server.embedded;version="4.0.0",
+ org.eclipse.emf.cdo.server.mem;version="4.0.0",
+ org.eclipse.emf.cdo.spi.server;version="4.0.0"
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/LockManager.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/LockManager.java
index 294250249e..087774b810 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/LockManager.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/LockManager.java
@@ -71,6 +71,12 @@ public class LockManager extends RWLockManager<Object, IView> implements Interna
this.repository = repository;
}
+ public Object getLockEntryObject(Object key)
+ {
+ LockEntry<Object, IView> lockEntry = getLockEntry(key);
+ return lockEntry.getObject();
+ }
+
@Override
protected void doActivate() throws Exception
{
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/TransactionCommitContext.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/TransactionCommitContext.java
index f5173c0ebf..ccf2da3a87 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/TransactionCommitContext.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/TransactionCommitContext.java
@@ -8,6 +8,7 @@
* Contributors:
* Simon McDuff - initial API and implementation
* Eike Stepper - maintenance
+ * Martin Fluegge - maintenance, bug 318518
*/
package org.eclipse.emf.cdo.internal.server;
@@ -27,11 +28,13 @@ import org.eclipse.emf.cdo.common.revision.CDOReferenceAdjuster;
import org.eclipse.emf.cdo.common.revision.CDORevision;
import org.eclipse.emf.cdo.common.revision.CDORevisionKey;
import org.eclipse.emf.cdo.common.revision.delta.CDOAddFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta;
import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDeltaVisitor;
import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta;
import org.eclipse.emf.cdo.common.revision.delta.CDOSetFeatureDelta;
import org.eclipse.emf.cdo.common.util.CDOCommonUtil;
import org.eclipse.emf.cdo.internal.common.commit.CDOCommitDataImpl;
+import org.eclipse.emf.cdo.internal.common.id.CDOIDRevisionDeltaLockWrapper;
import org.eclipse.emf.cdo.internal.common.model.CDOPackageRegistryImpl;
import org.eclipse.emf.cdo.internal.server.bundle.OM;
import org.eclipse.emf.cdo.server.IRepository.Props;
@@ -63,6 +66,7 @@ import org.eclipse.net4j.util.om.monitor.OMMonitor;
import org.eclipse.net4j.util.om.trace.ContextTracer;
import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import java.text.MessageFormat;
@@ -578,12 +582,24 @@ public class TransactionCommitContext implements InternalCommitContext
}
}
+ InternalLockManager lockManager = transaction.getRepository().getLockManager();
+
for (int i = 0; i < dirtyObjectDeltas.length; i++)
{
InternalCDORevisionDelta delta = dirtyObjectDeltas[i];
CDOID id = delta.getID();
Object key = supportingBranches ? CDOIDUtil.createIDAndBranch(id, transaction.getBranch()) : id;
- lockedObjects.add(key);
+ lockedObjects.add(new CDOIDRevisionDeltaLockWrapper(key, delta));
+
+ if (referentialIntegrityEnsured && hasContainmentChanges(delta))
+ {
+ InternalCDORevisionManager revisionManager = transaction.getRepository().getRevisionManager();
+ if (isContainerLocked(delta, revisionManager, lockManager))
+ {
+ lockedObjects.clear();
+ throw new ContainmentCycleDetectedException("Parent (" + key + ") is already locked for containment changes");
+ }
+ }
if (deltaTargetLocker != null)
{
@@ -602,7 +618,6 @@ public class TransactionCommitContext implements InternalCommitContext
{
if (!lockedObjects.isEmpty())
{
- InternalLockManager lockManager = transaction.getRepository().getLockManager();
lockManager.lock(LockType.WRITE, transaction, lockedObjects, 1000);
}
}
@@ -613,6 +628,72 @@ public class TransactionCommitContext implements InternalCommitContext
}
}
+ /**
+ * Iterates up the eContainers of an object and returns <code>true</code> on the first parent locked by another view.
+ *
+ * @return <code>true</code> if any parent is locked, <code>false</code> otherwise.
+ */
+ private boolean isContainerLocked(InternalCDORevisionDelta delta, InternalCDORevisionManager revisionManager,
+ InternalLockManager lockManager)
+ {
+ CDOID id = delta.getID();
+ InternalCDORevision revision = revisionManager.getRevisionByVersion(id, delta, CDORevision.UNCHUNKED, true);
+ return isContainerLocked(revision, revisionManager, lockManager);
+ }
+
+ private boolean isContainerLocked(InternalCDORevision revision, InternalCDORevisionManager revisionManager,
+ InternalLockManager lockManager)
+ {
+ CDOID id = (CDOID)revision.getContainerID();
+ if (CDOIDUtil.isNull(id))
+ {
+ return false;
+ }
+
+ final boolean supportingBranches = transaction.getRepository().isSupportingBranches();
+ Object key = supportingBranches ? CDOIDUtil.createIDAndBranch(id, transaction.getBranch()) : id;
+
+ if (lockManager.hasLockByOthers(LockType.WRITE, transaction, key))
+ {
+ Object object = lockManager.getLockEntryObject(key);
+ if (object instanceof CDOIDRevisionDeltaLockWrapper)
+ {
+ InternalCDORevisionDelta delta = ((CDOIDRevisionDeltaLockWrapper)object).getDelta();
+ if (delta != null && hasContainmentChanges(delta))
+ {
+ return true;
+ }
+ }
+ }
+
+ InternalCDORevision parent = revisionManager.getRevision(id, transaction, CDORevision.UNCHUNKED,
+ CDORevision.DEPTH_NONE, true);
+
+ if (parent != null)
+ {
+ return isContainerLocked(parent, revisionManager, lockManager);
+ }
+
+ return false;
+ }
+
+ private boolean hasContainmentChanges(InternalCDORevisionDelta delta)
+ {
+ for (CDOFeatureDelta featureDelta : delta.getFeatureDeltas())
+ {
+ EStructuralFeature feature = featureDelta.getFeature();
+ if (feature instanceof EReference)
+ {
+ if (((EReference)feature).isContainment())
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
private void lockTarget(Object value, boolean supportingBranches)
{
if (value instanceof CDOIDObject)
@@ -913,4 +994,31 @@ public class TransactionCommitContext implements InternalCommitContext
// Do nothing
}
}
+
+ /**
+ * @author Eike Stepper
+ */
+ public static class ContainmentCycleDetectedException extends IllegalStateException
+ {
+ private static final long serialVersionUID = 1L;
+
+ public ContainmentCycleDetectedException()
+ {
+ }
+
+ public ContainmentCycleDetectedException(String message, Throwable cause)
+ {
+ super(message, cause);
+ }
+
+ public ContainmentCycleDetectedException(String s)
+ {
+ super(s);
+ }
+
+ public ContainmentCycleDetectedException(Throwable cause)
+ {
+ super(cause);
+ }
+ }
}
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalLockManager.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalLockManager.java
index d15ff092ae..87161485d0 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalLockManager.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalLockManager.java
@@ -28,4 +28,9 @@ public interface InternalLockManager extends IRWLockManager<Object, IView>
public InternalRepository getRepository();
public void setRepository(InternalRepository repository);
+
+ /**
+ * @since 4.0
+ */
+ public Object getLockEntryObject(Object key);
}
diff --git a/plugins/org.eclipse.emf.cdo.tests.db/META-INF/MANIFEST.MF b/plugins/org.eclipse.emf.cdo.tests.db/META-INF/MANIFEST.MF
index f91368e0dd..4200cecedb 100644
--- a/plugins/org.eclipse.emf.cdo.tests.db/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.emf.cdo.tests.db/META-INF/MANIFEST.MF
@@ -10,7 +10,7 @@ Bundle-Activator: org.eclipse.emf.cdo.tests.db.bundle.OM$Activator
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Bundle-ClassPath: .
Require-Bundle: org.eclipse.emf.cdo.tests;bundle-version="[4.0.0,5.0.0)";visibility:=reexport,
- org.eclipse.emf.cdo.server.db;bundle-version="[3.0.0,4.0.0)";visibility:=reexport,
+ org.eclipse.emf.cdo.server.db;bundle-version="[4.0.0,5.0.0)";visibility:=reexport,
org.eclipse.net4j.db.hsqldb;bundle-version="[3.0.0,4.0.0)";visibility:=reexport,
org.eclipse.net4j.db.derby;bundle-version="[3.0.0,4.0.0)";visibility:=reexport,
org.eclipse.net4j.db.mysql;bundle-version="[3.0.0,4.0.0)";visibility:=reexport,
diff --git a/plugins/org.eclipse.emf.cdo.tests.hibernate/META-INF/MANIFEST.MF b/plugins/org.eclipse.emf.cdo.tests.hibernate/META-INF/MANIFEST.MF
index c6710a1505..fc5fd8ee30 100644
--- a/plugins/org.eclipse.emf.cdo.tests.hibernate/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.emf.cdo.tests.hibernate/META-INF/MANIFEST.MF
@@ -12,9 +12,9 @@ Bundle-ClassPath: .
Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.4.0,4.0.0)",
org.eclipse.net4j.tcp;bundle-version="[3.0.0,4.0.0)",
org.eclipse.emf.cdo;bundle-version="[3.0.0,4.0.0)",
- org.eclipse.emf.cdo.server;bundle-version="[3.0.0,4.0.0)",
- org.eclipse.emf.cdo.server.hibernate;bundle-version="[3.0.0,4.0.0)",
- org.eclipse.emf.cdo.server.db;bundle-version="[3.0.0,4.0.0)",
+ org.eclipse.emf.cdo.server;bundle-version="[4.0.0,5.0.0)",
+ org.eclipse.emf.cdo.server.hibernate;bundle-version="[4.0.0,5.0.0)",
+ org.eclipse.emf.cdo.server.db;bundle-version="[4.0.0,5.0.0)",
org.eclipse.emf.cdo.tests;bundle-version="[4.0.0,5.0.0)",
org.eclipse.emf.cdo.server.hibernate.teneo;bundle-version="[3.0.0,4.0.0)",
org.hsqldb;bundle-version="[1.8.0,2.0.0)",
diff --git a/plugins/org.eclipse.emf.cdo.tests.objectivity/META-INF/MANIFEST.MF b/plugins/org.eclipse.emf.cdo.tests.objectivity/META-INF/MANIFEST.MF
index b219858ffd..91e4bc9122 100644
--- a/plugins/org.eclipse.emf.cdo.tests.objectivity/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.emf.cdo.tests.objectivity/META-INF/MANIFEST.MF
@@ -2,10 +2,8 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: org.eclipse.emf.cdo.tests.objectivity;singleton:=true
Bundle-Version: 3.0.0.qualifier
-Bundle-Activator: org.eclipse.emf.cdo.server.internal.objectivity.bundle.OM$Activator
-Require-Bundle: org.eclipse.emf.cdo.server.objectivity;bundle-version="[3.0.0,4.0.0)",
+Require-Bundle: org.eclipse.emf.cdo.server.objectivity;bundle-version="[4.0.0,5.0.0)",
org.eclipse.emf.cdo.tests;bundle-version="[4.0.0,5.0.0)"
-Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Bundle-Name: %pluginName
Bundle-Vendor: %providerName
diff --git a/plugins/org.eclipse.emf.cdo.tests/META-INF/MANIFEST.MF b/plugins/org.eclipse.emf.cdo.tests/META-INF/MANIFEST.MF
index b9c0b1b944..296e6e3d21 100644
--- a/plugins/org.eclipse.emf.cdo.tests/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.emf.cdo.tests/META-INF/MANIFEST.MF
@@ -19,8 +19,8 @@ Require-Bundle: org.eclipse.net4j.tests;bundle-version="[3.0.0,4.0.0)";visibilit
org.eclipse.emf.cdo.common.db;bundle-version="[3.0.0,4.0.0)";visibility:=reexport,
org.eclipse.emf.cdo;bundle-version="[3.0.0,4.0.0)";visibility:=reexport,
org.eclipse.emf.cdo.net4j;bundle-version="[3.0.0,4.0.0)";visibility:=reexport,
- org.eclipse.emf.cdo.server;bundle-version="[3.0.0,4.0.0)";visibility:=reexport,
- org.eclipse.emf.cdo.server.net4j;bundle-version="[3.0.0,4.0.0)";visibility:=reexport,
+ org.eclipse.emf.cdo.server;bundle-version="[4.0.0,5.0.0)";visibility:=reexport,
+ org.eclipse.emf.cdo.server.net4j;bundle-version="[4.0.0,5.0.0)";visibility:=reexport,
org.eclipse.emf.cdo.tests.mango;bundle-version="[3.0.0,4.0.0)";visibility:=reexport,
org.eclipse.emf.cdo.tests.model1;bundle-version="[3.0.0,4.0.0)";visibility:=reexport,
org.eclipse.emf.cdo.tests.model2;bundle-version="[3.0.0,4.0.0)";visibility:=reexport,
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AllConfigs.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AllConfigs.java
index f7a5204025..283e58321b 100644
--- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AllConfigs.java
+++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AllConfigs.java
@@ -76,6 +76,7 @@ import org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_308895_Test;
import org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_310574_Test;
import org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_314264_Test;
import org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_316145_Test;
+import org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_316444_Test;
import org.eclipse.emf.cdo.tests.config.impl.ConfigTest;
import org.eclipse.emf.cdo.tests.config.impl.ConfigTestSuite;
@@ -215,6 +216,7 @@ public abstract class AllConfigs extends ConfigTestSuite
testClasses.add(Bugzilla_314264_Test.class);
testClasses.add(Bugzilla_316145_Test.class);
// testClasses.add(Bugzilla_316887_Test.class); // The test logic is buggy
+ testClasses.add(Bugzilla_316444_Test.class);
// TODO testClasses.add(NonCDOResourceTest.class);
// TODO testClasses.add(GeneratedEcoreTest.class);
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_316444_Test.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_316444_Test.java
new file mode 100644
index 0000000000..3e28b057dd
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_316444_Test.java
@@ -0,0 +1,561 @@
+/**
+ * Copyright (c) 2004 - 2010 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Martin Fluegge - initial API and implementation
+ */
+package org.eclipse.emf.cdo.tests.bugzilla;
+
+import org.eclipse.emf.cdo.internal.server.Repository;
+import org.eclipse.emf.cdo.internal.server.TransactionCommitContext;
+import org.eclipse.emf.cdo.net4j.CDOSession;
+import org.eclipse.emf.cdo.server.IRepository;
+import org.eclipse.emf.cdo.spi.server.InternalCommitContext;
+import org.eclipse.emf.cdo.spi.server.InternalRepository;
+import org.eclipse.emf.cdo.spi.server.InternalTransaction;
+import org.eclipse.emf.cdo.tests.AbstractCDOTest;
+import org.eclipse.emf.cdo.tests.config.impl.RepositoryConfig;
+import org.eclipse.emf.cdo.tests.model3.NodeA;
+import org.eclipse.emf.cdo.tests.model3.NodeB;
+import org.eclipse.emf.cdo.transaction.CDOTransaction;
+import org.eclipse.emf.cdo.util.CommitException;
+
+import org.eclipse.net4j.util.WrappedException;
+import org.eclipse.net4j.util.lifecycle.LifecycleUtil;
+
+import org.eclipse.emf.ecore.resource.Resource;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author Martin Fluegge
+ * @since 4.0
+ */
+public class Bugzilla_316444_Test extends AbstractCDOTest
+{
+ private static final String REPOSITORY_NAME = "repo1";
+
+ private static final String RESOURCE_PATH = "/my/resource";
+
+ public int idSessionA;
+
+ public int idSessionB;
+
+ private int idInitSession;
+
+ private Object monitor = new Object();
+
+ private CountDownLatch latch = new CountDownLatch(2);
+
+ private boolean finishedSessionA = false;
+
+ private List<Exception> exceptions = new ArrayList<Exception>();
+
+ @Override
+ protected void doSetUp() throws Exception
+ {
+ createRepository();
+ super.doSetUp();
+ }
+
+ private void createRepository()
+ {
+ Repository repository = new Repository.Default()
+ {
+ @Override
+ public InternalCommitContext createCommitContext(InternalTransaction transaction)
+ {
+ return new TransactionCommitContext(transaction)
+ {
+ @Override
+ protected void lockObjects() throws InterruptedException
+ {
+ int sessionID = getTransaction().getSession().getSessionID();
+ if (sessionID == idSessionB)
+ {
+ synchronized (monitor)
+ {
+ // Only wait if Session A has not passed the lockObjects
+ if (!finishedSessionA)
+ {
+ msg("Session B is waiting for Session A");
+ monitor.wait(DEFAULT_TIMEOUT);
+ msg("Session B stopped waiting");
+ }
+ else
+ {
+ msg("Session B - no need to wait. A has already passed lockObjects()");
+ }
+ }
+ }
+
+ msg("Passing lockObjects() " + getTransaction().getSession());
+
+ try
+ {
+ super.lockObjects();
+ }
+ catch (Exception e)
+ {
+ latch.countDown();
+ throw new RuntimeException(e);
+ }
+
+ msg("Passed lockObjects() " + getTransaction().getSession());
+
+ if (sessionID == idSessionA)
+ {
+ synchronized (monitor)
+ {
+ finishedSessionA = true;
+ monitor.notifyAll();
+ msg("Session A notified others not to wait anymore.");
+ }
+ }
+
+ // Do nothing for inital session. Otherwise the test will block too early
+ if (sessionID != idInitSession)
+ {
+ latch.countDown();
+
+ try
+ {
+ assertEquals(true, latch.await(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS));
+ }
+ catch (InterruptedException ex)
+ {
+ throw WrappedException.wrap(ex);
+ }
+ }
+ }
+ };
+ }
+ };
+
+ Map<String, String> props = getRepositoryProperties();
+
+ // Map<String, String> props = new HashMap<String, String>();
+ // props.put(IRepository.Props.SUPPORTING_AUDITS, "true");
+ // props.put(IRepository.Props.SUPPORTING_BRANCHES, "true");
+ props.put(IRepository.Props.ENSURE_REFERENTIAL_INTEGRITY, "true");
+ ((InternalRepository)repository).setProperties(props);
+
+ repository.setName(REPOSITORY_NAME);
+
+ Map<String, Object> map = getTestProperties();
+ map.put(RepositoryConfig.PROP_TEST_REPOSITORY, repository);
+ }
+
+ public void testLockParentWithEAttributeChange() throws Exception
+ {
+ skipUnlessBranching();
+
+ String resourcePath = RESOURCE_PATH + "1";
+ {
+ CDOSession session = (CDOSession)openSession(REPOSITORY_NAME);
+ idInitSession = session.getSessionID();
+ CDOTransaction transaction = session.openTransaction();
+
+ Resource resource = transaction.createResource(resourcePath);
+
+ // -------------- create graph begin ------------------------
+ NodeB root = createSimpleNode("root");
+
+ NodeB A = createSimpleNode("A");
+ NodeB B = createSimpleNode("B");
+ NodeB C = createSimpleNode("C");
+ NodeB D = createSimpleNode("D");
+ NodeB E = createSimpleNode("E");
+
+ root.getChildren().add(A);
+ root.getChildren().add(D);
+
+ A.getChildren().add(B);
+ B.getChildren().add(C);
+
+ D.getChildren().add(E);
+
+ resource.getContents().add(root);
+ transaction.commit();
+
+ // -------- check for consistency -----------
+
+ checkInitialGraph(root, A, B, C, D, E);
+
+ transaction.close();
+ session.close();
+ }
+
+ restartRepository();
+
+ {
+ CDOSession session = (CDOSession)openSession(REPOSITORY_NAME);
+ idInitSession = session.getSessionID();
+
+ // ----- start threads -----
+ ThreadX threadX = new ThreadX(resourcePath);
+ ThreadA threadA = new ThreadA(resourcePath);
+
+ threadA.start();
+ threadX.start();
+
+ threadX.join(DEFAULT_TIMEOUT);
+ threadA.join(DEFAULT_TIMEOUT);
+
+ if (exceptions.size() > 0)
+ {
+ throw exceptions.get(0);
+ }
+ }
+ }
+
+ public void testMovingSubtree() throws Exception
+ {
+ skipUnlessBranching();
+ exceptions.clear();
+
+ {
+ CDOSession session = (CDOSession)openSession(REPOSITORY_NAME);
+ idInitSession = session.getSessionID();
+ CDOTransaction transaction = session.openTransaction();
+
+ Resource resource = transaction.createResource(RESOURCE_PATH);
+
+ // -------------- create graph begin ------------------------
+ NodeB root = createSimpleNode("root");
+
+ NodeB A = createSimpleNode("A");
+ NodeB B = createSimpleNode("B");
+ NodeB C = createSimpleNode("C");
+ NodeB D = createSimpleNode("D");
+ NodeB E = createSimpleNode("E");
+
+ root.getChildren().add(A);
+ root.getChildren().add(D);
+
+ A.getChildren().add(B);
+ B.getChildren().add(C);
+
+ D.getChildren().add(E);
+
+ resource.getContents().add(root);
+ transaction.commit();
+
+ // -------- check for consistency -----------
+
+ checkInitialGraph(root, A, B, C, D, E);
+
+ transaction.close();
+ session.close();
+ }
+
+ // if (!(isConfig(MEM) || isConfig(MEM_AUDITS) || isConfig(MEM_BRANCHES) || isConfig(MEM_OFFLINE)))
+ // {
+ // // do not restart the repository on MEM store
+ // restartRepository();
+ // }
+
+ {
+ // Just an additional check to make sure that the graph is stored correctly even after repository restart
+ CDOSession session = (CDOSession)openSession(REPOSITORY_NAME);
+ idInitSession = session.getSessionID();
+ CDOTransaction transaction = session.openTransaction();
+ Resource resource = transaction.getResource(RESOURCE_PATH, true);
+
+ NodeB root = (NodeB)resource.getContents().get(0);
+ assertEquals("root", root.getName());
+
+ NodeB A = getElementFromGraphNodeB(root, "A");
+ NodeB B = getElementFromGraphNodeB(root, "B");
+ NodeB C = getElementFromGraphNodeB(root, "C");
+ NodeB D = getElementFromGraphNodeB(root, "D");
+ NodeB E = getElementFromGraphNodeB(root, "E");
+
+ assertNotNull(A);
+ assertNotNull(B);
+ assertNotNull(C);
+ assertNotNull(D);
+ assertNotNull(E);
+
+ checkInitialGraph(root, A, B, C, D, E);
+ }
+
+ {
+ CDOSession session = (CDOSession)openSession(REPOSITORY_NAME);
+ idInitSession = session.getSessionID();
+
+ // ----- start threads -----
+ ThreadA threadA = new ThreadA(RESOURCE_PATH);
+ ThreadB threadB = new ThreadB(RESOURCE_PATH);
+
+ threadB.start();
+ threadA.start();
+
+ threadA.join(DEFAULT_TIMEOUT);
+ threadB.join(DEFAULT_TIMEOUT);
+
+ if (exceptions.size() > 0)
+ {
+ Exception exception = exceptions.get(0);
+ if (exception instanceof ThreadBShouldHaveThrownAnExceptionException)
+ {
+ fail(exception.getMessage());
+ }
+ else
+ {
+ throw exception;
+ }
+ }
+
+ session.close();
+ msg("finished");
+ }
+
+ }
+
+ private void checkInitialGraph(NodeB root, NodeB A, NodeB B, NodeB C, NodeB D, NodeB E)
+ {
+ assertEquals("A", A.getName());
+ assertEquals("B", B.getName());
+ assertEquals("C", C.getName());
+ assertEquals("D", D.getName());
+ assertEquals("E", E.getName());
+
+ assertEquals(root, A.getParent());
+ assertEquals(root, A.eContainer());
+
+ assertEquals(root, D.getParent());
+ assertEquals(root, D.eContainer());
+
+ assertEquals(A, B.getParent());
+ assertEquals(A, B.eContainer());
+
+ assertEquals(B, C.getParent());
+ assertEquals(B, C.eContainer());
+
+ assertEquals(D, E.getParent());
+ assertEquals(D, E.eContainer());
+ }
+
+ private abstract class AbstactTestThread extends Thread
+ {
+ protected final String resourcePath;
+
+ public AbstactTestThread(String resourcePath)
+ {
+ this.resourcePath = resourcePath;
+ }
+ }
+
+ /**
+ * @author Martin Fluegge
+ */
+ private class ThreadA extends AbstactTestThread
+ {
+ private CDOSession session;
+
+ public ThreadA(String resourcePath)
+ {
+ super(resourcePath);
+ msg("Starting Thread A");
+ session = (CDOSession)openSession(REPOSITORY_NAME);
+ idSessionA = session.getSessionID();
+ }
+
+ @Override
+ public void run()
+ {
+ msg("Started Thread A");
+ CDOTransaction transaction = session.openTransaction();
+ Resource resource = transaction.getResource(resourcePath, true);
+
+ NodeB root = (NodeB)resource.getContents().get(0);
+ assertEquals("root", root.getName());
+
+ NodeB B = getElementFromGraphNodeB(root, "B");
+ NodeB E = getElementFromGraphNodeB(root, "E");
+
+ assertEquals("B", B.getName());
+ assertEquals("E", E.getName());
+
+ E.getChildren().add(B);
+
+ try
+ {
+ transaction.commit();
+ }
+ catch (CommitException ex)
+ {
+ exceptions.add(ex);
+ }
+
+ session.close();
+ msg("Finished Thread A");
+ }
+ }
+
+ /**
+ * @author Martin Fluegge
+ */
+ private class ThreadB extends AbstactTestThread
+ {
+ private CDOSession session;
+
+ public ThreadB(String resourcePath)
+ {
+ super(resourcePath);
+ msg("Starting Thread B");
+ session = (CDOSession)openSession(REPOSITORY_NAME);
+ idSessionB = session.getSessionID();
+ }
+
+ @Override
+ public void run()
+ {
+ msg("Started Thread B");
+ CDOTransaction transaction = session.openTransaction();
+ Resource resource = transaction.getResource(resourcePath, true);
+
+ NodeB root = (NodeB)resource.getContents().get(0);
+ assertEquals("root", root.getName());
+ NodeB C = getElementFromGraphNodeB(root, "C");
+ NodeB D = getElementFromGraphNodeB(root, "D");
+
+ assertEquals("C", C.getName());
+ assertEquals("D", D.getName());
+
+ C.getChildren().add(D);
+
+ try
+ {
+ transaction.commit();
+ }
+ catch (CommitException ex)
+ {
+ // passed
+ return;
+ }
+
+ exceptions.add(new ThreadBShouldHaveThrownAnExceptionException("Thread B should have thrown an exception"));
+
+ session.close();
+ msg("Finished Thread B");
+ }
+ }
+
+ /**
+ * @author Martin Fluegge
+ */
+ private class ThreadX extends AbstactTestThread
+ {
+ private CDOSession session;
+
+ public ThreadX(String resourcePath)
+ {
+ super(resourcePath);
+ msg("Starting Thread A");
+ session = (CDOSession)openSession(REPOSITORY_NAME);
+ idSessionA = session.getSessionID();
+ }
+
+ @Override
+ public void run()
+ {
+ msg("Started Thread X");
+ CDOTransaction transaction = session.openTransaction();
+ Resource resource = transaction.getResource(resourcePath, true);
+
+ NodeB root = (NodeB)resource.getContents().get(0);
+ assertEquals("root", root.getName());
+
+ NodeB D = getElementFromGraphNodeB(root, "D");
+
+ assertEquals("D", D.getName());
+ D.setName("DD");
+
+ try
+ {
+ transaction.commit();
+ }
+ catch (CommitException ex)
+ {
+ exceptions.add(ex);
+ }
+
+ session.close();
+ msg("Finished Thread X");
+ }
+ }
+
+ private NodeB createSimpleNode(String name)
+ {
+ NodeB y = getModel3Factory().createNodeB();
+ y.setName(name);
+ return y;
+ }
+
+ private NodeB getElementFromGraphNodeB(NodeB node, String name)
+ {
+ if (node.getName().equals(name))
+ {
+ return node;
+ }
+
+ for (NodeB child : node.getChildren())
+ {
+ NodeB elementFromGraph = getElementFromGraphNodeB(child, name);
+ if (elementFromGraph != null)
+ {
+ return elementFromGraph;
+ }
+ }
+
+ return null;
+ }
+
+ @SuppressWarnings("unused")
+ private NodeA getElementFromGraphNodeA(NodeA node, String name)
+ {
+ if (node.getName().equals(name))
+ {
+ return node;
+ }
+ for (NodeA child : node.getChildren())
+ {
+ NodeA elementFromGraph = getElementFromGraphNodeA(child, name);
+ if (elementFromGraph != null)
+ {
+ return elementFromGraph;
+ }
+ }
+ return null;
+ }
+
+ private void restartRepository()
+ {
+ LifecycleUtil.deactivate(getRepository());
+ createRepository();
+ getRepository();
+ }
+
+ /**
+ * @author Martin Fluegge
+ */
+ private static class ThreadBShouldHaveThrownAnExceptionException extends Exception
+ {
+ private static final long serialVersionUID = 1L;
+
+ public ThreadBShouldHaveThrownAnExceptionException(String s)
+ {
+ super(s);
+ }
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/impl/RepositoryConfig.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/impl/RepositoryConfig.java
index 260e03247c..bfe29e6d89 100644
--- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/impl/RepositoryConfig.java
+++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/impl/RepositoryConfig.java
@@ -42,7 +42,10 @@ import org.eclipse.net4j.jvm.JVMUtil;
import org.eclipse.net4j.util.ObjectUtil;
import org.eclipse.net4j.util.concurrent.ConcurrencyUtil;
import org.eclipse.net4j.util.container.IManagedContainer;
+import org.eclipse.net4j.util.event.IListener;
import org.eclipse.net4j.util.io.IOUtil;
+import org.eclipse.net4j.util.lifecycle.ILifecycle;
+import org.eclipse.net4j.util.lifecycle.LifecycleEventAdapter;
import org.eclipse.net4j.util.lifecycle.LifecycleUtil;
import org.eclipse.net4j.util.security.IUserManager;
import org.eclipse.net4j.util.tests.AbstractOMTest;
@@ -70,6 +73,8 @@ public abstract class RepositoryConfig extends Config implements IRepositoryConf
protected transient Map<String, InternalRepository> repositories;
+ private transient IListener repositoryListener;
+
public RepositoryConfig(String name)
{
super(name);
@@ -110,7 +115,22 @@ public abstract class RepositoryConfig extends Config implements IRepositoryConf
{
repository = createRepository(name);
}
+ else
+ {
+ if (repository.getStore() == null)
+ {
+ IStore store = createStore(name);
+ repository.setStore((InternalStore)store);
+ }
+ if (repository.getProperties() == null)
+ {
+ Map<String, String> props = getRepositoryProperties();
+ repository.setProperties(props);
+ }
+ }
+
+ repository.addListener(repositoryListener);
repositories.put(name, repository);
LifecycleUtil.activate(repository);
}
@@ -134,6 +154,18 @@ public abstract class RepositoryConfig extends Config implements IRepositoryConf
super.setUp();
StoreThreadLocal.release();
repositories = new HashMap<String, InternalRepository>();
+ repositoryListener = new LifecycleEventAdapter()
+ {
+ @Override
+ protected void onDeactivated(ILifecycle repository)
+ {
+ synchronized (repositories)
+ {
+ repositories.remove(((IRepository)repository).getName());
+ }
+ }
+ };
+
IManagedContainer serverContainer = getCurrentTest().getServerContainer();
CDONet4jServerUtil.prepareContainer(serverContainer, new IRepositoryProvider()
{
@@ -150,7 +182,13 @@ public abstract class RepositoryConfig extends Config implements IRepositoryConf
@Override
public void tearDown() throws Exception
{
- for (Object repository : repositories.values().toArray())
+ Object[] array;
+ synchronized (repositories)
+ {
+ array = repositories.values().toArray();
+ }
+
+ for (Object repository : array)
{
LifecycleUtil.deactivate(repository);
}
@@ -278,7 +316,11 @@ public abstract class RepositoryConfig extends Config implements IRepositoryConf
master = (InternalRepository)CDOServerUtil.createRepository(masterName, masterStore, props);
}
- repositories.put(masterName, master);
+ synchronized (repositories)
+ {
+ repositories.put(masterName, master);
+ }
+
LifecycleUtil.activate(master);
startMasterTransport();
diff --git a/plugins/org.gastro.server/META-INF/MANIFEST.MF b/plugins/org.gastro.server/META-INF/MANIFEST.MF
index 173e5ccc3f..6d33401cf6 100644
--- a/plugins/org.gastro.server/META-INF/MANIFEST.MF
+++ b/plugins/org.gastro.server/META-INF/MANIFEST.MF
@@ -2,12 +2,12 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: CDO Gastro Example Server
Bundle-SymbolicName: org.gastro.server;singleton:=true
-Bundle-Version: 3.0.0.qualifier
+Bundle-Version: 4.0.0.qualifier
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.5.0,4.0.0)",
- org.eclipse.emf.cdo.server;bundle-version="[2.0.0,4.0.0)";visibility:=reexport,
- org.eclipse.emf.cdo.server.net4j;bundle-version="[3.0.0,4.0.0)",
- org.eclipse.emf.cdo.server.db;bundle-version="[2.0.0,4.0.0)",
+ org.eclipse.emf.cdo.server;bundle-version="[4.0.0,5.0.0)";visibility:=reexport,
+ org.eclipse.emf.cdo.server.net4j;bundle-version="[4.0.0,5.0.0)",
+ org.eclipse.emf.cdo.server.db;bundle-version="[4.0.0,5.0.0)",
org.eclipse.net4j.db.h2;bundle-version="[3.0.0,4.0.0)",
org.eclipse.net4j.tcp;bundle-version="[2.0.0,4.0.0)"
Bundle-Activator: org.gastro.internal.server.OM$Activator
@@ -17,6 +17,6 @@ Import-Package: org.h2;version="1.1.114",
org.h2.tools;version="[1.1.0,1.2.0)",
org.h2.util;version="[1.1.0,1.2.0)"
Bundle-Vendor: Eclipse Modeling Project
-Export-Package: org.gastro.internal.server;version="3.0.0";x-internal:=true,
- org.gastro.server;version="3.0.0"
+Export-Package: org.gastro.internal.server;version="4.0.0";x-internal:=true,
+ org.gastro.server;version="4.0.0"
Bundle-ActivationPolicy: lazy

Back to the top