summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCaspar De Groot2011-06-08 06:54:59 (EDT)
committerCaspar De Groot2011-06-08 06:54:59 (EDT)
commit4d83e5b62819ef74f598653ca158969830d87af1 (patch)
treef7f8f0f45779818d738de4de219ef81d21602f2c
parentc5d3ceacb3ab876418518d7b1bc81368c177975f (diff)
downloadcdo-4d83e5b62819ef74f598653ca158969830d87af1.zip
cdo-4d83e5b62819ef74f598653ca158969830d87af1.tar.gz
cdo-4d83e5b62819ef74f598653ca158969830d87af1.tar.bz2
[347285] Durable locking support for db4o
https://bugs.eclipse.org/bugs/show_bug.cgi?id=347285
-rw-r--r--plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lock/IDurableLockingManager.java2
-rw-r--r--plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/CDOListImpl.java2
-rw-r--r--plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/CDORevisionImpl.java4
-rw-r--r--plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DurableLockingManager.java5
-rw-r--r--plugins/org.eclipse.emf.cdo.server.db4o/META-INF/MANIFEST.MF1
-rw-r--r--plugins/org.eclipse.emf.cdo.server.db4o/src/org/eclipse/emf/cdo/server/internal/db4o/DB4ODurableLockingManager.java199
-rw-r--r--plugins/org.eclipse.emf.cdo.server.db4o/src/org/eclipse/emf/cdo/server/internal/db4o/DB4OLockArea.java119
-rw-r--r--plugins/org.eclipse.emf.cdo.server.db4o/src/org/eclipse/emf/cdo/server/internal/db4o/DB4OLockEntry.java93
-rw-r--r--plugins/org.eclipse.emf.cdo.server.db4o/src/org/eclipse/emf/cdo/server/internal/db4o/DB4ORevision.java20
-rw-r--r--plugins/org.eclipse.emf.cdo.server.db4o/src/org/eclipse/emf/cdo/server/internal/db4o/DB4OStore.java90
-rw-r--r--plugins/org.eclipse.emf.cdo.server.db4o/src/org/eclipse/emf/cdo/server/internal/db4o/DB4OStoreAccessor.java50
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/LockManager.java4
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/mem/MEMStore.java8
-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.db4o/src/org/eclipse/emf/cdo/tests/db4o/AllTestsDB4O.java105
15 files changed, 684 insertions, 23 deletions
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lock/IDurableLockingManager.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lock/IDurableLockingManager.java
index 741f86a..52f803b 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lock/IDurableLockingManager.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lock/IDurableLockingManager.java
@@ -99,7 +99,7 @@ public interface IDurableLockingManager
{
NONE(0), READ(1), WRITE(2), READ_WRITE(READ.getValue() | WRITE.getValue());
- private int value;
+ private final int value;
private LockGrade(int value)
{
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/CDOListImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/CDOListImpl.java
index 56fe0ae..a5b4926 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/CDOListImpl.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/CDOListImpl.java
@@ -40,7 +40,7 @@ public class CDOListImpl extends MoveableArrayList<Object> implements InternalCD
private static final long serialVersionUID = 1L;
- private boolean frozen;
+ private transient boolean frozen;
public CDOListImpl(int initialCapacity, int size)
{
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/CDORevisionImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/CDORevisionImpl.java
index 433d4c5..38a0fec 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/CDORevisionImpl.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/CDORevisionImpl.java
@@ -34,7 +34,7 @@ public class CDORevisionImpl extends BaseCDORevision
{
private Object[] values;
- private boolean frozen;
+ private transient boolean frozen;
public CDORevisionImpl(EClass eClass)
{
@@ -93,7 +93,7 @@ public class CDORevisionImpl extends BaseCDORevision
public void freeze()
{
frozen = true;
-
+
EStructuralFeature[] features = CDOModelUtil.getAllPersistentFeatures(getEClass());
for (int i = 0; i < features.length; i++)
{
diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DurableLockingManager.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DurableLockingManager.java
index 07d2e35..594ff99 100644
--- a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DurableLockingManager.java
+++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DurableLockingManager.java
@@ -16,13 +16,13 @@ import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockArea;
import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockArea.Handler;
import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockAreaNotFoundException;
import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockGrade;
-import org.eclipse.emf.cdo.internal.server.LockManager;
import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
import org.eclipse.emf.cdo.server.db.IIDHandler;
import org.eclipse.emf.cdo.server.db.IPreparedStatementCache;
import org.eclipse.emf.cdo.server.db.IPreparedStatementCache.ReuseProbability;
import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranchManager;
import org.eclipse.emf.cdo.spi.server.DurableLockArea;
+import org.eclipse.emf.cdo.spi.server.InternalLockManager;
import org.eclipse.net4j.db.DBException;
import org.eclipse.net4j.db.DBType;
@@ -596,9 +596,10 @@ public class DurableLockingManager extends Lifecycle
stmtUpdate = statementCache.getPreparedStatement(sqlUpdateLock, ReuseProbability.MEDIUM);
stmtUpdate.setString(2, durableLockingID);
+ InternalLockManager lockManager = accessor.getStore().getRepository().getLockManager();
for (Object key : keys)
{
- CDOID id = LockManager.getIDToLock(key);
+ CDOID id = lockManager.getLockKeyID(key);
idHandler.setCDOID(stmtSelect, 2, id);
resultSet = stmtSelect.executeQuery();
diff --git a/plugins/org.eclipse.emf.cdo.server.db4o/META-INF/MANIFEST.MF b/plugins/org.eclipse.emf.cdo.server.db4o/META-INF/MANIFEST.MF
index 96e17d1..f77863e 100644
--- a/plugins/org.eclipse.emf.cdo.server.db4o/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.emf.cdo.server.db4o/META-INF/MANIFEST.MF
@@ -11,6 +11,7 @@ Export-Package: org.eclipse.emf.cdo.server.db4o;version="1.0.0",
org.eclipse.emf.cdo.server.internal.db4o.bundle;version="1.0.0";x-internal:=true
Import-Package: com.db4o;version="[7.4.0,8.0.0)",
com.db4o.config;version="[7.4.0,8.0.0)",
+ com.db4o.constraints;version="[7.4.0,8.0.0)",
com.db4o.ext;version="[7.4.0,8.0.0)",
com.db4o.query;version="[7.4.0,8.0.0)",
com.db4o.reflect;version="[7.4.0,8.0.0)",
diff --git a/plugins/org.eclipse.emf.cdo.server.db4o/src/org/eclipse/emf/cdo/server/internal/db4o/DB4ODurableLockingManager.java b/plugins/org.eclipse.emf.cdo.server.db4o/src/org/eclipse/emf/cdo/server/internal/db4o/DB4ODurableLockingManager.java
new file mode 100644
index 0000000..2efdf7e
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.server.db4o/src/org/eclipse/emf/cdo/server/internal/db4o/DB4ODurableLockingManager.java
@@ -0,0 +1,199 @@
+/**
+ * Copyright (c) 2004 - 2011 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:
+ * Caspar De Groot - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server.internal.db4o;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockArea;
+import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockArea.Handler;
+import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockAreaNotFoundException;
+import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockGrade;
+import org.eclipse.emf.cdo.spi.server.DurableLockArea;
+import org.eclipse.emf.cdo.spi.server.InternalLockManager;
+
+import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
+import org.eclipse.net4j.util.lifecycle.Lifecycle;
+
+import com.db4o.ObjectContainer;
+import com.db4o.ObjectSet;
+import com.db4o.query.Query;
+
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * @author Caspar De Groot
+ */
+public class DB4ODurableLockingManager extends Lifecycle
+{
+ public DB4ODurableLockingManager()
+ {
+ }
+
+ public LockArea createLockArea(DB4OStoreAccessor accessor, String userID, CDOBranchPoint branchPoint,
+ boolean readOnly, Map<CDOID, LockGrade> locks)
+ {
+ String durableLockingID = getNextDurableLockingID(accessor);
+ LockArea lockArea = new DurableLockArea(durableLockingID, userID, branchPoint, readOnly, locks);
+ storeLockArea(accessor, lockArea);
+ return lockArea;
+ }
+
+ private void storeLockArea(DB4OStoreAccessor accessor, LockArea area)
+ {
+ ObjectContainer objectContainer = accessor.getObjectContainer();
+ DB4OLockArea primitiveLockArea = DB4OLockArea.getPrimitiveLockArea(area);
+ objectContainer.store(primitiveLockArea);
+ objectContainer.commit();
+ }
+
+ public LockArea getLockArea(DB4OStoreAccessor accessor, String durableLockingID) throws LockAreaNotFoundException
+ {
+ DB4OLockArea primitive = getPrimitiveLockArea(accessor, durableLockingID);
+ return DB4OLockArea.getLockArea(accessor.getStore(), primitive);
+ }
+
+ private DB4OLockArea getPrimitiveLockArea(DB4OStoreAccessor accessor, String durableLockingID)
+ throws LockAreaNotFoundException
+ {
+ ObjectContainer container = accessor.getObjectContainer();
+ Query query = container.query();
+ query.constrain(DB4OLockArea.class);
+ query.descend("id").constrain(durableLockingID);
+
+ ObjectSet<?> lockAreas = query.execute();
+ if (lockAreas.isEmpty())
+ {
+ throw new LockAreaNotFoundException(durableLockingID);
+ }
+
+ if (lockAreas.size() > 1)
+ {
+ throw new AssertionError("Lockarea stored more than once in object database");
+ }
+
+ return (DB4OLockArea)lockAreas.get(0);
+ }
+
+ public void getLockAreas(DB4OStoreAccessor accessor, String userIDPrefix, Handler handler)
+ {
+ ObjectContainer container = accessor.getObjectContainer();
+ Query query = container.query();
+ query.constrain(DB4OLockArea.class);
+
+ if (userIDPrefix.length() > 0)
+ {
+ query.descend("userID").constrain(userIDPrefix).startsWith(true);
+ }
+
+ ObjectSet<?> primitives = query.execute();
+ for (Object primitive : primitives)
+ {
+ LockArea area = DB4OLockArea.getLockArea(accessor.getStore(), (DB4OLockArea)primitive);
+ if (!handler.handleLockArea(area))
+ {
+ break;
+ }
+ }
+ }
+
+ public void deleteLockArea(DB4OStoreAccessor accessor, String durableLockingID)
+ {
+ DB4OLockArea primitive = getPrimitiveLockArea(accessor, durableLockingID);
+ ObjectContainer container = accessor.getObjectContainer();
+ container.delete(primitive);
+ container.commit();
+ }
+
+ public void lock(DB4OStoreAccessor accessor, String durableLockingID, LockType type,
+ Collection<? extends Object> objectsToLock)
+ {
+ // TODO (CD) Refactor? Next chunk of code copied verbatim from MEMStore.lock
+ LockArea area = getLockArea(accessor, durableLockingID);
+ Map<CDOID, LockGrade> locks = area.getLocks();
+
+ InternalLockManager lockManager = accessor.getStore().getRepository().getLockManager();
+ for (Object objectToLock : objectsToLock)
+ {
+ CDOID id = lockManager.getLockKeyID(objectToLock);
+ LockGrade grade = locks.get(id);
+ if (grade != null)
+ {
+ grade = grade.getUpdated(type, true);
+ }
+ else
+ {
+ grade = LockGrade.get(type);
+ }
+
+ locks.put(id, grade);
+ }
+
+ storeLockArea(accessor, area);
+ }
+
+ public void unlock(DB4OStoreAccessor accessor, String durableLockingID, LockType type,
+ Collection<? extends Object> objectsToUnlock)
+ {
+ // TODO (CD) Refactor? Next chunk of code copied verbatim from MEMStore.lock
+ LockArea area = getLockArea(accessor, durableLockingID);
+ Map<CDOID, LockGrade> locks = area.getLocks();
+
+ InternalLockManager lockManager = accessor.getStore().getRepository().getLockManager();
+ for (Object objectToUnlock : objectsToUnlock)
+ {
+ CDOID id = lockManager.getLockKeyID(objectToUnlock);
+ LockGrade grade = locks.get(id);
+ if (grade != null)
+ {
+ grade = grade.getUpdated(type, false);
+ if (grade == LockGrade.NONE)
+ {
+ locks.remove(id);
+ }
+ else
+ {
+ locks.put(id, grade);
+ }
+ }
+ }
+
+ storeLockArea(accessor, area);
+ }
+
+ public void unlock(DB4OStoreAccessor accessor, String durableLockingID)
+ {
+ LockArea area = getLockArea(accessor, durableLockingID);
+ Map<CDOID, LockGrade> locks = area.getLocks();
+ locks.clear();
+
+ storeLockArea(accessor, area);
+ }
+
+ // TODO: Refactor -- this was copied verbatim from DurableLockingManager
+ private String getNextDurableLockingID(DB4OStoreAccessor accessor)
+ {
+ for (;;)
+ {
+ String durableLockingID = DurableLockArea.createDurableLockingID();
+
+ try
+ {
+ getLockArea(accessor, durableLockingID); // Check uniqueness
+ // Not unique; try once more...
+ }
+ catch (LockAreaNotFoundException ex)
+ {
+ return durableLockingID;
+ }
+ }
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.server.db4o/src/org/eclipse/emf/cdo/server/internal/db4o/DB4OLockArea.java b/plugins/org.eclipse.emf.cdo.server.db4o/src/org/eclipse/emf/cdo/server/internal/db4o/DB4OLockArea.java
new file mode 100644
index 0000000..35d248e
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.server.db4o/src/org/eclipse/emf/cdo/server/internal/db4o/DB4OLockArea.java
@@ -0,0 +1,119 @@
+/**
+ * Copyright (c) 2004 - 2011 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:
+ * Caspar De Groot - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server.internal.db4o;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.branch.CDOBranchManager;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.id.CDOIDUtil;
+import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockArea;
+import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockGrade;
+import org.eclipse.emf.cdo.server.db4o.IDB4OStore;
+import org.eclipse.emf.cdo.spi.server.DurableLockArea;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Caspar De Groot
+ */
+public class DB4OLockArea
+{
+ private static Map<LockArea, DB4OLockArea> map = new HashMap<LockArea, DB4OLockArea>();
+
+ private String id;
+
+ private String userID;
+
+ private long timestamp;
+
+ private int branchID;
+
+ private boolean readOnly;
+
+ private List<DB4OLockEntry> lockEntries = new LinkedList<DB4OLockEntry>();
+
+ public static DB4OLockArea getPrimitiveLockArea(LockArea lockArea)
+ {
+ DB4OLockArea primitive = map.get(lockArea);
+ if (primitive == null)
+ {
+ primitive = new DB4OLockArea();
+ }
+
+ primitive.id = lockArea.getDurableLockingID();
+ primitive.userID = lockArea.getUserID();
+ primitive.timestamp = lockArea.getTimeStamp();
+ primitive.branchID = lockArea.getBranch().getID();
+ primitive.readOnly = lockArea.isReadOnly();
+
+ List<DB4OLockEntry> newList = DB4OLockEntry.getPrimitiveLockEntries(primitive, lockArea.getLocks());
+ primitive.lockEntries = newList;
+
+ return primitive;
+ }
+
+ public static LockArea getLockArea(IDB4OStore store, DB4OLockArea primitive)
+ {
+ // Reconstruct the branchpoint
+ //
+ CDOBranchManager branchManager = store.getRepository().getBranchManager();
+ CDOBranch branch = branchManager.getBranch(primitive.branchID);
+ CDOBranchPoint branchpoint = branch.getPoint(primitive.timestamp);
+
+ // Reconstruct the lockMap
+ //
+ Map<CDOID, LockGrade> lockMap = new HashMap<CDOID, LockGrade>();
+ for (DB4OLockEntry entry : primitive.getLockEntries())
+ {
+ CDOID cdoid = CDOIDUtil.createLong(entry.getCdoID());
+ LockGrade lockGrade = LockGrade.get(entry.getLockGrade());
+ lockMap.put(cdoid, lockGrade);
+ }
+
+ LockArea lockArea = new DurableLockArea(primitive.id, primitive.userID, branchpoint, primitive.readOnly, lockMap);
+ map.put(lockArea, primitive);
+ return lockArea;
+ }
+
+ public void setId(String id)
+ {
+ this.id = id;
+ }
+
+ public String getId()
+ {
+ return id;
+ }
+
+ public String getUserID()
+ {
+ return userID;
+ }
+
+ public long getTimestamp()
+ {
+ return timestamp;
+ }
+
+ public int getBranchID()
+ {
+ return branchID;
+ }
+
+ public List<DB4OLockEntry> getLockEntries()
+ {
+ return lockEntries;
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.server.db4o/src/org/eclipse/emf/cdo/server/internal/db4o/DB4OLockEntry.java b/plugins/org.eclipse.emf.cdo.server.db4o/src/org/eclipse/emf/cdo/server/internal/db4o/DB4OLockEntry.java
new file mode 100644
index 0000000..267c5c2
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.server.db4o/src/org/eclipse/emf/cdo/server/internal/db4o/DB4OLockEntry.java
@@ -0,0 +1,93 @@
+/**
+ * Copyright (c) 2004 - 2011 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:
+ * Caspar De Groot - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server.internal.db4o;
+
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.id.CDOIDUtil;
+import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockGrade;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+/**
+ * @author Caspar De Groot
+ */
+public class DB4OLockEntry
+{
+ private long cdoID;
+
+ private int lockGrade;
+
+ public DB4OLockEntry(long longCdoID, int intLockGrade)
+ {
+ cdoID = longCdoID;
+ lockGrade = intLockGrade;
+ }
+
+ public static List<DB4OLockEntry> getPrimitiveLockEntries(DB4OLockArea primitive, Map<CDOID, LockGrade> locks)
+ {
+ List<DB4OLockEntry> newList = new LinkedList<DB4OLockEntry>();
+
+ for (Entry<CDOID, LockGrade> entry : locks.entrySet())
+ {
+ CDOID cdoid = entry.getKey();
+ long longCdoID = CDOIDUtil.getLong(cdoid);
+
+ LockGrade lockGrade = entry.getValue();
+ int intLockGrade = lockGrade.getValue();
+
+ DB4OLockEntry lockEntry = getEntry(primitive.getLockEntries(), longCdoID);
+ if (lockEntry == null)
+ {
+ lockEntry = new DB4OLockEntry(longCdoID, intLockGrade);
+ }
+ else
+ {
+ lockEntry.setLockGrade(intLockGrade);
+ }
+
+ newList.add(lockEntry);
+ }
+
+ return newList;
+ }
+
+ private void setLockGrade(int lockGrade)
+ {
+ this.lockGrade = lockGrade;
+ }
+
+ // TODO (CD) Avoid linear search
+ private static DB4OLockEntry getEntry(List<DB4OLockEntry> entries, long targetID)
+ {
+ for (DB4OLockEntry entry : entries)
+ {
+ if (entry.cdoID == targetID)
+ {
+ return entry;
+ }
+ }
+
+ return null;
+ }
+
+ public long getCdoID()
+ {
+ return cdoID;
+ }
+
+ public int getLockGrade()
+ {
+ return lockGrade;
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.server.db4o/src/org/eclipse/emf/cdo/server/internal/db4o/DB4ORevision.java b/plugins/org.eclipse.emf.cdo.server.db4o/src/org/eclipse/emf/cdo/server/internal/db4o/DB4ORevision.java
index a4ae8d3..d8090ba 100644
--- a/plugins/org.eclipse.emf.cdo.server.db4o/src/org/eclipse/emf/cdo/server/internal/db4o/DB4ORevision.java
+++ b/plugins/org.eclipse.emf.cdo.server.db4o/src/org/eclipse/emf/cdo/server/internal/db4o/DB4ORevision.java
@@ -19,6 +19,7 @@ import org.eclipse.emf.cdo.common.model.CDOClassInfo;
import org.eclipse.emf.cdo.common.revision.CDOList;
import org.eclipse.emf.cdo.common.revision.CDOListFactory;
import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionData;
import org.eclipse.emf.cdo.common.revision.CDORevisionFactory;
import org.eclipse.emf.cdo.common.revision.CDORevisionUtil;
import org.eclipse.emf.cdo.server.IRepository;
@@ -272,6 +273,12 @@ public class DB4ORevision
}
else
{
+ // Prevent the explicit null-ref "NIL" from being serialized!
+ if (obj == CDORevisionData.NIL)
+ {
+ obj = new ExplicitNull();
+ }
+
values.add(i, obj);
}
}
@@ -322,6 +329,12 @@ public class DB4ORevision
value = DB4OFeatureMapEntry.getCDOFeatureMapEntryList(eClass, value);
}
+ // Convert 'null' into the explicit null-ref "NIL" if appropriate
+ if (value instanceof ExplicitNull)
+ {
+ value = CDORevisionData.NIL;
+ }
+
revision.setValue(feature, value);
}
@@ -440,4 +453,11 @@ public class DB4ORevision
return list;
}
}
+
+ /**
+ * @author Caspar De Groot
+ */
+ private static final class ExplicitNull
+ {
+ }
}
diff --git a/plugins/org.eclipse.emf.cdo.server.db4o/src/org/eclipse/emf/cdo/server/internal/db4o/DB4OStore.java b/plugins/org.eclipse.emf.cdo.server.db4o/src/org/eclipse/emf/cdo/server/internal/db4o/DB4OStore.java
index 901ee7a..518a1fc 100644
--- a/plugins/org.eclipse.emf.cdo.server.db4o/src/org/eclipse/emf/cdo/server/internal/db4o/DB4OStore.java
+++ b/plugins/org.eclipse.emf.cdo.server.db4o/src/org/eclipse/emf/cdo/server/internal/db4o/DB4OStore.java
@@ -23,12 +23,14 @@ import org.eclipse.emf.cdo.spi.server.LongIDStore;
import org.eclipse.emf.cdo.spi.server.StoreAccessorPool;
import org.eclipse.net4j.util.ReflectUtil.ExcludeFromDump;
+import org.eclipse.net4j.util.lifecycle.LifecycleUtil;
import com.db4o.Db4o;
import com.db4o.ObjectContainer;
import com.db4o.ObjectServer;
import com.db4o.ObjectSet;
import com.db4o.config.Configuration;
+import com.db4o.constraints.UniqueFieldValueConstraint;
import com.db4o.query.Query;
import com.db4o.reflect.jdk.JdkReflector;
@@ -56,6 +58,8 @@ public class DB4OStore extends LongIDStore implements IDB4OStore
private ServerInfo serverInfo;
+ private DB4ODurableLockingManager durableLockingManager = new DB4ODurableLockingManager();
+
@ExcludeFromDump
private transient final StoreAccessorPool readerPool = new StoreAccessorPool(this, null);
@@ -105,6 +109,11 @@ public class DB4OStore extends LongIDStore implements IDB4OStore
return getServerInfo().isFirstTime();
}
+ public DB4ODurableLockingManager getDurableLockingManager()
+ {
+ return durableLockingManager;
+ }
+
public Map<String, String> getPersistentProperties(Set<String> names)
{
if (names == null || names.isEmpty())
@@ -167,6 +176,32 @@ public class DB4OStore extends LongIDStore implements IDB4OStore
initObjectServer();
initServerInfo();
setLastCommitTime(getServerInfo().getLastCommitTime());
+ setLastObjectID(fetchLastObjectID());
+ LifecycleUtil.activate(durableLockingManager);
+ }
+
+ private long fetchLastObjectID()
+ {
+ ObjectContainer container = openClient();
+
+ try
+ {
+ Query query = container.query();
+ query.constrain(DB4ORevision.class);
+ query.descend("id").orderDescending();
+ ObjectSet<?> results = query.execute();
+ int size = results.size();
+ if (size > 0)
+ {
+ DB4ORevision rev = (DB4ORevision)results.next();
+ return rev.getID();
+ }
+ return 0;
+ }
+ finally
+ {
+ closeClient(container);
+ }
}
protected void initObjectServer()
@@ -216,13 +251,9 @@ public class DB4OStore extends LongIDStore implements IDB4OStore
try
{
- ObjectSet<ServerInfo> infos = container.query(ServerInfo.class);
- if (infos.size() > 1)
- {
- throw new IllegalStateException("ServeInfo is stored in container more than once");
- }
+ serverInfo = getServerInfoFromDatabase(container);
- if (infos.isEmpty())
+ if (serverInfo == null)
{
serverInfo = new ServerInfo();
serverInfo.setFirstTime(true);
@@ -231,7 +262,6 @@ public class DB4OStore extends LongIDStore implements IDB4OStore
}
else
{
- serverInfo = infos.get(0);
if (serverInfo.isFirstTime())
{
serverInfo.setFirstTime(false);
@@ -245,6 +275,22 @@ public class DB4OStore extends LongIDStore implements IDB4OStore
}
}
+ private ServerInfo getServerInfoFromDatabase(ObjectContainer container)
+ {
+ ObjectSet<ServerInfo> infos = container.query(ServerInfo.class);
+ if (infos.size() > 1)
+ {
+ throw new IllegalStateException("ServeInfo is stored in container more than once");
+ }
+
+ if (infos.size() == 1)
+ {
+ return infos.get(0);
+ }
+
+ return null;
+ }
+
protected void closeClient(ObjectContainer container)
{
container.close();
@@ -256,6 +302,16 @@ public class DB4OStore extends LongIDStore implements IDB4OStore
try
{
+ ServerInfo storedInfo = getServerInfoFromDatabase(usedContainer);
+ if (storedInfo != null && storedInfo != serverInfo)
+ {
+ storedInfo.setCreationTime(serverInfo.getCreationTime());
+ storedInfo.setFirstTime(serverInfo.isFirstTime());
+ storedInfo.setLastCommitTime(serverInfo.getLastCommitTime());
+ storedInfo.setProperties(serverInfo.getProperties());
+ serverInfo = storedInfo;
+ }
+
usedContainer.store(serverInfo);
usedContainer.commit();
}
@@ -271,8 +327,8 @@ public class DB4OStore extends LongIDStore implements IDB4OStore
@Override
protected void doDeactivate() throws Exception
{
- tearDownObjectServer();
ObjectContainer container = openClient();
+
try
{
getServerInfo().setLastCommitTime(getLastCommitTime());
@@ -282,6 +338,10 @@ public class DB4OStore extends LongIDStore implements IDB4OStore
{
closeClient(container);
}
+
+ LifecycleUtil.deactivate(durableLockingManager);
+ tearDownObjectServer();
+
super.doDeactivate();
}
@@ -289,10 +349,23 @@ public class DB4OStore extends LongIDStore implements IDB4OStore
{
Configuration config = Db4o.newConfiguration();
config.reflectWith(new JdkReflector(getClass().getClassLoader()));
+
config.objectClass(DB4ORevision.class).objectField("id").indexed(true);
+ config.add(new UniqueFieldValueConstraint(DB4ORevision.class, "id"));
+
config.objectClass(DB4OPackageUnit.class).objectField("id").indexed(true);
+ config.add(new UniqueFieldValueConstraint(DB4OPackageUnit.class, "id"));
+
config.objectClass(DB4OIdentifiableObject.class).objectField("id").indexed(true);
+ config.add(new UniqueFieldValueConstraint(DB4OIdentifiableObject.class, "id"));
+
config.objectClass(DB4OCommitInfo.class).objectField("timeStamp").indexed(true);
+
+ config.objectClass(DB4OLockArea.class).objectField("id").indexed(true);
+ config.add(new UniqueFieldValueConstraint(DB4OLockArea.class, "id"));
+ config.objectClass(DB4OLockArea.class).cascadeOnUpdate(true);
+ config.objectClass(DB4OLockArea.class).cascadeOnDelete(true);
+
return config;
}
@@ -400,7 +473,6 @@ public class DB4OStore extends LongIDStore implements IDB4OStore
return creationTime;
}
- @SuppressWarnings("unused")
public void setProperties(Map<String, String> properties)
{
this.properties = properties;
diff --git a/plugins/org.eclipse.emf.cdo.server.db4o/src/org/eclipse/emf/cdo/server/internal/db4o/DB4OStoreAccessor.java b/plugins/org.eclipse.emf.cdo.server.db4o/src/org/eclipse/emf/cdo/server/internal/db4o/DB4OStoreAccessor.java
index b65e4db..5040ca8 100644
--- a/plugins/org.eclipse.emf.cdo.server.db4o/src/org/eclipse/emf/cdo/server/internal/db4o/DB4OStoreAccessor.java
+++ b/plugins/org.eclipse.emf.cdo.server.db4o/src/org/eclipse/emf/cdo/server/internal/db4o/DB4OStoreAccessor.java
@@ -18,6 +18,7 @@ import org.eclipse.emf.cdo.common.commit.CDOCommitInfoHandler;
import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.common.id.CDOIDUtil;
import org.eclipse.emf.cdo.common.lob.CDOLobHandler;
+import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockArea.Handler;
import org.eclipse.emf.cdo.common.model.EMFUtil;
import org.eclipse.emf.cdo.common.protocol.CDODataInput;
import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
@@ -29,7 +30,8 @@ import org.eclipse.emf.cdo.common.util.CDOQueryInfo;
import org.eclipse.emf.cdo.eresource.EresourcePackage;
import org.eclipse.emf.cdo.server.IQueryHandler;
import org.eclipse.emf.cdo.server.ISession;
-import org.eclipse.emf.cdo.server.IStoreAccessor;
+import org.eclipse.emf.cdo.server.IStoreAccessor.DurableLocking;
+import org.eclipse.emf.cdo.server.IStoreAccessor.Raw;
import org.eclipse.emf.cdo.server.IStoreChunkReader;
import org.eclipse.emf.cdo.server.ITransaction;
import org.eclipse.emf.cdo.server.db4o.IDB4OIdentifiableObject;
@@ -47,6 +49,7 @@ import org.eclipse.net4j.util.HexUtil;
import org.eclipse.net4j.util.ObjectUtil;
import org.eclipse.net4j.util.StringUtil;
import org.eclipse.net4j.util.collection.Pair;
+import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
import org.eclipse.net4j.util.io.IOUtil;
import org.eclipse.net4j.util.om.monitor.Monitor;
import org.eclipse.net4j.util.om.monitor.OMMonitor;
@@ -85,7 +88,7 @@ import java.util.Set;
/**
* @author Victor Roldan Betancort
*/
-public class DB4OStoreAccessor extends LongIDStoreAccessor implements IStoreAccessor.Raw
+public class DB4OStoreAccessor extends LongIDStoreAccessor implements Raw, DurableLocking
{
private ObjectContainer objectContainer;
@@ -827,4 +830,47 @@ public class DB4OStoreAccessor extends LongIDStoreAccessor implements IStoreAcce
{
doCommit(monitor);
}
+
+ public LockArea createLockArea(String userID, CDOBranchPoint branchPoint, boolean readOnly,
+ Map<CDOID, LockGrade> locks)
+ {
+ DB4ODurableLockingManager manager = getStore().getDurableLockingManager();
+ return manager.createLockArea(this, userID, branchPoint, readOnly, locks);
+ }
+
+ public LockArea getLockArea(String durableLockingID) throws LockAreaNotFoundException
+ {
+ DB4ODurableLockingManager manager = getStore().getDurableLockingManager();
+ return manager.getLockArea(this, durableLockingID);
+ }
+
+ public void getLockAreas(String userIDPrefix, Handler handler)
+ {
+ DB4ODurableLockingManager manager = getStore().getDurableLockingManager();
+ manager.getLockAreas(this, userIDPrefix, handler);
+ }
+
+ public void deleteLockArea(String durableLockingID)
+ {
+ DB4ODurableLockingManager manager = getStore().getDurableLockingManager();
+ manager.deleteLockArea(this, durableLockingID);
+ }
+
+ public void lock(String durableLockingID, LockType type, Collection<? extends Object> objectsToLock)
+ {
+ DB4ODurableLockingManager manager = getStore().getDurableLockingManager();
+ manager.lock(this, durableLockingID, type, objectsToLock);
+ }
+
+ public void unlock(String durableLockingID, LockType type, Collection<? extends Object> objectsToUnlock)
+ {
+ DB4ODurableLockingManager manager = getStore().getDurableLockingManager();
+ manager.unlock(this, durableLockingID, type, objectsToUnlock);
+ }
+
+ public void unlock(String durableLockingID)
+ {
+ DB4ODurableLockingManager manager = getStore().getDurableLockingManager();
+ manager.unlock(this, durableLockingID);
+ }
}
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 74318dd..ad6c3a7 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
@@ -129,7 +129,7 @@ public class LockManager extends RWLockManager<Object, IView> implements Interna
{
public boolean handleLockEntry(LockEntry<Object, IView> lockEntry)
{
- CDOID id = getIDToLock(lockEntry.getObject());
+ CDOID id = getLockKeyID(lockEntry.getObject());
LockGrade grade = LockGrade.NONE;
if (lockEntry.isReadLock(view))
{
@@ -364,7 +364,7 @@ public class LockManager extends RWLockManager<Object, IView> implements Interna
}
}
- public static CDOID getIDToLock(Object key)
+ public CDOID getLockKeyID(Object key)
{
if (key instanceof CDOID)
{
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/mem/MEMStore.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/mem/MEMStore.java
index df70bf7..6afe13c 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/mem/MEMStore.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/mem/MEMStore.java
@@ -29,7 +29,6 @@ import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
import org.eclipse.emf.cdo.common.revision.CDORevision;
import org.eclipse.emf.cdo.common.revision.CDORevisionHandler;
import org.eclipse.emf.cdo.common.util.CDOCommonUtil;
-import org.eclipse.emf.cdo.internal.server.LockManager;
import org.eclipse.emf.cdo.server.ISession;
import org.eclipse.emf.cdo.server.IStoreAccessor;
import org.eclipse.emf.cdo.server.IStoreAccessor.DurableLocking;
@@ -47,6 +46,7 @@ import org.eclipse.emf.cdo.spi.common.revision.DetachedCDORevision;
import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
import org.eclipse.emf.cdo.spi.common.revision.SyntheticCDORevision;
import org.eclipse.emf.cdo.spi.server.DurableLockArea;
+import org.eclipse.emf.cdo.spi.server.InternalLockManager;
import org.eclipse.emf.cdo.spi.server.LongIDStore;
import org.eclipse.emf.cdo.spi.server.StoreAccessorPool;
@@ -757,9 +757,10 @@ public class MEMStore extends LongIDStore implements IMEMStore, BranchLoader, Du
LockArea area = getLockArea(durableLockingID);
Map<CDOID, LockGrade> locks = area.getLocks();
+ InternalLockManager lockManager = getRepository().getLockManager();
for (Object objectToLock : objectsToLock)
{
- CDOID id = LockManager.getIDToLock(objectToLock);
+ CDOID id = lockManager.getLockKeyID(objectToLock);
LockGrade grade = locks.get(id);
if (grade != null)
{
@@ -779,9 +780,10 @@ public class MEMStore extends LongIDStore implements IMEMStore, BranchLoader, Du
LockArea area = getLockArea(durableLockingID);
Map<CDOID, LockGrade> locks = area.getLocks();
+ InternalLockManager lockManager = getRepository().getLockManager();
for (Object objectToUnlock : objectsToUnlock)
{
- CDOID id = LockManager.getIDToLock(objectToUnlock);
+ CDOID id = lockManager.getLockKeyID(objectToUnlock);
LockGrade grade = locks.get(id);
if (grade != null)
{
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 a7a7c5c..e7bd2e6 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
@@ -50,6 +50,11 @@ public interface InternalLockManager extends IRWLockManager<Object, IView>, IDur
/**
* @since 4.0
*/
+ public CDOID getLockKeyID(Object key);
+
+ /**
+ * @since 4.0
+ */
public Map<CDOID, LockGrade> getLocks(IView view);
/**
diff --git a/plugins/org.eclipse.emf.cdo.tests.db4o/src/org/eclipse/emf/cdo/tests/db4o/AllTestsDB4O.java b/plugins/org.eclipse.emf.cdo.tests.db4o/src/org/eclipse/emf/cdo/tests/db4o/AllTestsDB4O.java
index 87eb709..16e0a77 100644
--- a/plugins/org.eclipse.emf.cdo.tests.db4o/src/org/eclipse/emf/cdo/tests/db4o/AllTestsDB4O.java
+++ b/plugins/org.eclipse.emf.cdo.tests.db4o/src/org/eclipse/emf/cdo/tests/db4o/AllTestsDB4O.java
@@ -12,13 +12,24 @@ package org.eclipse.emf.cdo.tests.db4o;
import org.eclipse.emf.cdo.server.IRepository;
import org.eclipse.emf.cdo.server.IStore;
+import org.eclipse.emf.cdo.server.internal.db4o.DB4OStore;
import org.eclipse.emf.cdo.tests.AllConfigs;
+import org.eclipse.emf.cdo.tests.BranchingSameSessionTest;
+import org.eclipse.emf.cdo.tests.BranchingTest;
+import org.eclipse.emf.cdo.tests.BranchingWithCacheClearTest;
import org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_261218_Test;
+import org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_324585_Test;
import org.eclipse.emf.cdo.tests.config.impl.ConfigTest;
import org.eclipse.emf.cdo.tests.config.impl.RepositoryConfig;
+import org.eclipse.net4j.util.io.TMPUtil;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.ServerSocket;
import java.util.List;
import java.util.Map;
+import java.util.Random;
import junit.framework.Test;
import junit.framework.TestSuite;
@@ -41,6 +52,12 @@ public class AllTestsDB4O extends AllConfigs
// Added here testcases to skip
// takes too much
testClasses.remove(Bugzilla_261218_Test.class);
+ testClasses.remove(Bugzilla_324585_Test.class);
+
+ // db4o doesn't support branching
+ testClasses.remove(BranchingTest.class);
+ testClasses.remove(BranchingSameSessionTest.class);
+ testClasses.remove(BranchingWithCacheClearTest.class);
}
@Override
@@ -54,10 +71,14 @@ public class AllTestsDB4O extends AllConfigs
*/
public static class DB4ORepositoryConfig extends RepositoryConfig
{
+ private static final Random RANDOM = new Random(System.currentTimeMillis());
+
public static final DB4ORepositoryConfig INSTANCE = new DB4ORepositoryConfig("DB4O");
private static final long serialVersionUID = 1L;
+ private transient boolean optimizing = true;
+
public DB4ORepositoryConfig(String name)
{
super(name);
@@ -74,8 +95,90 @@ public class AllTestsDB4O extends AllConfigs
@Override
protected IStore createStore(String repoName)
{
- MEMDB4OStore.clearContainer();
+ File tempFolder = TMPUtil.getTempFolder();
+ File file = new File(tempFolder, "cdodb_" + repoName + ".db4o");
+ if (file.exists() && !isRestarting())
+ {
+ file.delete();
+ }
+
+ int port = 0;
+ boolean ok = false;
+ do
+ {
+ ServerSocket sock = null;
+ try
+ {
+ port = 1024 + RANDOM.nextInt(65536 - 1024);
+ sock = new ServerSocket(port);
+ ok = true;
+ }
+ catch (IOException e)
+ {
+ }
+ finally
+ {
+ try
+ {
+ if (sock != null)
+ {
+ sock.close();
+ }
+ }
+ catch (IOException e)
+ {
+ }
+ }
+ } while (!ok);
+
+ IStore store = new DB4OStore(file.getPath(), port);
+ return store;
+ }
+
+ @Override
+ protected boolean isOptimizing()
+ {
+ // Do NOT replace this with a hardcoded value!
+ return optimizing;
+ }
+ }
+
+ public static class MemDB4ORepositoryConfig extends RepositoryConfig
+ {
+ public static final MemDB4ORepositoryConfig INSTANCE = new MemDB4ORepositoryConfig("DB4O");
+
+ private static final long serialVersionUID = 1L;
+
+ private transient boolean optimizing = false;
+
+ public MemDB4ORepositoryConfig(String name)
+ {
+ super(name);
+ }
+
+ @Override
+ protected void initRepositoryProperties(Map<String, String> props)
+ {
+ super.initRepositoryProperties(props);
+ props.put(IRepository.Props.SUPPORTING_AUDITS, "false");
+ props.put(IRepository.Props.SUPPORTING_BRANCHES, "false");
+ }
+
+ @Override
+ protected IStore createStore(String repoName)
+ {
+ if (!isRestarting())
+ {
+ MEMDB4OStore.clearContainer();
+ }
return new MEMDB4OStore();
}
+
+ @Override
+ protected boolean isOptimizing()
+ {
+ // Do NOT replace this with a hardcoded value!
+ return optimizing;
+ }
}
}