Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDOProtocolConstants.java31
-rw-r--r--plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/CDOClientProtocol.java77
-rw-r--r--plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/UnitRequest.java74
-rw-r--r--plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/IDBStoreAccessor.java3
-rw-r--r--plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/IClassMappingUnitSupport.java30
-rw-r--r--plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/IListMapping3.java22
-rw-r--r--plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/IListMappingUnitSupport.java33
-rw-r--r--plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStore.java17
-rw-r--r--plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStoreAccessor.java41
-rw-r--r--plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/AbstractMappingStrategy.java16
-rw-r--r--plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AbstractBasicListTableMapping.java10
-rw-r--r--plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AbstractHorizontalClassMapping.java131
-rw-r--r--plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AuditListTableMappingWithRanges.java504
-rw-r--r--plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalAuditClassMapping.java362
-rw-r--r--plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalNonAuditClassMapping.java2
-rw-r--r--plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/ObjectTypeTable.java9
-rw-r--r--plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/UnitMappingTable.java255
-rw-r--r--plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CDOServerProtocol.java3
-rw-r--r--plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/UnitIndication.java102
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Repository.java55
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/ServerCDOView.java6
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/TransactionCommitContext.java3
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/UnitManager.java282
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/View.java85
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/embedded/EmbeddedClientSessionProtocol.java5
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IRepository.java10
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IStoreAccessor.java16
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IUnit.java31
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IUnitManager.java33
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalRepository.java5
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalView.java7
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/Store.java7
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/StoreAccessor.java4
-rw-r--r--plugins/org.eclipse.emf.cdo.tests.db/CDO AllTests (H2 audit).launch2
-rw-r--r--plugins/org.eclipse.emf.cdo.tests.db/src/org/eclipse/emf/cdo/tests/db/MysqlConfig.java8
-rw-r--r--plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AllConfigs.java3
-rw-r--r--plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/CDOStaleReferencePolicyTest.java (renamed from plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/CDOStaleReferencePolicyTests.java)2
-rw-r--r--plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/UnitManagerMain.java291
-rw-r--r--plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/UnitManagerTest.java170
-rw-r--r--plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_485961_Test.java3
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOPushTransaction.java9
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/view/CDOUnit.java26
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/view/CDOUnitManager.java52
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/view/CDOView.java5
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/DelegatingSessionProtocol.java16
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOViewImpl.java256
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/CDOSessionProtocol.java6
-rw-r--r--plugins/org.eclipse.net4j.db.h2/H2 Browser.launch13
48 files changed, 2739 insertions, 394 deletions
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDOProtocolConstants.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDOProtocolConstants.java
index d9196795c5..72fa700a76 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDOProtocolConstants.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDOProtocolConstants.java
@@ -30,8 +30,9 @@ public interface CDOProtocolConstants
* @since 4.2
* @noreference This field is not intended to be referenced by clients.
*/
- public static final int PROTOCOL_VERSION = 28; // SIGNAL_RESET_TRANSACTION
+ public static final int PROTOCOL_VERSION = 29; // SIGNAL_UNIT
+ // public static final int PROTOCOL_VERSION = 28; // SIGNAL_RESET_TRANSACTION
// public static final int PROTOCOL_VERSION = 27; // SIGNAL_OPENED_SESSION
// public static final int PROTOCOL_VERSION = 26; // Add prefetch depth in LockStateRequest/Indication
// public static final int PROTOCOL_VERSION = 25; // OpenSessionResponse.repositoryAuthenticating
@@ -312,6 +313,11 @@ public interface CDOProtocolConstants
*/
public static final short SIGNAL_RESET_TRANSACTION = 61;
+ /**
+ * @since 4.5
+ */
+ public static final short SIGNAL_UNIT = 62;
+
// //////////////////////////////////////////////////////////////////////
// Session Refresh
@@ -470,4 +476,27 @@ public interface CDOProtocolConstants
* @since 4.3
*/
public static final byte REVISION_DOES_NOT_EXIST = -1;
+
+ // //////////////////////////////////////////////////////////////////////
+ // Units
+
+ /**
+ * @since 4.5
+ */
+ public static final byte UNIT_CHECK = 0;
+
+ /**
+ * @since 4.5
+ */
+ public static final byte UNIT_CREATE = 1;
+
+ /**
+ * @since 4.5
+ */
+ public static final byte UNIT_OPEN = 2;
+
+ /**
+ * @since 4.5
+ */
+ public static final byte UNIT_CLOSE = 3;
}
diff --git a/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/CDOClientProtocol.java b/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/CDOClientProtocol.java
index 2e6f609394..f58ae8f414 100644
--- a/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/CDOClientProtocol.java
+++ b/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/CDOClientProtocol.java
@@ -503,6 +503,47 @@ public class CDOClientProtocol extends AuthenticatingSignalProtocol<CDOSessionIm
return send(new LoadMergeDataRequest(this, targetInfo, sourceInfo, targetBaseInfo, sourceBaseInfo));
}
+ @Deprecated
+ public CDOLockState[] getLockStates(int viewID, Collection<CDOID> ids)
+ {
+ return getLockStates(viewID, ids, CDOLockState.DEPTH_NONE);
+ }
+
+ public CDOLockState[] getLockStates(int viewID, Collection<CDOID> ids, int depth)
+ {
+ return send(new LockStateRequest(this, viewID, ids, depth));
+ }
+
+ public void enableLockNotifications(int viewID, boolean on)
+ {
+ send(new EnableLockNotificationRequest(this, viewID, on));
+ }
+
+ public void setLockNotificationMode(LockNotificationMode mode)
+ {
+ send(new SetLockNotificationModeRequest(this, mode));
+ }
+
+ public Map<CDORevision, CDOPermission> loadPermissions(InternalCDORevision[] revisions)
+ {
+ return send(new LoadPermissionsRequest(this, revisions));
+ }
+
+ public void requestChangeCredentials()
+ {
+ send(new ChangeCredentialsRequest(this, CredentialsUpdateOperation.CHANGE_PASSWORD, null), new Monitor());
+ }
+
+ public void requestResetCredentials(String userID)
+ {
+ send(new ChangeCredentialsRequest(this, CredentialsUpdateOperation.RESET_PASSWORD, userID), new Monitor());
+ }
+
+ public boolean requestUnit(int viewID, CDOID rootID, byte opcode, CDORevisionHandler revisionHandler)
+ {
+ return send(new UnitRequest(this, viewID, rootID, opcode, revisionHandler));
+ }
+
@Override
protected SignalReactor createSignalReactor(short signalID)
{
@@ -600,40 +641,4 @@ public class CDOClientProtocol extends AuthenticatingSignalProtocol<CDOSessionIm
REVISION_LOADING.stop(request);
}
}
-
- @Deprecated
- public CDOLockState[] getLockStates(int viewID, Collection<CDOID> ids)
- {
- return getLockStates(viewID, ids, CDOLockState.DEPTH_NONE);
- }
-
- public CDOLockState[] getLockStates(int viewID, Collection<CDOID> ids, int depth)
- {
- return send(new LockStateRequest(this, viewID, ids, depth));
- }
-
- public void enableLockNotifications(int viewID, boolean on)
- {
- send(new EnableLockNotificationRequest(this, viewID, on));
- }
-
- public void setLockNotificationMode(LockNotificationMode mode)
- {
- send(new SetLockNotificationModeRequest(this, mode));
- }
-
- public Map<CDORevision, CDOPermission> loadPermissions(InternalCDORevision[] revisions)
- {
- return send(new LoadPermissionsRequest(this, revisions));
- }
-
- public void requestChangeCredentials()
- {
- send(new ChangeCredentialsRequest(this, CredentialsUpdateOperation.CHANGE_PASSWORD, null), new Monitor());
- }
-
- public void requestResetCredentials(String userID)
- {
- send(new ChangeCredentialsRequest(this, CredentialsUpdateOperation.RESET_PASSWORD, userID), new Monitor());
- }
}
diff --git a/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/UnitRequest.java b/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/UnitRequest.java
new file mode 100644
index 0000000000..01e23d3559
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/UnitRequest.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2016 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:
+ * Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.internal.net4j.protocol;
+
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.protocol.CDODataInput;
+import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
+import org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionHandler;
+
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+
+import java.io.IOException;
+
+/**
+ * @author Eike Stepper
+ */
+public class UnitRequest extends CDOClientRequestWithMonitoring<Boolean>
+{
+ private int viewID;
+
+ private CDOID rootID;
+
+ private byte opcode;
+
+ private CDORevisionHandler revisionHandler;
+
+ public UnitRequest(CDOClientProtocol protocol, int viewID, CDOID rootID, byte opcode,
+ CDORevisionHandler revisionHandler)
+ {
+ super(protocol, CDOProtocolConstants.SIGNAL_UNIT);
+ this.viewID = viewID;
+ this.rootID = rootID;
+ this.opcode = opcode;
+ this.revisionHandler = revisionHandler;
+ }
+
+ @Override
+ protected void requesting(CDODataOutput out, OMMonitor monitor) throws IOException
+ {
+ out.writeInt(viewID);
+ out.writeCDOID(rootID);
+ out.writeByte(opcode);
+ }
+
+ @Override
+ protected Boolean confirming(CDODataInput in, OMMonitor monitor) throws IOException
+ {
+ if (opcode == CDOProtocolConstants.UNIT_CREATE || opcode == CDOProtocolConstants.UNIT_OPEN)
+ {
+ for (;;)
+ {
+ CDORevision revision = in.readCDORevision();
+ if (revision == null)
+ {
+ break;
+ }
+
+ revisionHandler.handleRevision(revision);
+ }
+ }
+
+ return in.readBoolean();
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/IDBStoreAccessor.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/IDBStoreAccessor.java
index 4b80d68f95..78b9747bcd 100644
--- a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/IDBStoreAccessor.java
+++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/IDBStoreAccessor.java
@@ -11,6 +11,7 @@
package org.eclipse.emf.cdo.server.db;
import org.eclipse.emf.cdo.server.IStoreAccessor;
+import org.eclipse.emf.cdo.server.IStoreAccessor.UnitSupport;
import org.eclipse.net4j.db.IDBConnection;
@@ -23,7 +24,7 @@ import java.sql.Connection;
* @noextend This interface is not intended to be extended by clients.
* @noimplement This interface is not intended to be implemented by clients.
*/
-public interface IDBStoreAccessor extends IStoreAccessor.Raw
+public interface IDBStoreAccessor extends IStoreAccessor.Raw, UnitSupport
{
public IDBStore getStore();
diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/IClassMappingUnitSupport.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/IClassMappingUnitSupport.java
new file mode 100644
index 0000000000..65e8e77d33
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/IClassMappingUnitSupport.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2016 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:
+ * Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server.db.mapping;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.revision.CDORevisionHandler;
+import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
+
+import java.sql.SQLException;
+
+/**
+ * An extension interface for {@link IClassMapping class mappings} that support <i>units</i>.
+ *
+ * @author Eike Stepper
+ * @since 4.4
+ */
+public interface IClassMappingUnitSupport extends IClassMapping
+{
+ public void readUnitRevisions(IDBStoreAccessor accessor, CDOBranchPoint branchPoint, CDOID rootID,
+ CDORevisionHandler revisionHandler) throws SQLException;
+}
diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/IListMapping3.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/IListMapping3.java
new file mode 100644
index 0000000000..8fc37c5a4e
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/IListMapping3.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2016 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:
+ * Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server.db.mapping;
+
+/**
+ * Extension interface to {@link IListMapping2}.
+ *
+ * @author Eike Stepper
+ * @since 4.4
+ */
+public interface IListMapping3 extends IListMapping2
+{
+ public void setClassMapping(IClassMapping classMapping);
+}
diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/IListMappingUnitSupport.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/IListMappingUnitSupport.java
new file mode 100644
index 0000000000..8c54771c86
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/IListMappingUnitSupport.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2016 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:
+ * Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server.db.mapping;
+
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
+import org.eclipse.emf.cdo.server.db.IIDHandler;
+
+import org.eclipse.net4j.util.collection.MoveableList;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+/**
+ * Interface to complement {@link IListMapping} in order to provide unit support.
+ *
+ * @author Eike Stepper
+ * @since 4.4
+ */
+public interface IListMappingUnitSupport extends IListMapping
+{
+ public ResultSet queryUnitEntries(IDBStoreAccessor accessor, IIDHandler idHandler, CDOID rootID) throws SQLException;
+
+ public void readUnitEntries(ResultSet resultSet, MoveableList<Object> list) throws SQLException;
+}
diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStore.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStore.java
index 9efd29ccc8..48df638948 100644
--- a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStore.java
+++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStore.java
@@ -32,6 +32,7 @@ import org.eclipse.emf.cdo.server.db.IMetaDataManager;
import org.eclipse.emf.cdo.server.db.mapping.IMappingStrategy;
import org.eclipse.emf.cdo.server.internal.db.bundle.OM;
import org.eclipse.emf.cdo.server.internal.db.mapping.horizontal.IMappingConstants;
+import org.eclipse.emf.cdo.server.internal.db.mapping.horizontal.UnitMappingTable;
import org.eclipse.emf.cdo.server.internal.db.messages.Messages;
import org.eclipse.emf.cdo.spi.server.InternalRepository;
import org.eclipse.emf.cdo.spi.server.InternalSession;
@@ -115,6 +116,8 @@ public class DBStore extends Store implements IDBStore, IMappingConstants, CDOAl
private DurableLockingManager durableLockingManager = new DurableLockingManager(this);
+ private UnitMappingTable unitMappingTable;
+
private IMappingStrategy mappingStrategy;
private IDBDatabase database;
@@ -237,6 +240,11 @@ public class DBStore extends Store implements IDBStore, IMappingConstants, CDOAl
return durableLockingManager;
}
+ public UnitMappingTable getUnitMappingTable()
+ {
+ return unitMappingTable;
+ }
+
public Timer getConnectionKeepAliveTimer()
{
return connectionKeepAliveTimer;
@@ -640,6 +648,12 @@ public class DBStore extends Store implements IDBStore, IMappingConstants, CDOAl
LifecycleUtil.activate(durableLockingManager);
LifecycleUtil.activate(mappingStrategy);
+ if (repository.isSupportingUnits())
+ {
+ unitMappingTable = new UnitMappingTable(mappingStrategy);
+ unitMappingTable.activate();
+ }
+
setRevisionTemporality(mappingStrategy.hasAuditSupport() ? RevisionTemporality.AUDITING : RevisionTemporality.NONE);
setRevisionParallelism(
mappingStrategy.hasBranchingSupport() ? RevisionParallelism.BRANCHING : RevisionParallelism.NONE);
@@ -659,6 +673,7 @@ public class DBStore extends Store implements IDBStore, IMappingConstants, CDOAl
@Override
protected void doDeactivate() throws Exception
{
+ LifecycleUtil.deactivate(unitMappingTable);
LifecycleUtil.deactivate(mappingStrategy);
LifecycleUtil.deactivate(durableLockingManager);
LifecycleUtil.deactivate(metaDataManager);
@@ -961,7 +976,7 @@ public class DBStore extends Store implements IDBStore, IMappingConstants, CDOAl
};
private static final SchemaMigrator[] SCHEMA_MIGRATORS = { NO_MIGRATION_NEEDED, NON_AUDIT_MIGRATION,
- LOB_SIZE_MIGRATION, NO_MIGRATION_NEEDED };
+ LOB_SIZE_MIGRATION, NO_MIGRATION_NEEDED };
static
{
diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStoreAccessor.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStoreAccessor.java
index 834cbca7b9..3af8e796b4 100644
--- a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStoreAccessor.java
+++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStoreAccessor.java
@@ -39,6 +39,7 @@ import org.eclipse.emf.cdo.server.ISession;
import org.eclipse.emf.cdo.server.IStoreAccessor;
import org.eclipse.emf.cdo.server.IStoreAccessor.DurableLocking2;
import org.eclipse.emf.cdo.server.ITransaction;
+import org.eclipse.emf.cdo.server.IView;
import org.eclipse.emf.cdo.server.db.IDBStore;
import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
import org.eclipse.emf.cdo.server.db.IIDHandler;
@@ -49,6 +50,7 @@ import org.eclipse.emf.cdo.server.db.mapping.IClassMappingDeltaSupport;
import org.eclipse.emf.cdo.server.db.mapping.IMappingStrategy;
import org.eclipse.emf.cdo.server.internal.db.bundle.OM;
import org.eclipse.emf.cdo.server.internal.db.mapping.horizontal.AbstractHorizontalClassMapping;
+import org.eclipse.emf.cdo.server.internal.db.mapping.horizontal.UnitMappingTable;
import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranch;
import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranchManager;
import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranchManager.BranchLoader3;
@@ -133,17 +135,17 @@ public class DBStoreAccessor extends StoreAccessor implements IDBStoreAccessor,
}
@Override
- public DBStore getStore()
+ public final DBStore getStore()
{
return (DBStore)super.getStore();
}
- public IDBConnection getDBConnection()
+ public final IDBConnection getDBConnection()
{
return connection;
}
- public Connection getConnection()
+ public final Connection getConnection()
{
return connection;
}
@@ -480,11 +482,12 @@ public class DBStoreAccessor extends StoreAccessor implements IDBStoreAccessor,
{
super.applyIDMappings(context, monitor);
+ DBStore store = getStore();
+ IIDHandler idHandler = store.getIDHandler();
+
// Remember maxID because it may have to be adjusted if the repository is BACKUP or CLONE. See bug 325097.
boolean adjustMaxID = !context.getBranchPoint().getBranch().isLocal()
- && getStore().getRepository().getIDGenerationLocation() == IDGenerationLocation.STORE;
-
- IIDHandler idHandler = getStore().getIDHandler();
+ && store.getRepository().getIDGenerationLocation() == IDGenerationLocation.STORE;
// Remember CDOIDs of new objects. They are cleared after writeRevisions()
for (InternalCDORevision revision : context.getNewObjects())
@@ -850,6 +853,13 @@ public class DBStoreAccessor extends StoreAccessor implements IDBStoreAccessor,
IMappingStrategy mappingStrategy = store.getMappingStrategy();
mappingStrategy.createMapping(connection, packageUnits, monitor.fork());
+
+ int writePackageUnits; // TODO Extra commit needed for Mysql between DDL and DML.
+ connection.commit();
+ }
+ catch (SQLException ex)
+ {
+ throw new DBException(ex);
}
finally
{
@@ -1443,6 +1453,25 @@ public class DBStoreAccessor extends StoreAccessor implements IDBStoreAccessor,
manager.unlock(this, durableLockingID);
}
+ public List<CDOID> readUnitRoots()
+ {
+ UnitMappingTable unitMappingTable = getStore().getUnitMappingTable();
+ return unitMappingTable.readUnitRoots(this);
+ }
+
+ public void initUnit(IView view, CDOID rootID, CDORevisionHandler revisionHandler)
+ {
+ long created = getStore().getRepository().getTimeStamp();
+ UnitMappingTable unitMappingTable = getStore().getUnitMappingTable();
+ unitMappingTable.initUnit(this, view, rootID, created, revisionHandler);
+ }
+
+ public void readUnit(IView view, CDOID rootID, CDORevisionHandler revisionHandler)
+ {
+ UnitMappingTable unitMappingTable = getStore().getUnitMappingTable();
+ unitMappingTable.readUnitRevisions(this, view, rootID, revisionHandler);
+ }
+
/**
* @author Stefan Winkler
*/
diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/AbstractMappingStrategy.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/AbstractMappingStrategy.java
index 9552980072..78590284f4 100644
--- a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/AbstractMappingStrategy.java
+++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/AbstractMappingStrategy.java
@@ -55,6 +55,7 @@ import org.eclipse.net4j.util.StringUtil;
import org.eclipse.net4j.util.WrappedException;
import org.eclipse.net4j.util.collection.CloseableIterator;
import org.eclipse.net4j.util.lifecycle.Lifecycle;
+import org.eclipse.net4j.util.lifecycle.LifecycleUtil;
import org.eclipse.net4j.util.om.monitor.OMMonitor;
import org.eclipse.net4j.util.om.monitor.OMMonitor.Async;
@@ -828,6 +829,21 @@ public abstract class AbstractMappingStrategy extends Lifecycle implements IMapp
public abstract IListMapping doCreateFeatureMapMapping(EClass containingClass, EStructuralFeature feature);
+ @Override
+ protected void doDeactivate() throws Exception
+ {
+ deactivateClassMappings();
+ super.doDeactivate();
+ }
+
+ protected void deactivateClassMappings()
+ {
+ for (IClassMapping classMapping : classMappings.values())
+ {
+ LifecycleUtil.deactivate(classMapping);
+ }
+ }
+
private static Set<CDOFeatureType> doGetForceIndexes(IMappingStrategy mappingStrategy)
{
return CDOFeatureType.readCombination(mappingStrategy.getProperties().get(Props.FORCE_INDEXES));
diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AbstractBasicListTableMapping.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AbstractBasicListTableMapping.java
index 695e803227..b68f84dc8c 100644
--- a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AbstractBasicListTableMapping.java
+++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AbstractBasicListTableMapping.java
@@ -13,7 +13,8 @@ package org.eclipse.emf.cdo.server.internal.db.mapping.horizontal;
import org.eclipse.emf.cdo.common.branch.CDOBranch;
import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
-import org.eclipse.emf.cdo.server.db.mapping.IListMapping2;
+import org.eclipse.emf.cdo.server.db.mapping.IClassMapping;
+import org.eclipse.emf.cdo.server.db.mapping.IListMapping3;
import org.eclipse.emf.cdo.server.db.mapping.IMappingStrategy;
import org.eclipse.emf.ecore.EClass;
@@ -22,7 +23,7 @@ import org.eclipse.emf.ecore.EStructuralFeature;
/**
* @author Stefan Winkler
*/
-public abstract class AbstractBasicListTableMapping implements IListMapping2, IMappingConstants
+public abstract class AbstractBasicListTableMapping implements IListMapping3, IMappingConstants
{
private IMappingStrategy mappingStrategy;
@@ -70,5 +71,10 @@ public abstract class AbstractBasicListTableMapping implements IListMapping2, IM
builder.append(toIndex - 1);
}
+ public void setClassMapping(IClassMapping classMapping)
+ {
+ // Subclasses may override.
+ }
+
public abstract void rawDeleted(IDBStoreAccessor accessor, CDOID id, CDOBranch branch, int version);
}
diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AbstractHorizontalClassMapping.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AbstractHorizontalClassMapping.java
index 2efd6d6307..21e0d908cf 100644
--- a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AbstractHorizontalClassMapping.java
+++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AbstractHorizontalClassMapping.java
@@ -31,6 +31,7 @@ import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
import org.eclipse.emf.cdo.server.db.IIDHandler;
import org.eclipse.emf.cdo.server.db.mapping.IClassMapping;
import org.eclipse.emf.cdo.server.db.mapping.IListMapping;
+import org.eclipse.emf.cdo.server.db.mapping.IListMapping3;
import org.eclipse.emf.cdo.server.db.mapping.IMappingStrategy;
import org.eclipse.emf.cdo.server.db.mapping.ITypeMapping;
import org.eclipse.emf.cdo.server.internal.db.bundle.OM;
@@ -51,6 +52,7 @@ import org.eclipse.net4j.db.ddl.IDBIndex;
import org.eclipse.net4j.db.ddl.IDBSchema;
import org.eclipse.net4j.db.ddl.IDBTable;
import org.eclipse.net4j.spi.db.ddl.InternalDBIndex;
+import org.eclipse.net4j.util.lifecycle.IDeactivateable;
import org.eclipse.net4j.util.om.monitor.OMMonitor;
import org.eclipse.net4j.util.om.monitor.OMMonitor.Async;
import org.eclipse.net4j.util.om.trace.ContextTracer;
@@ -79,7 +81,7 @@ import java.util.Set;
* @author Eike Stepper
* @since 2.0
*/
-public abstract class AbstractHorizontalClassMapping implements IClassMapping, IMappingConstants
+public abstract class AbstractHorizontalClassMapping implements IClassMapping, IMappingConstants, IDeactivateable
{
private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG, AbstractHorizontalClassMapping.class);
@@ -142,7 +144,9 @@ public abstract class AbstractHorizontalClassMapping implements IClassMapping, I
primaryKey.addIndexField(branchField);
}
- table.addIndex(IDBIndex.Type.NON_UNIQUE, ATTRIBUTES_ID, ATTRIBUTES_REVISED);
+ int xxx;
+ // table.addIndex(IDBIndex.Type.NON_UNIQUE, ATTRIBUTES_ID, ATTRIBUTES_REVISED);
+ table.addIndex(IDBIndex.Type.NON_UNIQUE, ATTRIBUTES_REVISED);
}
}
@@ -175,6 +179,11 @@ public abstract class AbstractHorizontalClassMapping implements IClassMapping, I
mapping = mappingStrategy.createListMapping(eClass, feature);
}
+ if (mapping instanceof IListMapping3)
+ {
+ ((IListMapping3)mapping).setClassMapping(this);
+ }
+
listMappings.add(mapping);
// Add field for list sizes
@@ -294,9 +303,10 @@ public abstract class AbstractHorizontalClassMapping implements IClassMapping, I
}
stmt.setMaxRows(1); // Optimization: only 1 row
-
resultSet = stmt.executeQuery();
- if (!resultSet.next())
+
+ IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+ if (!readValuesFromResultSet(resultSet, idHandler, revision, false))
{
if (TRACER.isEnabled())
{
@@ -306,69 +316,95 @@ public abstract class AbstractHorizontalClassMapping implements IClassMapping, I
return false;
}
- revision.setVersion(resultSet.getInt(ATTRIBUTES_VERSION));
+ return true;
+ }
+ catch (SQLException ex)
+ {
+ throw new DBException(ex);
+ }
+ finally
+ {
+ DBUtil.close(resultSet);
+ }
+ }
- long timeStamp = resultSet.getLong(ATTRIBUTES_CREATED);
+ /**
+ * Read the revision's values from the DB.
+ *
+ * @return <code>true</code> if the revision has been read successfully.<br>
+ * <code>false</code> if the revision does not exist in the DB.
+ */
+ protected final boolean readValuesFromResultSet(ResultSet resultSet, IIDHandler idHandler,
+ InternalCDORevision revision, boolean forUnit)
+ {
+ try
+ {
+ if (resultSet.next())
+ {
+ long timeStamp = resultSet.getLong(ATTRIBUTES_CREATED);
+ CDOBranchPoint branchPoint = revision.getBranch().getPoint(timeStamp);
- IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
- CDOBranchPoint branchPoint = revision.getBranch().getPoint(timeStamp);
+ if (forUnit)
+ {
+ revision.setID(idHandler.getCDOID(resultSet, ATTRIBUTES_ID));
+ }
- revision.setBranchPoint(branchPoint);
- revision.setRevised(resultSet.getLong(ATTRIBUTES_REVISED));
- revision.setResourceID(idHandler.getCDOID(resultSet, ATTRIBUTES_RESOURCE));
- revision.setContainerID(idHandler.getCDOID(resultSet, ATTRIBUTES_CONTAINER));
- revision.setContainingFeatureID(resultSet.getInt(ATTRIBUTES_FEATURE));
+ revision.setBranchPoint(branchPoint);
+ revision.setVersion(resultSet.getInt(ATTRIBUTES_VERSION));
+ revision.setRevised(resultSet.getLong(ATTRIBUTES_REVISED));
+ revision.setResourceID(idHandler.getCDOID(resultSet, ATTRIBUTES_RESOURCE));
+ revision.setContainerID(idHandler.getCDOID(resultSet, ATTRIBUTES_CONTAINER));
+ revision.setContainingFeatureID(resultSet.getInt(ATTRIBUTES_FEATURE));
- for (ITypeMapping mapping : valueMappings)
- {
- EStructuralFeature feature = mapping.getFeature();
- if (feature.isUnsettable())
+ for (ITypeMapping mapping : valueMappings)
{
- IDBField field = unsettableFields.get(feature);
- if (!resultSet.getBoolean(field.getName()))
+ EStructuralFeature feature = mapping.getFeature();
+ if (feature.isUnsettable())
{
- // isSet==false -- setValue: null
- revision.setValue(feature, null);
- continue;
+ IDBField field = unsettableFields.get(feature);
+ if (!resultSet.getBoolean(field.getName()))
+ {
+ // isSet==false -- setValue: null
+ revision.setValue(feature, null);
+ continue;
+ }
}
- }
- mapping.readValueToRevision(resultSet, revision);
- }
+ mapping.readValueToRevision(resultSet, revision);
+ }
- if (listSizeFields != null)
- {
- for (Map.Entry<EStructuralFeature, IDBField> listSizeEntry : listSizeFields.entrySet())
+ if (listSizeFields != null)
{
- EStructuralFeature feature = listSizeEntry.getKey();
- IDBField field = listSizeEntry.getValue();
- int size = resultSet.getInt(field.getName());
+ for (Map.Entry<EStructuralFeature, IDBField> listSizeEntry : listSizeFields.entrySet())
+ {
+ EStructuralFeature feature = listSizeEntry.getKey();
+ IDBField field = listSizeEntry.getValue();
+ int size = resultSet.getInt(field.getName());
- // ensure the listSize (TODO: remove assertion)
- CDOList list = revision.getList(feature, size);
+ // ensure the listSize (TODO: remove assertion)
+ CDOList list = revision.getList(feature, size);
- for (int i = 0; i < size; i++)
- {
- list.add(InternalCDOList.UNINITIALIZED);
- }
+ for (int i = 0; i < size; i++)
+ {
+ list.add(InternalCDOList.UNINITIALIZED);
+ }
- if (list.size() != size)
- {
- Assert.isTrue(false);
+ if (list.size() != size)
+ {
+ Assert.isTrue(false);
+ }
}
}
+
+ return true;
}
- return true;
+ return false;
}
catch (SQLException ex)
{
throw new DBException(ex);
}
- finally
- {
- DBUtil.close(resultSet);
- }
}
protected final void readLists(IDBStoreAccessor accessor, InternalCDORevision revision, int listChunk)
@@ -926,6 +962,11 @@ public abstract class AbstractHorizontalClassMapping implements IClassMapping, I
protected abstract void writeValues(IDBStoreAccessor accessor, InternalCDORevision revision);
+ public Exception deactivate()
+ {
+ return null;
+ }
+
protected static void appendTypeMappingNames(StringBuilder builder, Collection<ITypeMapping> typeMappings)
{
if (typeMappings != null)
diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AuditListTableMappingWithRanges.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AuditListTableMappingWithRanges.java
index 3583e2e2c5..45446e29e0 100644
--- a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AuditListTableMappingWithRanges.java
+++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AuditListTableMappingWithRanges.java
@@ -36,11 +36,14 @@ import org.eclipse.emf.cdo.server.db.IDBStore;
import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
import org.eclipse.emf.cdo.server.db.IDBStoreChunkReader;
import org.eclipse.emf.cdo.server.db.IIDHandler;
+import org.eclipse.emf.cdo.server.db.mapping.IClassMapping;
import org.eclipse.emf.cdo.server.db.mapping.IListMappingDeltaSupport;
+import org.eclipse.emf.cdo.server.db.mapping.IListMappingUnitSupport;
import org.eclipse.emf.cdo.server.db.mapping.IMappingStrategy;
import org.eclipse.emf.cdo.server.db.mapping.ITypeMapping;
import org.eclipse.emf.cdo.server.internal.db.bundle.OM;
import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+import org.eclipse.emf.cdo.spi.server.InternalRepository;
import org.eclipse.net4j.db.DBException;
import org.eclipse.net4j.db.DBType;
@@ -75,7 +78,8 @@ import java.util.List;
* @author Stefan Winkler
* @author Lothar Werzinger
*/
-public class AuditListTableMappingWithRanges extends AbstractBasicListTableMapping implements IListMappingDeltaSupport
+public class AuditListTableMappingWithRanges extends AbstractBasicListTableMapping
+ implements IListMappingDeltaSupport, IListMappingUnitSupport
{
private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG, AuditListTableMappingWithRanges.class);
@@ -84,6 +88,8 @@ public class AuditListTableMappingWithRanges extends AbstractBasicListTableMappi
*/
private static final int FINAL_VERSION = Integer.MAX_VALUE;
+ private static final String SQL_ORDER_BY_INDEX = " ORDER BY " + LIST_IDX;
+
/**
* The table of this mapping.
*/
@@ -97,7 +103,7 @@ public class AuditListTableMappingWithRanges extends AbstractBasicListTableMappi
// --------- SQL strings - see initSQLStrings() -----------------
private String sqlSelectChunksPrefix;
- private String sqlOrderByIndex;
+ private String sqlSelectUnitEntries;
private String sqlInsertEntry;
@@ -172,8 +178,6 @@ public class AuditListTableMappingWithRanges extends AbstractBasicListTableMappi
builder.append(">?)"); //$NON-NLS-1$
sqlSelectChunksPrefix = builder.toString();
- sqlOrderByIndex = " ORDER BY " + LIST_IDX; //$NON-NLS-1$
-
// ----------------- insert entry -----------------
builder = new StringBuilder("INSERT INTO "); //$NON-NLS-1$
builder.append(tableName);
@@ -271,6 +275,26 @@ public class AuditListTableMappingWithRanges extends AbstractBasicListTableMappi
sqlDeleteList = builder.toString();
}
+ @Override
+ public void setClassMapping(IClassMapping classMapping)
+ {
+ InternalRepository repository = (InternalRepository)getMappingStrategy().getStore().getRepository();
+ if (repository.isSupportingUnits())
+ {
+ String listTableName = getTable().getName();
+ String attributesTableName = classMapping.getDBTables().get(0).getName();
+
+ sqlSelectUnitEntries = "SELECT cdo_list." + LIST_VALUE + //
+ " FROM " + listTableName + " cdo_list, " + attributesTableName + ", " + UnitMappingTable.UNITS + //
+ " WHERE " + UnitMappingTable.UNITS_ELEM + "=" + ATTRIBUTES_ID + //
+ " AND " + ATTRIBUTES_ID + "=cdo_list." + LIST_REVISION_ID + //
+ " AND " + UnitMappingTable.UNITS_UNIT + "=?" + //
+ " AND cdo_list." + LIST_REVISION_VERSION_ADDED + "<=" + ATTRIBUTES_VERSION + //
+ " AND (cdo_list." + LIST_REVISION_VERSION_REMOVED + " IS NULL OR cdo_list." + LIST_REVISION_VERSION_REMOVED
+ + ">" + ATTRIBUTES_VERSION + ") ORDER BY cdo_list." + LIST_REVISION_ID + ", cdo_list." + LIST_IDX;
+ }
+ }
+
public Collection<IDBTable> getDBTables()
{
return Collections.singleton(table);
@@ -301,7 +325,7 @@ public class AuditListTableMappingWithRanges extends AbstractBasicListTableMappi
getFeature().getName(), revision.getID(), revision.getVersion());
}
- String sql = sqlSelectChunksPrefix + sqlOrderByIndex;
+ String sql = sqlSelectChunksPrefix + SQL_ORDER_BY_INDEX;
IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
IDBPreparedStatement stmt = accessor.getDBConnection().prepareStatement(sql, ReuseProbability.HIGH);
@@ -365,7 +389,7 @@ public class AuditListTableMappingWithRanges extends AbstractBasicListTableMappi
builder.append(where);
}
- builder.append(sqlOrderByIndex);
+ builder.append(SQL_ORDER_BY_INDEX);
String sql = builder.toString();
IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
@@ -536,6 +560,251 @@ public class AuditListTableMappingWithRanges extends AbstractBasicListTableMappi
throw new UnsupportedOperationException("Raw deletion does not work in range-based mappings");
}
+ public ResultSet queryUnitEntries(IDBStoreAccessor accessor, IIDHandler idHandler, CDOID rootID) throws SQLException
+ {
+ IDBPreparedStatement stmt = accessor.getDBConnection().prepareStatement(sqlSelectUnitEntries,
+ ReuseProbability.MEDIUM);
+ idHandler.setCDOID(stmt, 1, rootID);
+ return stmt.executeQuery();
+ }
+
+ public void readUnitEntries(ResultSet resultSet, MoveableList<Object> list) throws SQLException
+ {
+ int size = list.size();
+ for (int i = 0; i < size; i++)
+ {
+ resultSet.next();
+
+ int xxx; // TODO Check that this is the correct revision?
+
+ Object value = typeMapping.readValue(resultSet);
+ list.set(i, value);
+ }
+ }
+
+ private void addEntry(IDBStoreAccessor accessor, CDOID id, int version, int index, Object value)
+ {
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("Adding value for feature() {0}.{1} index {2} of {3}v{4} : {5}", //$NON-NLS-1$
+ getContainingClass().getName(), getFeature().getName(), index, id, version, value);
+ }
+
+ IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+ IDBPreparedStatement stmt = accessor.getDBConnection().prepareStatement(sqlInsertEntry, ReuseProbability.HIGH);
+
+ try
+ {
+ int column = 1;
+ idHandler.setCDOID(stmt, column++, id);
+ stmt.setInt(column++, version);
+ stmt.setInt(column++, index);
+ typeMapping.setValue(stmt, column++, value);
+
+ DBUtil.update(stmt, true);
+ }
+ catch (SQLException e)
+ {
+ throw new DBException(e);
+ }
+ catch (IllegalStateException e)
+ {
+ throw new DBException(e);
+ }
+ finally
+ {
+ DBUtil.close(stmt);
+ }
+ }
+
+ private void removeEntry(IDBStoreAccessor accessor, CDOID id, int oldVersion, int newVersion, int index)
+ {
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("Removing value for feature() {0}.{1} index {2} of {3}v{4}", //$NON-NLS-1$
+ getContainingClass().getName(), getFeature().getName(), index, id, newVersion);
+ }
+
+ IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+ IDBPreparedStatement stmt = accessor.getDBConnection().prepareStatement(sqlDeleteEntry, ReuseProbability.HIGH);
+
+ try
+ {
+ // try to delete a temporary entry first
+ int column = 1;
+ idHandler.setCDOID(stmt, column++, id);
+ stmt.setInt(column++, index);
+ stmt.setInt(column++, newVersion);
+
+ int result = DBUtil.update(stmt, false);
+ if (result == 1)
+ {
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("removeEntry deleted: {0}", index); //$NON-NLS-1$
+ }
+ }
+ else if (result > 1)
+ {
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("removeEntry Too many results: {0}: {1}", index, result); //$NON-NLS-1$
+ }
+
+ throw new DBException("Too many results"); //$NON-NLS-1$
+ }
+ else
+ {
+ // no temporary entry found, so mark the entry as removed
+ DBUtil.close(stmt);
+ stmt = accessor.getDBConnection().prepareStatement(sqlRemoveEntry, ReuseProbability.HIGH);
+
+ column = 1;
+ stmt.setInt(column++, newVersion);
+ idHandler.setCDOID(stmt, column++, id);
+ stmt.setInt(column++, index);
+
+ DBUtil.update(stmt, true);
+ }
+ }
+ catch (SQLException e)
+ {
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("Removing value for feature() {0}.{1} index {2} of {3}v{4} FAILED {5}", //$NON-NLS-1$
+ getContainingClass().getName(), getFeature().getName(), index, id, newVersion, e.getMessage());
+ }
+
+ throw new DBException(e);
+ }
+ catch (IllegalStateException e)
+ {
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("Removing value for feature() {0}.{1} index {2} of {3}v{4} FAILED {5}", //$NON-NLS-1$
+ getContainingClass().getName(), getFeature().getName(), index, id, newVersion, e.getMessage());
+ }
+
+ throw new DBException(e);
+ }
+ finally
+ {
+ DBUtil.close(stmt);
+ }
+ }
+
+ private Object getValue(IDBStoreAccessor accessor, CDOID id, int index)
+ {
+ IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+ IDBPreparedStatement stmt = accessor.getDBConnection().prepareStatement(sqlGetValue, ReuseProbability.HIGH);
+ Object result = null;
+
+ try
+ {
+ int column = 1;
+ idHandler.setCDOID(stmt, column++, id);
+ stmt.setInt(column++, index);
+
+ ResultSet resultSet = stmt.executeQuery();
+ if (!resultSet.next())
+ {
+ throw new DBException("getValue() expects exactly one result");
+ }
+
+ result = typeMapping.readValue(resultSet);
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("Read value (index {0}) from result set: {1}", index, result); //$NON-NLS-1$
+ }
+ }
+ catch (SQLException e)
+ {
+ throw new DBException(e);
+ }
+ finally
+ {
+ DBUtil.close(stmt);
+ }
+
+ return result;
+ }
+
+ public final boolean queryXRefs(IDBStoreAccessor accessor, String mainTableName, String mainTableWhere,
+ QueryXRefsContext context, String idString)
+ {
+
+ String tableName = getTable().getName();
+ String listJoin = getMappingStrategy().getListJoin("a_t", "l_t");
+
+ StringBuilder builder = new StringBuilder();
+ builder.append("SELECT l_t."); //$NON-NLS-1$
+ builder.append(LIST_REVISION_ID);
+ builder.append(", l_t."); //$NON-NLS-1$
+ builder.append(LIST_VALUE);
+ builder.append(", l_t."); //$NON-NLS-1$
+ builder.append(LIST_IDX);
+ builder.append(" FROM "); //$NON-NLS-1$
+ builder.append(tableName);
+ builder.append(" l_t, ");//$NON-NLS-1$
+ builder.append(mainTableName);
+ builder.append(" a_t WHERE ");//$NON-NLS-1$
+ builder.append("a_t.");//$NON-NLS-1$
+ builder.append(mainTableWhere);
+ builder.append(listJoin);
+ builder.append(" AND "); //$NON-NLS-1$
+ builder.append(LIST_VALUE);
+ builder.append(" IN "); //$NON-NLS-1$
+ builder.append(idString);
+ String sql = builder.toString();
+
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("Query XRefs (list): {0}", sql);
+ }
+
+ IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+ IDBPreparedStatement stmt = accessor.getDBConnection().prepareStatement(sql, ReuseProbability.MEDIUM);
+ ResultSet resultSet = null;
+
+ try
+ {
+ resultSet = stmt.executeQuery();
+ while (resultSet.next())
+ {
+ CDOID sourceID = idHandler.getCDOID(resultSet, 1);
+ CDOID targetID = idHandler.getCDOID(resultSet, 2);
+ int idx = resultSet.getInt(3);
+
+ boolean more = context.addXRef(targetID, sourceID, (EReference)getFeature(), idx);
+ if (TRACER.isEnabled())
+ {
+ TRACER.format(" add XRef to context: src={0}, tgt={1}, idx={2}", sourceID, targetID, idx);
+ }
+
+ if (!more)
+ {
+ if (TRACER.isEnabled())
+ {
+ TRACER.format(" result limit reached. Ignoring further results.");
+ }
+
+ return false;
+ }
+ }
+
+ return true;
+ }
+ catch (SQLException ex)
+ {
+ throw new DBException(ex);
+ }
+ finally
+ {
+ DBUtil.close(resultSet);
+ DBUtil.close(stmt);
+ }
+ }
+
public void processDelta(final IDBStoreAccessor accessor, final CDOID id, final int branchId, int oldVersion,
final int newVersion, long created, CDOListFeatureDelta delta)
{
@@ -890,227 +1159,4 @@ public class AuditListTableMappingWithRanges extends AbstractBasicListTableMappi
}
}
}
-
- private void addEntry(IDBStoreAccessor accessor, CDOID id, int version, int index, Object value)
- {
- if (TRACER.isEnabled())
- {
- TRACER.format("Adding value for feature() {0}.{1} index {2} of {3}v{4} : {5}", //$NON-NLS-1$
- getContainingClass().getName(), getFeature().getName(), index, id, version, value);
- }
-
- IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
- IDBPreparedStatement stmt = accessor.getDBConnection().prepareStatement(sqlInsertEntry, ReuseProbability.HIGH);
-
- try
- {
- int column = 1;
- idHandler.setCDOID(stmt, column++, id);
- stmt.setInt(column++, version);
- stmt.setInt(column++, index);
- typeMapping.setValue(stmt, column++, value);
-
- DBUtil.update(stmt, true);
- }
- catch (SQLException e)
- {
- throw new DBException(e);
- }
- catch (IllegalStateException e)
- {
- throw new DBException(e);
- }
- finally
- {
- DBUtil.close(stmt);
- }
- }
-
- private void removeEntry(IDBStoreAccessor accessor, CDOID id, int oldVersion, int newVersion, int index)
- {
- if (TRACER.isEnabled())
- {
- TRACER.format("Removing value for feature() {0}.{1} index {2} of {3}v{4}", //$NON-NLS-1$
- getContainingClass().getName(), getFeature().getName(), index, id, newVersion);
- }
-
- IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
- IDBPreparedStatement stmt = accessor.getDBConnection().prepareStatement(sqlDeleteEntry, ReuseProbability.HIGH);
-
- try
- {
- // try to delete a temporary entry first
- int column = 1;
- idHandler.setCDOID(stmt, column++, id);
- stmt.setInt(column++, index);
- stmt.setInt(column++, newVersion);
-
- int result = DBUtil.update(stmt, false);
- if (result == 1)
- {
- if (TRACER.isEnabled())
- {
- TRACER.format("removeEntry deleted: {0}", index); //$NON-NLS-1$
- }
- }
- else if (result > 1)
- {
- if (TRACER.isEnabled())
- {
- TRACER.format("removeEntry Too many results: {0}: {1}", index, result); //$NON-NLS-1$
- }
-
- throw new DBException("Too many results"); //$NON-NLS-1$
- }
- else
- {
- // no temporary entry found, so mark the entry as removed
- DBUtil.close(stmt);
- stmt = accessor.getDBConnection().prepareStatement(sqlRemoveEntry, ReuseProbability.HIGH);
-
- column = 1;
- stmt.setInt(column++, newVersion);
- idHandler.setCDOID(stmt, column++, id);
- stmt.setInt(column++, index);
-
- DBUtil.update(stmt, true);
- }
- }
- catch (SQLException e)
- {
- if (TRACER.isEnabled())
- {
- TRACER.format("Removing value for feature() {0}.{1} index {2} of {3}v{4} FAILED {5}", //$NON-NLS-1$
- getContainingClass().getName(), getFeature().getName(), index, id, newVersion, e.getMessage());
- }
-
- throw new DBException(e);
- }
- catch (IllegalStateException e)
- {
- if (TRACER.isEnabled())
- {
- TRACER.format("Removing value for feature() {0}.{1} index {2} of {3}v{4} FAILED {5}", //$NON-NLS-1$
- getContainingClass().getName(), getFeature().getName(), index, id, newVersion, e.getMessage());
- }
-
- throw new DBException(e);
- }
- finally
- {
- DBUtil.close(stmt);
- }
- }
-
- private Object getValue(IDBStoreAccessor accessor, CDOID id, int index)
- {
- IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
- IDBPreparedStatement stmt = accessor.getDBConnection().prepareStatement(sqlGetValue, ReuseProbability.HIGH);
- Object result = null;
-
- try
- {
- int column = 1;
- idHandler.setCDOID(stmt, column++, id);
- stmt.setInt(column++, index);
-
- ResultSet resultSet = stmt.executeQuery();
- if (!resultSet.next())
- {
- throw new DBException("getValue() expects exactly one result");
- }
-
- result = typeMapping.readValue(resultSet);
- if (TRACER.isEnabled())
- {
- TRACER.format("Read value (index {0}) from result set: {1}", index, result); //$NON-NLS-1$
- }
- }
- catch (SQLException e)
- {
- throw new DBException(e);
- }
- finally
- {
- DBUtil.close(stmt);
- }
-
- return result;
- }
-
- public final boolean queryXRefs(IDBStoreAccessor accessor, String mainTableName, String mainTableWhere,
- QueryXRefsContext context, String idString)
- {
-
- String tableName = getTable().getName();
- String listJoin = getMappingStrategy().getListJoin("a_t", "l_t");
-
- StringBuilder builder = new StringBuilder();
- builder.append("SELECT l_t."); //$NON-NLS-1$
- builder.append(LIST_REVISION_ID);
- builder.append(", l_t."); //$NON-NLS-1$
- builder.append(LIST_VALUE);
- builder.append(", l_t."); //$NON-NLS-1$
- builder.append(LIST_IDX);
- builder.append(" FROM "); //$NON-NLS-1$
- builder.append(tableName);
- builder.append(" l_t, ");//$NON-NLS-1$
- builder.append(mainTableName);
- builder.append(" a_t WHERE ");//$NON-NLS-1$
- builder.append("a_t.");//$NON-NLS-1$
- builder.append(mainTableWhere);
- builder.append(listJoin);
- builder.append(" AND "); //$NON-NLS-1$
- builder.append(LIST_VALUE);
- builder.append(" IN "); //$NON-NLS-1$
- builder.append(idString);
- String sql = builder.toString();
-
- if (TRACER.isEnabled())
- {
- TRACER.format("Query XRefs (list): {0}", sql);
- }
-
- IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
- IDBPreparedStatement stmt = accessor.getDBConnection().prepareStatement(sql, ReuseProbability.MEDIUM);
- ResultSet resultSet = null;
-
- try
- {
- resultSet = stmt.executeQuery();
- while (resultSet.next())
- {
- CDOID sourceID = idHandler.getCDOID(resultSet, 1);
- CDOID targetID = idHandler.getCDOID(resultSet, 2);
- int idx = resultSet.getInt(3);
-
- boolean more = context.addXRef(targetID, sourceID, (EReference)getFeature(), idx);
- if (TRACER.isEnabled())
- {
- TRACER.format(" add XRef to context: src={0}, tgt={1}, idx={2}", sourceID, targetID, idx);
- }
-
- if (!more)
- {
- if (TRACER.isEnabled())
- {
- TRACER.format(" result limit reached. Ignoring further results.");
- }
-
- return false;
- }
- }
-
- return true;
- }
- catch (SQLException ex)
- {
- throw new DBException(ex);
- }
- finally
- {
- DBUtil.close(resultSet);
- DBUtil.close(stmt);
- }
- }
}
diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalAuditClassMapping.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalAuditClassMapping.java
index 63d4e1840c..605d9d2fed 100644
--- a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalAuditClassMapping.java
+++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalAuditClassMapping.java
@@ -20,6 +20,7 @@ import org.eclipse.emf.cdo.common.branch.CDOBranchVersion;
import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.common.revision.CDOList;
import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionHandler;
import org.eclipse.emf.cdo.common.revision.delta.CDOAddFeatureDelta;
import org.eclipse.emf.cdo.common.revision.delta.CDOClearFeatureDelta;
import org.eclipse.emf.cdo.common.revision.delta.CDOContainerFeatureDelta;
@@ -35,18 +36,27 @@ import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
import org.eclipse.emf.cdo.server.db.IIDHandler;
import org.eclipse.emf.cdo.server.db.mapping.IClassMappingAuditSupport;
import org.eclipse.emf.cdo.server.db.mapping.IClassMappingDeltaSupport;
+import org.eclipse.emf.cdo.server.db.mapping.IClassMappingUnitSupport;
+import org.eclipse.emf.cdo.server.db.mapping.IListMapping;
import org.eclipse.emf.cdo.server.db.mapping.IListMappingDeltaSupport;
+import org.eclipse.emf.cdo.server.db.mapping.IListMappingUnitSupport;
import org.eclipse.emf.cdo.server.db.mapping.ITypeMapping;
+import org.eclipse.emf.cdo.server.internal.db.DBStore;
import org.eclipse.emf.cdo.server.internal.db.bundle.OM;
import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionDelta;
+import org.eclipse.emf.cdo.spi.common.revision.StubCDORevision;
+import org.eclipse.emf.cdo.spi.server.InternalRepository;
import org.eclipse.net4j.db.DBException;
import org.eclipse.net4j.db.DBUtil;
import org.eclipse.net4j.db.IDBPreparedStatement;
import org.eclipse.net4j.db.IDBPreparedStatement.ReuseProbability;
+import org.eclipse.net4j.db.IDBResultSet;
import org.eclipse.net4j.db.ddl.IDBField;
import org.eclipse.net4j.util.ImplementationError;
+import org.eclipse.net4j.util.collection.MoveableList;
+import org.eclipse.net4j.util.concurrent.ConcurrencyUtil;
import org.eclipse.net4j.util.om.monitor.OMMonitor;
import org.eclipse.net4j.util.om.monitor.OMMonitor.Async;
import org.eclipse.net4j.util.om.trace.ContextTracer;
@@ -54,28 +64,38 @@ import org.eclipse.net4j.util.om.trace.ContextTracer;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EStructuralFeature;
+import java.sql.ResultSet;
import java.sql.SQLException;
+import java.util.List;
import java.util.Map;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
/**
* @author Eike Stepper
* @since 2.0
*/
public class HorizontalAuditClassMapping extends AbstractHorizontalClassMapping
- implements IClassMappingAuditSupport, IClassMappingDeltaSupport
+ implements IClassMappingAuditSupport, IClassMappingDeltaSupport, IClassMappingUnitSupport
{
private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG, HorizontalAuditClassMapping.class);
private String sqlInsertAttributes;
- private String sqlSelectCurrentAttributes;
-
- private String sqlSelectAllObjectIDs;
+ private String sqlSelectAttributesCurrent;
private String sqlSelectAttributesByTime;
private String sqlSelectAttributesByVersion;
+ private String sqlSelectUnitCurrent;
+
+ private String sqlSelectUnitByTime;
+
+ private String sqlSelectAllObjectIDs;
+
private String sqlReviseAttributes;
private String sqlRawDeleteAttributes;
@@ -98,47 +118,25 @@ public class HorizontalAuditClassMapping extends AbstractHorizontalClassMapping
private void initSQLStrings()
{
// ----------- Select Revision ---------------------------
- StringBuilder builder = new StringBuilder();
- builder.append("SELECT "); //$NON-NLS-1$
- builder.append(ATTRIBUTES_VERSION);
- builder.append(", "); //$NON-NLS-1$
- builder.append(ATTRIBUTES_CREATED);
- builder.append(", "); //$NON-NLS-1$
- builder.append(ATTRIBUTES_REVISED);
- builder.append(", "); //$NON-NLS-1$
- builder.append(ATTRIBUTES_RESOURCE);
- builder.append(", "); //$NON-NLS-1$
- builder.append(ATTRIBUTES_CONTAINER);
- builder.append(", "); //$NON-NLS-1$
- builder.append(ATTRIBUTES_FEATURE);
- appendTypeMappingNames(builder, getValueMappings());
- appendFieldNames(builder, getUnsettableFields());
- appendFieldNames(builder, getListSizeFields());
- builder.append(" FROM "); //$NON-NLS-1$
- builder.append(getTable());
- builder.append(" WHERE "); //$NON-NLS-1$
- builder.append(ATTRIBUTES_ID);
- builder.append("=? AND ("); //$NON-NLS-1$
- String sqlSelectAttributesPrefix = builder.toString();
- builder.append(ATTRIBUTES_REVISED);
- builder.append("=0)"); //$NON-NLS-1$
- sqlSelectCurrentAttributes = builder.toString();
-
- builder = new StringBuilder(sqlSelectAttributesPrefix);
- builder.append(ATTRIBUTES_CREATED);
- builder.append("<=? AND ("); //$NON-NLS-1$
- builder.append(ATTRIBUTES_REVISED);
- builder.append("=0 OR "); //$NON-NLS-1$
- builder.append(ATTRIBUTES_REVISED);
- builder.append(">=?))"); //$NON-NLS-1$
- sqlSelectAttributesByTime = builder.toString();
+ String[] strings = buildSQLSelects(false);
+ String sqlSelectAttributesPrefix = strings[0];
+ sqlSelectAttributesCurrent = strings[1];
+ sqlSelectAttributesByTime = strings[2];
- builder = new StringBuilder(sqlSelectAttributesPrefix);
+ StringBuilder builder = new StringBuilder(sqlSelectAttributesPrefix);
builder.append("ABS(");
builder.append(ATTRIBUTES_VERSION);
- builder.append(")=?)"); //$NON-NLS-1$
+ builder.append(")=?"); //$NON-NLS-1$
sqlSelectAttributesByVersion = builder.toString();
+ InternalRepository repository = (InternalRepository)getMappingStrategy().getStore().getRepository();
+ if (repository.isSupportingUnits())
+ {
+ strings = buildSQLSelects(true);
+ sqlSelectUnitCurrent = strings[1];
+ sqlSelectUnitByTime = strings[2];
+ }
+
// ----------- Insert Attributes -------------------------
builder = new StringBuilder();
builder.append("INSERT INTO "); //$NON-NLS-1$
@@ -200,6 +198,78 @@ public class HorizontalAuditClassMapping extends AbstractHorizontalClassMapping
sqlRawDeleteAttributes = builder.toString();
}
+ private String[] buildSQLSelects(boolean forUnits)
+ {
+ String[] strings = new String[3];
+
+ StringBuilder builder = new StringBuilder();
+ builder.append("SELECT "); //$NON-NLS-1$
+ if (forUnits)
+ {
+ builder.append(ATTRIBUTES_ID);
+ builder.append(", "); //$NON-NLS-1$
+ }
+
+ builder.append(ATTRIBUTES_VERSION);
+ builder.append(", "); //$NON-NLS-1$
+ builder.append(ATTRIBUTES_CREATED);
+ builder.append(", "); //$NON-NLS-1$
+ builder.append(ATTRIBUTES_REVISED);
+ builder.append(", "); //$NON-NLS-1$
+ builder.append(ATTRIBUTES_RESOURCE);
+ builder.append(", "); //$NON-NLS-1$
+ builder.append(ATTRIBUTES_CONTAINER);
+ builder.append(", "); //$NON-NLS-1$
+ builder.append(ATTRIBUTES_FEATURE);
+ appendTypeMappingNames(builder, getValueMappings());
+ appendFieldNames(builder, getUnsettableFields());
+ appendFieldNames(builder, getListSizeFields());
+ builder.append(" FROM "); //$NON-NLS-1$
+ builder.append(getTable());
+
+ if (forUnits)
+ {
+ builder.append(", "); //$NON-NLS-1$
+ builder.append(UnitMappingTable.UNITS);
+ builder.append(" WHERE "); //$NON-NLS-1$
+ builder.append(ATTRIBUTES_ID);
+ builder.append("="); //$NON-NLS-1$
+ builder.append(UnitMappingTable.UNITS);
+ builder.append("."); //$NON-NLS-1$
+ builder.append(UnitMappingTable.UNITS_ELEM);
+ builder.append(" AND "); //$NON-NLS-1$
+ builder.append(UnitMappingTable.UNITS);
+ builder.append("."); //$NON-NLS-1$
+ builder.append(UnitMappingTable.UNITS_UNIT);
+ builder.append("=?"); //$NON-NLS-1$
+ builder.append(" AND "); //$NON-NLS-1$
+ }
+ else
+ {
+ builder.append(" WHERE "); //$NON-NLS-1$
+ builder.append(ATTRIBUTES_ID);
+ builder.append("=? AND "); //$NON-NLS-1$
+ }
+
+ strings[0] = builder.toString();
+
+ builder.append(ATTRIBUTES_REVISED);
+ builder.append("=0"); //$NON-NLS-1$
+ strings[1] = builder.toString();
+
+ builder = new StringBuilder(strings[0]);
+ builder.append("("); //$NON-NLS-1$
+ builder.append(ATTRIBUTES_CREATED);
+ builder.append("<=? AND ("); //$NON-NLS-1$
+ builder.append(ATTRIBUTES_REVISED);
+ builder.append("=0 OR "); //$NON-NLS-1$
+ builder.append(ATTRIBUTES_REVISED);
+ builder.append(">=?))"); //$NON-NLS-1$
+ strings[2] = builder.toString();
+
+ return strings;
+ }
+
public boolean readRevision(IDBStoreAccessor accessor, InternalCDORevision revision, int listChunk)
{
IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
@@ -217,7 +287,7 @@ public class HorizontalAuditClassMapping extends AbstractHorizontalClassMapping
}
else
{
- stmt = accessor.getDBConnection().prepareStatement(sqlSelectCurrentAttributes, ReuseProbability.HIGH);
+ stmt = accessor.getDBConnection().prepareStatement(sqlSelectAttributesCurrent, ReuseProbability.HIGH);
idHandler.setCDOID(stmt, 1, revision.getID());
}
@@ -593,6 +663,216 @@ public class HorizontalAuditClassMapping extends AbstractHorizontalClassMapping
return builder.toString();
}
+ public void readUnitRevisions(IDBStoreAccessor accessor, CDOBranchPoint branchPoint, CDOID rootID,
+ CDORevisionHandler revisionHandler) throws SQLException
+ {
+ DBStore store = (DBStore)getMappingStrategy().getStore();
+ InternalRepository repository = store.getRepository();
+ CDOBranchPoint head = repository.getBranchManager().getMainBranch().getHead();
+ EClass eClass = getEClass();
+
+ int xxx;
+ long start = System.currentTimeMillis();
+ System.out.print(eClass.getName() + ":\t");
+
+ IIDHandler idHandler = store.getIDHandler();
+ IDBPreparedStatement stmt = null;
+ int oldFetchSize = -1;
+
+ try
+ {
+ long timeStamp = branchPoint.getTimeStamp();
+ if (timeStamp != CDOBranchPoint.UNSPECIFIED_DATE)
+ {
+ stmt = accessor.getDBConnection().prepareStatement(sqlSelectUnitByTime, ReuseProbability.MEDIUM);
+ idHandler.setCDOID(stmt, 1, rootID);
+ stmt.setLong(2, timeStamp);
+ stmt.setLong(3, timeStamp);
+ }
+ else
+ {
+ stmt = accessor.getDBConnection().prepareStatement(sqlSelectUnitCurrent, ReuseProbability.HIGH);
+ idHandler.setCDOID(stmt, 1, rootID);
+ }
+
+ AsnychronousListFiller listFiller = new AsnychronousListFiller(accessor, rootID, revisionHandler);
+ ConcurrencyUtil.execute(repository, listFiller);
+
+ oldFetchSize = stmt.getFetchSize();
+ stmt.setFetchSize(100000);
+ IDBResultSet resultSet = stmt.executeQuery();
+
+ for (;;)
+ {
+ InternalCDORevision revision = store.createRevision(eClass, null);
+ revision.setBranchPoint(head);
+
+ if (!readValuesFromResultSet(resultSet, idHandler, revision, true))
+ {
+ break;
+ }
+
+ listFiller.schedule(revision);
+ }
+
+ long stop = System.currentTimeMillis();
+ System.out.print(stop - start);
+ start = stop;
+
+ listFiller.await();
+
+ stop = System.currentTimeMillis() - start;
+ if (stop != 0)
+ {
+ System.out.print("\t" + stop);
+ }
+
+ System.out.println();
+ }
+ finally
+ {
+ if (oldFetchSize != -1)
+ {
+ stmt.setFetchSize(oldFetchSize);
+ }
+
+ DBUtil.close(stmt);
+ }
+ }
+
+ private class AsnychronousListFiller implements Runnable
+ {
+ private final BlockingQueue<InternalCDORevision> queue = new LinkedBlockingQueue<InternalCDORevision>();
+
+ private final CountDownLatch latch = new CountDownLatch(1);
+
+ private final IDBStoreAccessor accessor;
+
+ private final CDOID rootID;
+
+ private final DBStore store;
+
+ private final IIDHandler idHandler;
+
+ private final IListMappingUnitSupport[] listMappings;
+
+ private final ResultSet[] resultSets;
+
+ private final CDORevisionHandler revisionHandler;
+
+ public AsnychronousListFiller(IDBStoreAccessor accessor, CDOID rootID, CDORevisionHandler revisionHandler)
+ {
+ this.accessor = accessor;
+ this.rootID = rootID;
+ this.revisionHandler = revisionHandler;
+
+ store = (DBStore)accessor.getStore();
+ idHandler = store.getIDHandler();
+
+ List<IListMapping> tmp = getListMappings();
+ int size = tmp.size();
+
+ listMappings = new IListMappingUnitSupport[size];
+ resultSets = new ResultSet[size];
+
+ int i = 0;
+ for (IListMapping listMapping : tmp)
+ {
+ listMappings[i++] = (IListMappingUnitSupport)listMapping;
+ }
+ }
+
+ public void schedule(InternalCDORevision revision)
+ {
+ queue.offer(revision);
+ }
+
+ public void await()
+ {
+ // Schedule an end marker revision.
+ schedule(new StubCDORevision(getEClass()));
+
+ try
+ {
+ latch.await();
+ }
+ catch (InterruptedException ex)
+ {
+ //$FALL-THROUGH$
+ }
+ }
+
+ public void run()
+ {
+ try
+ {
+ while (store.isActive())
+ {
+ InternalCDORevision revision;
+
+ try
+ {
+ revision = queue.poll(1, TimeUnit.SECONDS);
+ if (revision == null)
+ {
+ continue;
+ }
+
+ if (revision instanceof StubCDORevision)
+ {
+ return;
+ }
+ }
+ catch (InterruptedException ex)
+ {
+ return;
+ }
+
+ try
+ {
+ readUnitEntries(revision);
+ }
+ catch (SQLException ex)
+ {
+ int xxx;
+ ex.printStackTrace();
+ return;
+ }
+ }
+ }
+ finally
+ {
+ latch.countDown();
+ }
+ }
+
+ private void readUnitEntries(InternalCDORevision revision) throws SQLException
+ {
+ for (int i = 0; i < listMappings.length; i++)
+ {
+ IListMappingUnitSupport listMapping = listMappings[i];
+ EStructuralFeature feature = listMapping.getFeature();
+
+ MoveableList<Object> list = revision.getList(feature);
+ int size = list.size();
+ if (size != 0)
+ {
+ if (resultSets[i] == null)
+ {
+ resultSets[i] = listMapping.queryUnitEntries(accessor, idHandler, rootID);
+ }
+
+ listMapping.readUnitEntries(resultSets[i], list);
+ }
+ }
+
+ synchronized (revisionHandler)
+ {
+ revisionHandler.handleRevision(revision);
+ }
+ }
+ }
+
/**
* @author Stefan Winkler
*/
diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalNonAuditClassMapping.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalNonAuditClassMapping.java
index 3a3b6795a2..85c1855bf7 100644
--- a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalNonAuditClassMapping.java
+++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalNonAuditClassMapping.java
@@ -368,6 +368,8 @@ public class HorizontalNonAuditClassMapping extends AbstractHorizontalClassMappi
{
if (hasLists)
{
+ // Reading all list rows of an object is not atomic.
+ // After all row reads are done, check the revision version again (see below).
stmtVersion = accessor.getDBConnection().prepareStatement(sqlSelectCurrentVersion, ReuseProbability.HIGH);
stmtVersion.setMaxRows(1); // Optimization: only 1 row
idHandler.setCDOID(stmtVersion, 1, id);
diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/ObjectTypeTable.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/ObjectTypeTable.java
index cade3cb771..5787470f50 100644
--- a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/ObjectTypeTable.java
+++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/ObjectTypeTable.java
@@ -21,6 +21,7 @@ import org.eclipse.emf.cdo.server.db.IDBStore;
import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
import org.eclipse.emf.cdo.server.db.IIDHandler;
import org.eclipse.emf.cdo.server.internal.db.CDODBSchema;
+import org.eclipse.emf.cdo.spi.server.InternalRepository;
import org.eclipse.net4j.db.DBException;
import org.eclipse.net4j.db.DBType;
@@ -213,7 +214,7 @@ public class ObjectTypeTable extends AbstractObjectTypeMapper implements IMappin
{
super.doActivate();
- IDBStore store = getMappingStrategy().getStore();
+ final IDBStore store = getMappingStrategy().getStore();
final DBType idType = store.getIDHandler().getDBType();
final int idLength = store.getIDColumnLength();
@@ -230,6 +231,12 @@ public class ObjectTypeTable extends AbstractObjectTypeMapper implements IMappin
table.addField(ATTRIBUTES_CLASS, idType, idLength);
table.addField(ATTRIBUTES_CREATED, DBType.BIGINT);
table.addIndex(IDBIndex.Type.PRIMARY_KEY, ATTRIBUTES_ID);
+
+ InternalRepository repository = (InternalRepository)store.getRepository();
+ if (repository.isSupportingUnits())
+ {
+ table.addIndex(IDBIndex.Type.NON_UNIQUE, ATTRIBUTES_CLASS);
+ }
}
});
}
diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/UnitMappingTable.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/UnitMappingTable.java
new file mode 100644
index 0000000000..f44d2456da
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/UnitMappingTable.java
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2010-2014 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:
+ * Eike Stepper - initial API and implementation
+ * Stefan Winkler - bug 259402
+ * Stefan Winkler - redesign (prepared statements)
+ * Stefan Winkler - bug 276926
+ */
+package org.eclipse.emf.cdo.server.internal.db.mapping.horizontal;
+
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionHandler;
+import org.eclipse.emf.cdo.common.revision.CDORevisionUtil;
+import org.eclipse.emf.cdo.server.IView;
+import org.eclipse.emf.cdo.server.db.IDBStore;
+import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
+import org.eclipse.emf.cdo.server.db.IIDHandler;
+import org.eclipse.emf.cdo.server.db.IMetaDataManager;
+import org.eclipse.emf.cdo.server.db.mapping.IClassMappingUnitSupport;
+import org.eclipse.emf.cdo.server.db.mapping.IMappingStrategy;
+import org.eclipse.emf.cdo.server.internal.db.CDODBSchema;
+
+import org.eclipse.net4j.db.DBException;
+import org.eclipse.net4j.db.DBType;
+import org.eclipse.net4j.db.DBUtil;
+import org.eclipse.net4j.db.IDBConnection;
+import org.eclipse.net4j.db.IDBDatabase;
+import org.eclipse.net4j.db.IDBDatabase.RunnableWithSchema;
+import org.eclipse.net4j.db.IDBPreparedStatement;
+import org.eclipse.net4j.db.IDBPreparedStatement.ReuseProbability;
+import org.eclipse.net4j.db.ddl.IDBIndex;
+import org.eclipse.net4j.db.ddl.IDBSchema;
+import org.eclipse.net4j.db.ddl.IDBTable;
+import org.eclipse.net4j.util.lifecycle.Lifecycle;
+
+import org.eclipse.emf.ecore.EClass;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Eike Stepper
+ * @since 4.0
+ */
+public class UnitMappingTable extends Lifecycle implements IMappingConstants
+{
+ public static final String UNITS = "CDO_UNITS"; //$NON-NLS-1$
+
+ public static final String UNITS_ELEM = "CDO_ELEM"; //$NON-NLS-1$
+
+ public static final String UNITS_UNIT = "CDO_UNIT"; //$NON-NLS-1$
+
+ // public static final String UNITS_CREATED = "CDO_CREATED"; //$NON-NLS-1$
+
+ private static final String SQL_SELECT_ROOTS = "SELECT DISTINCT " + UNITS_UNIT + " FROM " + UNITS;
+
+ private static final String SQL_INSERT_MAPPINGS = "INSERT INTO " + UNITS + " VALUES (?, ?)";
+
+ private static final String SQL_SELECT_CLASSES = "SELECT DISTINCT " + ATTRIBUTES_CLASS + " FROM " + UNITS + ", "
+ + CDODBSchema.CDO_OBJECTS + " WHERE " + UNITS_ELEM + "=" + ATTRIBUTES_ID + " AND " + UNITS_UNIT + "=?";
+
+ private static final int WRITE_UNIT_MAPPING_BATCH_SIZE = 100000;
+
+ private final IMappingStrategy mappingStrategy;
+
+ private IDBTable table;
+
+ public UnitMappingTable(IMappingStrategy mappingStrategy)
+ {
+ this.mappingStrategy = mappingStrategy;
+ }
+
+ public List<CDOID> readUnitRoots(IDBStoreAccessor accessor)
+ {
+ List<CDOID> rootIDs = new ArrayList<CDOID>();
+ IIDHandler idHandler = mappingStrategy.getStore().getIDHandler();
+ Statement stmt = null;
+
+ try
+ {
+ stmt = accessor.getDBConnection().createStatement();
+
+ if (DBUtil.isTracerEnabled())
+ {
+ DBUtil.trace(stmt.toString());
+ }
+
+ ResultSet resultSet = stmt.executeQuery(SQL_SELECT_ROOTS);
+ while (resultSet.next())
+ {
+ CDOID rootID = idHandler.getCDOID(resultSet, 1);
+ rootIDs.add(rootID);
+ }
+ }
+ catch (SQLException ex)
+ {
+ throw new DBException(ex);
+ }
+ finally
+ {
+ DBUtil.close(stmt);
+ }
+
+ return rootIDs;
+ }
+
+ public void initUnit(IDBStoreAccessor accessor, IView view, CDOID rootID, long created,
+ CDORevisionHandler revisionHandler)
+ {
+ IIDHandler idHandler = mappingStrategy.getStore().getIDHandler();
+ IDBConnection connection = accessor.getDBConnection();
+ IDBPreparedStatement stmt = connection.prepareStatement(SQL_INSERT_MAPPINGS, ReuseProbability.HIGH);
+
+ try
+ {
+ CDORevision revision = view.getRevision(rootID);
+ int batchCount = 0;
+
+ if (initUnit(accessor, idHandler, stmt, view, rootID, created, revisionHandler, revision, batchCount) != 0)
+ {
+ stmt.executeBatch();
+ }
+
+ connection.commit();
+ }
+ catch (SQLException ex)
+ {
+ throw new DBException(ex);
+ }
+ finally
+ {
+ DBUtil.close(stmt);
+ }
+ }
+
+ private int initUnit(IDBStoreAccessor accessor, IIDHandler idHandler, IDBPreparedStatement stmt, IView view,
+ CDOID rootID, long created, CDORevisionHandler revisionHandler, CDORevision revision, int batchCount)
+ throws SQLException
+ {
+ revisionHandler.handleRevision(revision);
+
+ CDOID id = revision.getID();
+ idHandler.setCDOID(stmt, 1, id);
+ idHandler.setCDOID(stmt, 2, rootID);
+ // stmt.setLong(3, created);
+ stmt.addBatch();
+
+ if (++batchCount > WRITE_UNIT_MAPPING_BATCH_SIZE)
+ {
+ stmt.executeBatch();
+ batchCount = 0;
+ }
+
+ List<CDORevision> children = CDORevisionUtil.getChildRevisions(revision, view, true);
+ for (CDORevision child : children)
+ {
+ batchCount = initUnit(accessor, idHandler, stmt, view, rootID, created, revisionHandler, child, batchCount);
+ }
+
+ return batchCount;
+ }
+
+ public void readUnitRevisions(IDBStoreAccessor accessor, IView view, CDOID rootID, CDORevisionHandler revisionHandler)
+ {
+ IDBStore store = mappingStrategy.getStore();
+ IIDHandler idHandler = store.getIDHandler();
+ IMetaDataManager metaDataManager = store.getMetaDataManager();
+
+ IDBConnection connection = accessor.getDBConnection();
+ IDBPreparedStatement stmt = connection.prepareStatement(SQL_SELECT_CLASSES, ReuseProbability.HIGH);
+ int oldFetchSize = -1;
+
+ try
+ {
+ idHandler.setCDOID(stmt, 1, rootID);
+
+ oldFetchSize = stmt.getFetchSize();
+ stmt.setFetchSize(100000);
+ ResultSet resultSet = stmt.executeQuery();
+
+ while (resultSet.next())
+ {
+ CDOID classID = idHandler.getCDOID(resultSet, 1);
+ EClass eClass = (EClass)metaDataManager.getMetaInstance(classID);
+
+ IClassMappingUnitSupport classMapping = (IClassMappingUnitSupport)mappingStrategy.getClassMapping(eClass);
+ classMapping.readUnitRevisions(accessor, view, rootID, revisionHandler);
+ }
+ }
+ catch (SQLException ex)
+ {
+ throw new DBException(ex);
+ }
+ finally
+ {
+ if (oldFetchSize != -1)
+ {
+ try
+ {
+ stmt.setFetchSize(oldFetchSize);
+ }
+ catch (SQLException ex)
+ {
+ throw new DBException(ex);
+ }
+ }
+
+ DBUtil.close(stmt);
+ }
+ }
+
+ @Override
+ protected void doActivate() throws Exception
+ {
+ super.doActivate();
+
+ IDBStore store = mappingStrategy.getStore();
+ final DBType idType = store.getIDHandler().getDBType();
+ final int idLength = store.getIDColumnLength();
+
+ IDBDatabase database = store.getDatabase();
+ table = database.getSchema().getTable(UNITS);
+ if (table == null)
+ {
+ database.updateSchema(new RunnableWithSchema()
+ {
+ public void run(IDBSchema schema)
+ {
+ table = schema.addTable(UNITS);
+ table.addField(UNITS_ELEM, idType, idLength, true);
+ table.addField(UNITS_UNIT, idType, idLength);
+ // table.addField(UNITS_CREATED, DBType.BIGINT);
+ table.addIndex(IDBIndex.Type.PRIMARY_KEY, UNITS_ELEM);
+ table.addIndex(IDBIndex.Type.NON_UNIQUE, UNITS_UNIT);
+ }
+ });
+ }
+ }
+
+ @Override
+ protected void doDeactivate() throws Exception
+ {
+ table = null;
+ super.doDeactivate();
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CDOServerProtocol.java b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CDOServerProtocol.java
index 158ec41677..8b87235fcd 100644
--- a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CDOServerProtocol.java
+++ b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CDOServerProtocol.java
@@ -391,6 +391,9 @@ public class CDOServerProtocol extends SignalProtocol<InternalSession> implement
case SIGNAL_RESET_TRANSACTION:
return new ResetTransactionIndication(this);
+ case SIGNAL_UNIT:
+ return new UnitIndication(this);
+
default:
return super.createSignalReactor(signalID);
}
diff --git a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/UnitIndication.java b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/UnitIndication.java
new file mode 100644
index 0000000000..3ee438696c
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/UnitIndication.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2016 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:
+ * Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server.internal.net4j.protocol;
+
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.protocol.CDODataInput;
+import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
+import org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionHandler;
+import org.eclipse.emf.cdo.server.IUnitManager;
+import org.eclipse.emf.cdo.spi.server.InternalView;
+
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+
+import java.io.IOException;
+
+/**
+ * @author Eike Stepper
+ */
+public class UnitIndication extends CDOServerReadIndicationWithMonitoring
+{
+ private int viewID;
+
+ private CDOID rootID;
+
+ private byte opcode;
+
+ public UnitIndication(CDOServerProtocol protocol)
+ {
+ super(protocol, CDOProtocolConstants.SIGNAL_UNIT);
+ }
+
+ @Override
+ protected void indicating(CDODataInput in, OMMonitor monitor) throws Exception
+ {
+ viewID = in.readInt();
+ rootID = in.readCDOID();
+ opcode = in.readByte();
+ }
+
+ @Override
+ protected void responding(final CDODataOutput out, OMMonitor monitor) throws Exception
+ {
+ if (opcode == CDOProtocolConstants.UNIT_CHECK)
+ {
+ IUnitManager unitManager = getRepository().getUnitManager();
+ out.writeBoolean(unitManager.isUnit(rootID));
+ return;
+ }
+
+ final IOException[] ioException = { null };
+ final RuntimeException[] runtimeException = { null };
+ InternalView view = getView(viewID);
+
+ boolean success = view.openUnit(rootID, opcode == CDOProtocolConstants.UNIT_CREATE, new CDORevisionHandler()
+ {
+ public boolean handleRevision(CDORevision revision)
+ {
+ try
+ {
+ out.writeCDORevision(revision, CDORevision.UNCHUNKED); // Exposes revision to client side
+ return true;
+ }
+ catch (IOException ex)
+ {
+ ioException[0] = ex;
+ }
+ catch (RuntimeException ex)
+ {
+ runtimeException[0] = ex;
+ }
+
+ return false;
+ }
+ }, monitor);
+
+ if (ioException[0] != null)
+ {
+ throw ioException[0];
+ }
+
+ if (runtimeException[0] != null)
+ {
+ throw runtimeException[0];
+ }
+
+ out.writeCDORevision(null, CDORevision.UNCHUNKED); // No more revisions
+ out.writeBoolean(success);
+
+ int xxx;
+ System.out.println("--> DONE");
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Repository.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Repository.java
index 25ede606b0..a21da01059 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Repository.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Repository.java
@@ -147,7 +147,7 @@ import java.util.concurrent.Semaphore;
* @author Eike Stepper
* @since 2.0
*/
-public class Repository extends Container<Object>implements InternalRepository, IExecutorServiceProvider
+public class Repository extends Container<Object> implements InternalRepository, IExecutorServiceProvider
{
private static final int UNCHUNKED = CDORevision.UNCHUNKED;
@@ -169,6 +169,8 @@ public class Repository extends Container<Object>implements InternalRepository,
private boolean supportingBranches;
+ private boolean supportingUnits;
+
private boolean serializingCommits;
private boolean ensuringReferentialIntegrity;
@@ -180,7 +182,7 @@ public class Repository extends Container<Object>implements InternalRepository,
/**
* Must not be thread-bound to support XA commits.
*/
- private Semaphore packageRegistryCommitLock = new Semaphore(1);
+ private final Semaphore packageRegistryCommitLock = new Semaphore(1);
private InternalCDOPackageRegistry packageRegistry;
@@ -202,27 +204,29 @@ public class Repository extends Container<Object>implements InternalRepository,
private IManagedContainer container;
- private List<ReadAccessHandler> readAccessHandlers = new ArrayList<ReadAccessHandler>();
+ private final UnitManager unitManager = new UnitManager(this);
- private List<WriteAccessHandler> writeAccessHandlers = new ArrayList<WriteAccessHandler>();
+ private final List<ReadAccessHandler> readAccessHandlers = new ArrayList<ReadAccessHandler>();
- private EPackage[] initialPackages;
+ private final List<WriteAccessHandler> writeAccessHandlers = new ArrayList<WriteAccessHandler>();
// Bug 297940
- private TimeStampAuthority timeStampAuthority = new TimeStampAuthority(this);
-
- private long lastTreeRestructuringCommit = -1;
+ private final TimeStampAuthority timeStampAuthority = new TimeStampAuthority(this);
@ExcludeFromDump
- private transient Object commitTransactionLock = new Object();
+ private final transient Object commitTransactionLock = new Object();
@ExcludeFromDump
- private transient Object createBranchLock = new Object();
+ private final transient Object createBranchLock = new Object();
private boolean skipInitialization;
+ private EPackage[] initialPackages;
+
private CDOID rootResourceID;
+ private long lastTreeRestructuringCommit = -1;
+
public Repository()
{
}
@@ -355,6 +359,11 @@ public class Repository extends Container<Object>implements InternalRepository,
return supportingBranches;
}
+ public boolean isSupportingUnits()
+ {
+ return supportingUnits;
+ }
+
@Deprecated
public boolean isSupportingEcore()
{
@@ -963,6 +972,11 @@ public class Repository extends Container<Object>implements InternalRepository,
return sessionManager;
}
+ public UnitManager getUnitManager()
+ {
+ return unitManager;
+ }
+
/**
* @since 2.0
*/
@@ -1918,6 +1932,13 @@ public class Repository extends Container<Object>implements InternalRepository,
supportingBranches = store.getRevisionParallelism() == IStore.RevisionParallelism.BRANCHING;
}
+ // SUPPORTING_UNITS
+ String valueUnits = properties.get(Props.SUPPORTING_UNITS);
+ if (valueUnits != null)
+ {
+ supportingUnits = Boolean.valueOf(valueUnits);
+ }
+
// SERIALIZE_COMMITS
String valueCommits = properties.get(Props.SERIALIZE_COMMITS);
if (valueCommits != null)
@@ -2086,6 +2107,7 @@ public class Repository extends Container<Object>implements InternalRepository,
newPackageUnitsForRootResource.add(packageUnit);
}
}
+
return newPackageUnitsForRootResource.toArray(new InternalCDOPackageUnit[0]);
}
@@ -2152,7 +2174,7 @@ public class Repository extends Container<Object>implements InternalRepository,
checkState(queryManager, "queryManager"); //$NON-NLS-1$
checkState(commitInfoManager, "commitInfoManager"); //$NON-NLS-1$
checkState(commitManager, "commitManager"); //$NON-NLS-1$
- checkState(getLockingManager(), "lockingManager"); //$NON-NLS-1$
+ checkState(lockingManager, "lockingManager"); //$NON-NLS-1$
packageRegistry.setReplacingDescriptors(true);
packageRegistry.setPackageProcessor(this);
@@ -2167,7 +2189,7 @@ public class Repository extends Container<Object>implements InternalRepository,
commitInfoManager.setRepository(this);
commitInfoManager.setCommitInfoLoader(this);
commitManager.setRepository(this);
- getLockingManager().setRepository(this);
+ lockingManager.setRepository(this);
store.setRepository(this);
}
@@ -2221,13 +2243,20 @@ public class Repository extends Container<Object>implements InternalRepository,
}
LifecycleUtil.activate(lockingManager); // Needs an initialized main branch / branch manager
+
+ if (supportingUnits)
+ {
+ LifecycleUtil.activate(unitManager);
+ }
+
setPostActivateState();
}
@Override
protected void doDeactivate() throws Exception
{
- LifecycleUtil.deactivate(getLockingManager());
+ LifecycleUtil.deactivate(unitManager);
+ LifecycleUtil.deactivate(lockingManager);
LifecycleUtil.deactivate(queryHandlerProvider);
LifecycleUtil.deactivate(commitManager);
LifecycleUtil.deactivate(commitInfoManager);
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/ServerCDOView.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/ServerCDOView.java
index 2e40085253..fe13338342 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/ServerCDOView.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/ServerCDOView.java
@@ -51,6 +51,7 @@ import org.eclipse.emf.cdo.view.CDOFetchRuleManager;
import org.eclipse.emf.cdo.view.CDOInvalidationPolicy;
import org.eclipse.emf.cdo.view.CDORevisionPrefetchingPolicy;
import org.eclipse.emf.cdo.view.CDOStaleReferencePolicy;
+import org.eclipse.emf.cdo.view.CDOUnitManager;
import org.eclipse.emf.cdo.view.CDOView;
import org.eclipse.emf.internal.cdo.session.SessionUtil;
@@ -464,6 +465,11 @@ public class ServerCDOView extends AbstractCDOView implements org.eclipse.emf.cd
throw new UnsupportedOperationException();
}
+ public CDOUnitManager getUnitManager()
+ {
+ throw new UnsupportedOperationException();
+ }
+
/**
* @author Eike Stepper
*/
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 e87ac6a685..009f70f55f 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
@@ -717,6 +717,9 @@ public class TransactionCommitContext implements InternalCommitContext
protected void handleException(Throwable ex)
{
+ int xxx;
+ ex.printStackTrace();
+
try
{
if (TRACER.isEnabled())
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/UnitManager.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/UnitManager.java
new file mode 100644
index 0000000000..d22194f39b
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/UnitManager.java
@@ -0,0 +1,282 @@
+/*
+ * Copyright (c) 2016 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:
+ * Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.internal.server;
+
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.revision.CDORevisionHandler;
+import org.eclipse.emf.cdo.server.IRepository;
+import org.eclipse.emf.cdo.server.IStoreAccessor.UnitSupport;
+import org.eclipse.emf.cdo.server.IUnit;
+import org.eclipse.emf.cdo.server.IUnitManager;
+import org.eclipse.emf.cdo.server.IView;
+import org.eclipse.emf.cdo.spi.server.InternalRepository;
+
+import org.eclipse.net4j.util.container.Container;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
+
+/**
+ * @author Eike Stepper
+ */
+public final class UnitManager extends Container<IUnit> implements IUnitManager
+{
+ private final InternalRepository repository;
+
+ private final Map<CDOID, IUnit> units = new HashMap<CDOID, IUnit>();
+
+ private final ReentrantReadWriteLock managerLock = new ReentrantReadWriteLock();
+
+ public UnitManager(InternalRepository repository)
+ {
+ this.repository = repository;
+ }
+
+ public final IRepository getRepository()
+ {
+ return repository;
+ }
+
+ public boolean isUnit(CDOID rootID)
+ {
+ ReadLock readLock = managerLock.readLock();
+ readLock.lock();
+
+ try
+ {
+ return units.containsKey(rootID);
+ }
+ finally
+ {
+ readLock.unlock();
+ }
+ }
+
+ public IUnit createUnit(CDOID rootID, IView view, CDORevisionHandler revisionHandler)
+ {
+ WriteLock writeLock = managerLock.writeLock();
+ writeLock.lock();
+
+ try
+ {
+ Unit unit;
+ if (units.containsKey(rootID))
+ {
+ return null;
+ }
+
+ int xxx; // TODO Check that units are not nested.
+
+ unit = new Unit(rootID);
+ units.put(rootID, unit);
+
+ // Acquire unit write lock early here, release it in Unit.init()
+ unit.unitLock.writeLock().lock();
+
+ writeLock.unlock();
+ writeLock = null;
+
+ unit.init(view, revisionHandler);
+ fireElementAddedEvent(unit);
+ return unit;
+ }
+ finally
+ {
+ if (writeLock != null)
+ {
+ writeLock.unlock();
+ }
+ }
+ }
+
+ public IUnit getUnit(CDOID rootID)
+ {
+ ReadLock readLock = managerLock.readLock();
+ readLock.lock();
+
+ try
+ {
+ return units.get(rootID);
+ }
+ finally
+ {
+ readLock.unlock();
+ }
+ }
+
+ public IUnit[] getUnits()
+ {
+ return getElements();
+ }
+
+ public IUnit[] getElements()
+ {
+ ReadLock readLock = managerLock.readLock();
+ readLock.lock();
+
+ try
+ {
+ return units.values().toArray(new IUnit[units.size()]);
+ }
+ finally
+ {
+ readLock.unlock();
+ }
+ }
+
+ @Override
+ protected void doActivate() throws Exception
+ {
+ super.doActivate();
+
+ UnitSupport unitSupport = (UnitSupport)repository.getStore().getReader(null);
+
+ try
+ {
+ List<CDOID> roots = unitSupport.readUnitRoots();
+ for (CDOID root : roots)
+ {
+ IUnit unit = new Unit(root);
+ units.put(root, unit);
+ }
+ }
+ finally
+ {
+ unitSupport.release();
+ }
+ }
+
+ @Override
+ protected void doDeactivate() throws Exception
+ {
+ units.clear();
+ super.doDeactivate();
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ public final class Unit implements IUnit
+ {
+ private final CDOID rootID;
+
+ private final Set<IView> views = new HashSet<IView>();
+
+ private final ReentrantReadWriteLock unitLock = new ReentrantReadWriteLock();
+
+ public Unit(CDOID rootID)
+ {
+ this.rootID = rootID;
+ }
+
+ public IUnitManager getManager()
+ {
+ return UnitManager.this;
+ }
+
+ public CDOID getRootID()
+ {
+ return rootID;
+ }
+
+ public void init(IView view, CDORevisionHandler revisionHandler)
+ {
+ // Write lock has been acquired by UnitManager.createUnit()
+
+ try
+ {
+ UnitSupport unitSupport = (UnitSupport)repository.getStore().getWriter(null);
+
+ try
+ {
+ unitSupport.initUnit(view, rootID, revisionHandler);
+ }
+ finally
+ {
+ unitSupport.release();
+ }
+ }
+ finally
+ {
+ // Write lock has been acquired by UnitManager.createUnit()
+ unitLock.writeLock().unlock();
+ }
+ }
+
+ public boolean isOpen()
+ {
+ ReadLock readLock = unitLock.readLock();
+ readLock.lock();
+
+ try
+ {
+ return !views.isEmpty();
+ }
+ finally
+ {
+ readLock.unlock();
+ }
+ }
+
+ public void open(IView view, final CDORevisionHandler revisionHandler)
+ {
+ ReadLock readLock = unitLock.readLock();
+ readLock.lock();
+
+ try
+ {
+ views.add(view);
+
+ UnitSupport unitSupport = (UnitSupport)repository.getStore().getReader(null);
+
+ try
+ {
+ unitSupport.readUnit(view, rootID, revisionHandler);
+ }
+ finally
+ {
+ unitSupport.release();
+ }
+ }
+ finally
+ {
+ readLock.unlock();
+ }
+ }
+
+ public void close(IView view)
+ {
+ ReadLock readLock = unitLock.readLock();
+ readLock.lock();
+
+ try
+ {
+ views.remove(view);
+ }
+ finally
+ {
+ readLock.unlock();
+ }
+ }
+
+ @Override
+ public String toString()
+ {
+ return "Unit[" + rootID + "]";
+ }
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/View.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/View.java
index 9b3f19187a..ec3f221e34 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/View.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/View.java
@@ -15,9 +15,13 @@ import org.eclipse.emf.cdo.common.CDOCommonView;
import org.eclipse.emf.cdo.common.branch.CDOBranch;
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.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionHandler;
import org.eclipse.emf.cdo.common.revision.CDORevisionManager;
import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta;
+import org.eclipse.emf.cdo.server.IUnit;
+import org.eclipse.emf.cdo.server.IUnitManager;
import org.eclipse.emf.cdo.spi.common.branch.CDOBranchUtil;
import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranchManager;
import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
@@ -29,6 +33,7 @@ import org.eclipse.emf.cdo.spi.server.InternalView;
import org.eclipse.net4j.util.AdapterUtil;
import org.eclipse.net4j.util.ObjectUtil;
import org.eclipse.net4j.util.lifecycle.Lifecycle;
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
import org.eclipse.net4j.util.options.IOptionsContainer;
import org.eclipse.net4j.util.registry.HashMapRegistry;
import org.eclipse.net4j.util.registry.IRegistry;
@@ -57,9 +62,11 @@ public class View extends Lifecycle implements InternalView, CDOCommonView.Optio
private String durableLockingID;
- private InternalRepository repository;
+ private final InternalRepository repository;
- private Set<CDOID> changeSubscriptionIDs = new HashSet<CDOID>();
+ private final Set<CDOID> changeSubscriptionIDs = new HashSet<CDOID>();
+
+ private final Set<CDOID> openUnitRoots = new HashSet<CDOID>();
private boolean lockNotificationsEnabled;
@@ -155,7 +162,7 @@ public class View extends Lifecycle implements InternalView, CDOCommonView.Optio
List<CDORevision> oldRevisions = getRevisions(invalidObjects);
setBranchPoint(branchPoint);
List<CDORevision> newRevisions = getRevisions(invalidObjects);
-
+
Iterator<CDORevision> it = newRevisions.iterator();
for (CDORevision oldRevision : oldRevisions)
{
@@ -169,7 +176,7 @@ public class View extends Lifecycle implements InternalView, CDOCommonView.Optio
// Fix for Bug 369646: ensure that revisions are fully loaded
repository.ensureChunks((InternalCDORevision)newRevision, CDORevision.UNCHUNKED);
repository.ensureChunks((InternalCDORevision)oldRevision, CDORevision.UNCHUNKED);
-
+
CDORevisionDelta delta = newRevision.compare(oldRevision);
allChangedObjects.add(delta);
}
@@ -199,6 +206,64 @@ public class View extends Lifecycle implements InternalView, CDOCommonView.Optio
this.durableLockingID = durableLockingID;
}
+ public boolean openUnit(CDOID rootID, boolean create, CDORevisionHandler revisionHandler, OMMonitor monitor)
+ {
+ IUnitManager unitManager = repository.getUnitManager();
+ IUnit unit = unitManager.getUnit(rootID);
+
+ if (create)
+ {
+ if (unit != null)
+ {
+ return false;
+ }
+
+ unit = unitManager.createUnit(rootID, this, revisionHandler);
+ }
+ else
+ {
+ if (unit == null)
+ {
+ return false;
+ }
+
+ int xxx; // TODO Use monitor?
+ unit.open(this, revisionHandler);
+ }
+
+ openUnitRoots.add(rootID);
+ return true;
+ }
+
+ private boolean isInOpenUnit(CDOID id)
+ {
+ if (openUnitRoots.isEmpty())
+ {
+ return false;
+ }
+
+ if (openUnitRoots.contains(id))
+ {
+ return true;
+ }
+
+ int xxx; // TODO Remember object->unit relationship for modified objects?!
+
+ InternalCDORevision revision = getRevision(id);
+ if (revision != null)
+ {
+ CDOID parentID = revision.getResourceID();
+ if (CDOIDUtil.isNull(parentID))
+ {
+ parentID = (CDOID)revision.getContainerID();
+ }
+
+ return isInOpenUnit(parentID);
+ }
+
+ return false;
+ }
+
/**
* @since 2.0
*/
@@ -227,7 +292,17 @@ public class View extends Lifecycle implements InternalView, CDOCommonView.Optio
return false;
}
- return changeSubscriptionIDs.contains(id);
+ if (changeSubscriptionIDs.contains(id))
+ {
+ return true;
+ }
+
+ if (repository.isSupportingUnits())
+ {
+ return isInOpenUnit(id);
+ }
+
+ return false;
}
/**
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/embedded/EmbeddedClientSessionProtocol.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/embedded/EmbeddedClientSessionProtocol.java
index 75db50bbc4..8912da605e 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/embedded/EmbeddedClientSessionProtocol.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/embedded/EmbeddedClientSessionProtocol.java
@@ -653,6 +653,11 @@ public class EmbeddedClientSessionProtocol extends Lifecycle implements CDOSessi
throw new UnsupportedOperationException();
}
+ public boolean requestUnit(int viewID, CDOID rootID, byte opcode, CDORevisionHandler revisionHandler)
+ {
+ throw new UnsupportedOperationException();
+ }
+
@Override
protected void doActivate() throws Exception
{
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IRepository.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IRepository.java
index 738ee52aff..5de431d616 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IRepository.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IRepository.java
@@ -86,6 +86,11 @@ public interface IRepository extends CDOCommonRepository, IQueryHandlerProvider,
public ISessionManager getSessionManager();
/**
+ * @since 4.5
+ */
+ public IUnitManager getUnitManager();
+
+ /**
* @since 4.0
* @deprecated As of 4.1 use {@link #getLockingManager()}.
*/
@@ -319,6 +324,11 @@ public interface IRepository extends CDOCommonRepository, IQueryHandlerProvider,
public static final String SUPPORTING_BRANCHES = "supportingBranches"; //$NON-NLS-1$
/**
+ * @since 4.5
+ */
+ public static final String SUPPORTING_UNITS = "supportingUnits"; //$NON-NLS-1$
+
+ /**
* @since 4.0
* @deprecated As of 4.2 instances of Ecore are always supported (on demand).
*/
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IStoreAccessor.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IStoreAccessor.java
index 62059a2667..2255128941 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IStoreAccessor.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IStoreAccessor.java
@@ -798,4 +798,20 @@ public interface IStoreAccessor extends IQueryHandlerProvider, BranchLoader, Com
public void updateLockArea(LockArea lockArea);
}
+
+ /**
+ * An extension interface for {@link IStoreAccessor store accessors} that support <i>units</i>.
+ *
+ * @author Eike Stepper
+ * @since 4.5
+ * @apiviz.exclude
+ */
+ public interface UnitSupport extends IStoreAccessor
+ {
+ public List<CDOID> readUnitRoots();
+
+ public void initUnit(IView view, CDOID rootID, CDORevisionHandler revisionHandler);
+
+ public void readUnit(IView view, CDOID rootID, CDORevisionHandler revisionHandler);
+ }
}
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IUnit.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IUnit.java
new file mode 100644
index 0000000000..a41352d478
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IUnit.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2016 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:
+ * Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server;
+
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.revision.CDORevisionHandler;
+
+/**
+ * @author Eike Stepper
+ * @since 4.5
+ */
+public interface IUnit
+{
+ public IUnitManager getManager();
+
+ public CDOID getRootID();
+
+ public boolean isOpen();
+
+ public void open(IView view, CDORevisionHandler revisionHandler);
+
+ public void close(IView view);
+}
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IUnitManager.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IUnitManager.java
new file mode 100644
index 0000000000..6c373e9383
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IUnitManager.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2016 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:
+ * Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server;
+
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.revision.CDORevisionHandler;
+
+import org.eclipse.net4j.util.container.IContainer;
+
+/**
+ * @author Eike Stepper
+ * @since 4.5
+ */
+public interface IUnitManager extends IContainer<IUnit>
+{
+ public IRepository getRepository();
+
+ public IUnit createUnit(CDOID rootID, IView view, CDORevisionHandler revisionHandler);
+
+ public boolean isUnit(CDOID rootID);
+
+ public IUnit getUnit(CDOID rootID);
+
+ public IUnit[] getUnits();
+}
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalRepository.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalRepository.java
index c86b01b557..6b60df51a4 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalRepository.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalRepository.java
@@ -262,6 +262,11 @@ public interface InternalRepository extends IRepository, PackageProcessor, Packa
public void setSkipInitialization(boolean skipInitialization);
/**
+ * @since 4.5
+ */
+ public boolean isSupportingUnits();
+
+ /**
* @since 4.0
* @deprecated As of 4.3 use {@link #initSystemPackages()}.
*/
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalView.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalView.java
index f6e8857176..1127725369 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalView.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalView.java
@@ -12,10 +12,12 @@ package org.eclipse.emf.cdo.spi.server;
import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.revision.CDORevisionHandler;
import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta;
import org.eclipse.emf.cdo.server.IView;
import org.eclipse.net4j.util.lifecycle.ILifecycle;
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
import java.util.List;
@@ -55,4 +57,9 @@ public interface InternalView extends IView, ILifecycle
public void clearChangeSubscription();
public void doClose();
+
+ /**
+ * @since 4.5
+ */
+ public boolean openUnit(CDOID rootID, boolean create, CDORevisionHandler revisionHandler, OMMonitor monitor);
}
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/Store.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/Store.java
index 931a4b75c1..ca55a80ea4 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/Store.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/Store.java
@@ -400,7 +400,12 @@ public abstract class Store extends Lifecycle implements InternalStore
{
CDORevisionFactory factory = repository.getRevisionManager().getFactory();
InternalCDORevision revision = (InternalCDORevision)factory.createRevision(eClass);
- revision.setID(id);
+
+ if (id != null)
+ {
+ revision.setID(id);
+ }
+
return revision;
}
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/StoreAccessor.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/StoreAccessor.java
index 0ff8592ca5..c570d5a32c 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/StoreAccessor.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/StoreAccessor.java
@@ -77,9 +77,11 @@ public abstract class StoreAccessor extends StoreAccessorBase
{
monitor.begin(1 + newPackageUnits.length + 2 + newObjects.length + detachedObjects.length + dirtyCount + 1);
- writeCommitInfo(branch, timeStamp, previousTimeStamp, userID, commitComment, monitor.fork());
+ int writePackageUnits; // TODO Extra commit needed for Mysql between DDL and DML.
writePackageUnits(newPackageUnits, monitor.fork(newPackageUnits.length));
+ writeCommitInfo(branch, timeStamp, previousTimeStamp, userID, commitComment, monitor.fork());
+
IDGenerationLocation idGenerationLocation = store.getRepository().getIDGenerationLocation();
if (idGenerationLocation == IDGenerationLocation.STORE)
{
diff --git a/plugins/org.eclipse.emf.cdo.tests.db/CDO AllTests (H2 audit).launch b/plugins/org.eclipse.emf.cdo.tests.db/CDO AllTests (H2 audit).launch
index d00e13136c..b3a9432737 100644
--- a/plugins/org.eclipse.emf.cdo.tests.db/CDO AllTests (H2 audit).launch
+++ b/plugins/org.eclipse.emf.cdo.tests.db/CDO AllTests (H2 audit).launch
@@ -12,5 +12,5 @@
<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit3"/>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.eclipse.emf.cdo.tests.db.AllTestsDBH2Audit"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.emf.cdo.tests.db"/>
-<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xms40m&#13;&#10;-Xmx1024m&#13;&#10;-Dorg.eclipse.net4j.util.om.trace.disable=true"/>
+<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xms1G&#13;&#10;-Xmx4G&#13;&#10;-Dorg.eclipse.net4j.util.om.trace.disable=true&#13;&#10;-Dorg.eclipse.emf.cdo.tests.config.impl.RepositoryConfig.enableServerBrowser=true"/>
</launchConfiguration>
diff --git a/plugins/org.eclipse.emf.cdo.tests.db/src/org/eclipse/emf/cdo/tests/db/MysqlConfig.java b/plugins/org.eclipse.emf.cdo.tests.db/src/org/eclipse/emf/cdo/tests/db/MysqlConfig.java
index 82f69fb120..d4185a5e8b 100644
--- a/plugins/org.eclipse.emf.cdo.tests.db/src/org/eclipse/emf/cdo/tests/db/MysqlConfig.java
+++ b/plugins/org.eclipse.emf.cdo.tests.db/src/org/eclipse/emf/cdo/tests/db/MysqlConfig.java
@@ -35,9 +35,11 @@ public class MysqlConfig extends AbstractSetupDBConfig
*/
public static final String HOST = "localhost";
- public static final String USER = "root";
+ public static final String SCHEMA = "test";
- public static final String PASS = "root";
+ public static final String USER = "test";
+
+ public static final String PASS = "0000";
private static final long serialVersionUID = 1L;
@@ -62,7 +64,7 @@ public class MysqlConfig extends AbstractSetupDBConfig
protected DataSource createDataSourceForDB(String dbName) throws SQLException
{
MysqlDataSource dataSource = new MysqlDataSource();
- dataSource.setUrl("jdbc:mysql://" + HOST);
+ dataSource.setUrl("jdbc:mysql://" + HOST + "/" + SCHEMA);
dataSource.setUser(USER);
if (PASS != null)
{
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 1598df139e..af1783cc04 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
@@ -116,7 +116,8 @@ public class AllConfigs extends ConfigTestSuite
testClasses.add(WorkspaceTest.class);
testClasses.add(BackupTest.class);
testClasses.add(ResourceModificationTrackingTest.class);
- testClasses.add(CDOStaleReferencePolicyTests.class);
+ testClasses.add(CDOStaleReferencePolicyTest.class);
+ testClasses.add(UnitManagerTest.class);
// TODO testClasses.add(RemoteSessionManagerTest.class);
// TODO testClasses.add(NonCDOResourceTest.class);
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/CDOStaleReferencePolicyTests.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/CDOStaleReferencePolicyTest.java
index 56500ab5a3..9d4634c2ea 100644
--- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/CDOStaleReferencePolicyTests.java
+++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/CDOStaleReferencePolicyTest.java
@@ -29,7 +29,7 @@ import org.eclipse.emf.ecore.util.EcoreUtil;
*
* @author Esteban Dugueperoux
*/
-public class CDOStaleReferencePolicyTests extends AbstractCDOTest
+public class CDOStaleReferencePolicyTest extends AbstractCDOTest
{
private static final String RESOURCE_NAME = "test1.model1";
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/UnitManagerMain.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/UnitManagerMain.java
new file mode 100644
index 0000000000..33e8c17d58
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/UnitManagerMain.java
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 2016 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:
+ * Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.tests;
+
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.eresource.CDOResource;
+import org.eclipse.emf.cdo.net4j.CDONet4jSessionConfiguration;
+import org.eclipse.emf.cdo.net4j.CDONet4jUtil;
+import org.eclipse.emf.cdo.server.net4j.CDONet4jServerUtil;
+import org.eclipse.emf.cdo.session.CDOSession;
+import org.eclipse.emf.cdo.tests.model1.Category;
+import org.eclipse.emf.cdo.tests.model1.Company;
+import org.eclipse.emf.cdo.tests.model1.Customer;
+import org.eclipse.emf.cdo.tests.model1.Model1Factory;
+import org.eclipse.emf.cdo.tests.model1.Model1Package;
+import org.eclipse.emf.cdo.tests.model1.OrderDetail;
+import org.eclipse.emf.cdo.tests.model1.Product1;
+import org.eclipse.emf.cdo.tests.model1.PurchaseOrder;
+import org.eclipse.emf.cdo.tests.model1.SalesOrder;
+import org.eclipse.emf.cdo.tests.model1.Supplier;
+import org.eclipse.emf.cdo.transaction.CDOTransaction;
+
+import org.eclipse.net4j.Net4jUtil;
+import org.eclipse.net4j.connector.IConnector;
+import org.eclipse.net4j.tcp.TCPUtil;
+import org.eclipse.net4j.util.container.IPluginContainer;
+
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.util.InternalEList;
+
+import java.util.Iterator;
+
+/**
+ * @author Eike Stepper
+ */
+public class UnitManagerMain
+{
+ private static final String RESOURCE_NAME = "test";
+
+ private static final boolean ADD_UNIQUE = true;
+
+ private static long start;
+
+ /**
+ * @author Eike Stepper
+ */
+ public static final class FillRepository
+ {
+ public static void main(String[] args) throws Exception
+ {
+ CDOSession session = openSession();
+
+ try
+ {
+ CDOTransaction transaction = session.openTransaction();
+ CDOResource resource = transaction.createResource(RESOURCE_NAME);
+
+ for (int i = 0; i < 1; i++)
+ {
+ start("Fill " + i);
+ Company company = Model1Factory.eINSTANCE.createCompany();
+ add(resource.getContents(), company);
+ fillCompany(company);
+ stop();
+
+ start("Commit " + i);
+ transaction.commit();
+ stop();
+ }
+ }
+ finally
+ {
+ session.close();
+ }
+ }
+
+ private static void fillCompany(Company company)
+ {
+ for (int i = 0; i < 5; i++)
+ {
+ Category category = Model1Factory.eINSTANCE.createCategory();
+ add(company.getCategories(), category);
+ fillCategory(category, 5);
+ }
+
+ for (int i = 0; i < 1000; i++)
+ {
+ Supplier supplier = Model1Factory.eINSTANCE.createSupplier();
+ add(company.getSuppliers(), supplier);
+ }
+
+ for (int i = 0; i < 1000; i++)
+ {
+ Customer customer = Model1Factory.eINSTANCE.createCustomer();
+ add(company.getCustomers(), customer);
+ }
+
+ for (int i = 0; i < 1000; i++)
+ {
+ PurchaseOrder order = Model1Factory.eINSTANCE.createPurchaseOrder();
+ order.setSupplier(company.getSuppliers().get(i));
+ add(company.getPurchaseOrders(), order);
+
+ for (int j = 0; j < 100; j++)
+ {
+ OrderDetail orderDetail = Model1Factory.eINSTANCE.createOrderDetail();
+ add(order.getOrderDetails(), orderDetail);
+ }
+ }
+
+ for (int i = 0; i < 1000; i++)
+ {
+ SalesOrder order = Model1Factory.eINSTANCE.createSalesOrder();
+ order.setCustomer(company.getCustomers().get(i));
+ add(company.getSalesOrders(), order);
+
+ for (int j = 0; j < 100; j++)
+ {
+ OrderDetail orderDetail = Model1Factory.eINSTANCE.createOrderDetail();
+ add(order.getOrderDetails(), orderDetail);
+ }
+ }
+ }
+
+ private static void fillCategory(Category category, int depth)
+ {
+ for (int i = 0; i < 5; i++)
+ {
+ Category child = Model1Factory.eINSTANCE.createCategory();
+ add(category.getCategories(), child);
+ if (depth > 1)
+ {
+ fillCategory(child, depth - 1);
+ }
+ }
+
+ for (int i = 0; i < 20; i++)
+ {
+ Product1 product = Model1Factory.eINSTANCE.createProduct1();
+ add(category.getProducts(), product);
+ }
+ }
+
+ private static <T extends EObject> void add(EList<T> list, T object)
+ {
+ if (ADD_UNIQUE)
+ {
+ ((InternalEList<T>)list).addUnique(object);
+ }
+ else
+ {
+ list.add(object);
+ }
+ }
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ public static final class PrefetchResource
+ {
+ public static void main(String[] args) throws Exception
+ {
+ CDOSession session = openSession();
+
+ try
+ {
+ CDOTransaction transaction = session.openTransaction();
+ CDOResource resource = transaction.getResource(RESOURCE_NAME);
+
+ start("Prefetch Resource");
+ resource.cdoPrefetch(CDORevision.DEPTH_INFINITE);
+ stop();
+
+ iterateResource(resource);
+ }
+ finally
+ {
+ session.close();
+ }
+ }
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ public static final class CreateUnit
+ {
+ public static void main(String[] args) throws Exception
+ {
+ CDOSession session = openSession();
+
+ try
+ {
+ CDOTransaction transaction = session.openTransaction();
+ CDOResource resource = transaction.getResource(RESOURCE_NAME);
+
+ start("Create Unit");
+ resource.cdoView().getUnitManager().createUnit(resource);
+ stop();
+
+ iterateResource(resource);
+ }
+ finally
+ {
+ session.close();
+ }
+ }
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ public static final class OpenUnit
+ {
+ public static void main(String[] args) throws Exception
+ {
+ CDOSession session = openSession();
+
+ try
+ {
+ CDOTransaction transaction = session.openTransaction();
+ CDOResource resource = transaction.getResource(RESOURCE_NAME);
+
+ start("Open Unit");
+ resource.cdoView().getUnitManager().openUnit(resource);
+ stop();
+
+ iterateResource(resource);
+ }
+ finally
+ {
+ session.close();
+ }
+ }
+ }
+
+ private static CDOSession openSession()
+ {
+ IConnector connector = TCPUtil.getConnector(IPluginContainer.INSTANCE, "localhost");
+
+ CDONet4jSessionConfiguration configuration = CDONet4jUtil.createNet4jSessionConfiguration();
+ configuration.setConnector(connector);
+ configuration.setRepositoryName("repo1");
+ return configuration.openNet4jSession();
+ }
+
+ private static void iterateResource(CDOResource resource)
+ {
+ start("Iterate");
+ for (Iterator<EObject> it = resource.eAllContents(); it.hasNext();)
+ {
+ it.next();
+ }
+
+ stop();
+ }
+
+ private static void start(String msg)
+ {
+ start = System.currentTimeMillis();
+ System.out.print(msg + ": ");
+ }
+
+ private static void stop()
+ {
+ long stop = System.currentTimeMillis();
+ System.out.println(stop - start);
+ start = stop;
+ }
+
+ static
+ {
+ Model1Package.eINSTANCE.getClass();
+
+ Net4jUtil.prepareContainer(IPluginContainer.INSTANCE);
+ TCPUtil.prepareContainer(IPluginContainer.INSTANCE);
+ CDONet4jServerUtil.prepareContainer(IPluginContainer.INSTANCE);
+ CDONet4jUtil.prepareContainer(IPluginContainer.INSTANCE);
+ IPluginContainer.INSTANCE.activate();
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/UnitManagerTest.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/UnitManagerTest.java
new file mode 100644
index 0000000000..c68b879593
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/UnitManagerTest.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2016 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:
+ * Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.tests;
+
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.eresource.CDOResource;
+import org.eclipse.emf.cdo.session.CDOSession;
+import org.eclipse.emf.cdo.tests.model1.Category;
+import org.eclipse.emf.cdo.tests.model1.Company;
+import org.eclipse.emf.cdo.tests.model1.Customer;
+import org.eclipse.emf.cdo.tests.model1.OrderDetail;
+import org.eclipse.emf.cdo.tests.model1.Product1;
+import org.eclipse.emf.cdo.tests.model1.PurchaseOrder;
+import org.eclipse.emf.cdo.tests.model1.SalesOrder;
+import org.eclipse.emf.cdo.tests.model1.Supplier;
+import org.eclipse.emf.cdo.transaction.CDOTransaction;
+
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.util.InternalEList;
+
+import java.util.Iterator;
+
+/**
+ * @author Eike Stepper
+ */
+public class UnitManagerTest extends AbstractCDOTest
+{
+ private static final String RESOURCE_NAME = "test";
+
+ public void testPrefetchBigModel() throws Exception
+ {
+ {
+ CDOSession session = openSession();
+ CDOTransaction transaction = session.openTransaction();
+ CDOResource resource = transaction.createResource(getResourcePath(RESOURCE_NAME));
+
+ long start = System.currentTimeMillis();
+ for (int i = 0; i < 10; i++)
+ {
+ Company company = getModel1Factory().createCompany();
+ addUnique(resource.getContents(), company);
+ fillCompany(company);
+ long stop = System.currentTimeMillis();
+ System.out.println("Filled " + i + ": " + (stop - start));
+
+ start = stop;
+ transaction.commit();
+ stop = System.currentTimeMillis();
+ System.out.println("Committed " + i + ": " + (stop - start));
+ start = stop;
+ }
+
+ session.close();
+ System.out.println();
+ }
+
+ if (true)
+ {
+ clearCache(getRepository().getRevisionManager());
+ }
+
+ {
+ CDOSession session = openSession();
+ CDOTransaction transaction = session.openTransaction();
+ CDOResource resource = transaction.getResource(getResourcePath(RESOURCE_NAME));
+
+ if (true)
+ {
+ long start = System.currentTimeMillis();
+ resource.cdoPrefetch(CDORevision.DEPTH_INFINITE);
+ long stop = System.currentTimeMillis();
+ System.out.println("Prefetched: " + (stop - start));
+ }
+
+ long start = System.currentTimeMillis();
+ for (Iterator<EObject> it = resource.eAllContents(); it.hasNext();)
+ {
+ it.next();
+ }
+
+ long stop = System.currentTimeMillis();
+ System.out.println("Iterated: " + (stop - start));
+
+ session.close();
+ System.out.println();
+ }
+ }
+
+ private void fillCompany(Company company)
+ {
+ for (int i = 0; i < 5; i++)
+ {
+ Category category = getModel1Factory().createCategory();
+ addUnique(company.getCategories(), category);
+ fillCategory(category, 5);
+ }
+
+ for (int i = 0; i < 1000; i++)
+ {
+ Supplier supplier = getModel1Factory().createSupplier();
+ addUnique(company.getSuppliers(), supplier);
+ }
+
+ for (int i = 0; i < 1000; i++)
+ {
+ Customer customer = getModel1Factory().createCustomer();
+ addUnique(company.getCustomers(), customer);
+ }
+
+ for (int i = 0; i < 1000; i++)
+ {
+ PurchaseOrder order = getModel1Factory().createPurchaseOrder();
+ order.setSupplier(company.getSuppliers().get(i));
+ addUnique(company.getPurchaseOrders(), order);
+
+ for (int j = 0; j < 100; j++)
+ {
+ OrderDetail orderDetail = getModel1Factory().createOrderDetail();
+ addUnique(order.getOrderDetails(), orderDetail);
+ }
+ }
+
+ for (int i = 0; i < 1000; i++)
+ {
+ SalesOrder order = getModel1Factory().createSalesOrder();
+ order.setCustomer(company.getCustomers().get(i));
+ addUnique(company.getSalesOrders(), order);
+
+ for (int j = 0; j < 100; j++)
+ {
+ OrderDetail orderDetail = getModel1Factory().createOrderDetail();
+ addUnique(order.getOrderDetails(), orderDetail);
+ }
+ }
+ }
+
+ private void fillCategory(Category category, int depth)
+ {
+ for (int i = 0; i < 5; i++)
+ {
+ Category child = getModel1Factory().createCategory();
+ addUnique(category.getCategories(), child);
+ if (depth > 1)
+ {
+ fillCategory(child, depth - 1);
+ }
+ }
+
+ for (int i = 0; i < 20; i++)
+ {
+ Product1 product = getModel1Factory().createProduct1();
+ addUnique(category.getProducts(), product);
+ }
+ }
+
+ private static <T extends EObject> void addUnique(EList<T> list, T object)
+ {
+ ((InternalEList<T>)list).addUnique(object);
+ // list.add(object);
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_485961_Test.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_485961_Test.java
index 7abbea6672..92c0c44cce 100644
--- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_485961_Test.java
+++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_485961_Test.java
@@ -54,13 +54,12 @@ public class Bugzilla_485961_Test extends AbstractCDOTest
InternalRepository repository = getRepository();
CDORevisionProvider revisionProvider = new ManagedRevisionProvider(repository.getRevisionManager(),
repository.getBranchManager().getMainBranch().getHead());
- CDOID rootResourceID = repository.getRootResourceID();
StoreThreadLocal.setSession(repository.getSessionManager().getSession(session.getSessionID()));
try
{
- assertEquals(8, traverse(revisionProvider, rootResourceID));
+ assertEquals(4, traverse(revisionProvider, res1.cdoID()));
}
finally
{
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOPushTransaction.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOPushTransaction.java
index 13ef778aaf..f139e2a2a7 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOPushTransaction.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOPushTransaction.java
@@ -32,6 +32,7 @@ import org.eclipse.emf.cdo.session.CDOSession;
import org.eclipse.emf.cdo.util.CommitException;
import org.eclipse.emf.cdo.view.CDOObjectHandler;
import org.eclipse.emf.cdo.view.CDOQuery;
+import org.eclipse.emf.cdo.view.CDOUnitManager;
import org.eclipse.emf.cdo.view.CDOView;
import org.eclipse.emf.cdo.view.CDOViewProvider;
import org.eclipse.emf.cdo.view.CDOViewSet;
@@ -954,6 +955,14 @@ public class CDOPushTransaction extends Notifier implements CDOTransaction
return delegate.getURIHandler();
}
+ /**
+ * @since 4.5
+ */
+ public CDOUnitManager getUnitManager()
+ {
+ return delegate.getUnitManager();
+ }
+
public String getCommitComment()
{
return delegate.getCommitComment();
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/view/CDOUnit.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/view/CDOUnit.java
new file mode 100644
index 0000000000..26acbe17e0
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/view/CDOUnit.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2016 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:
+ * Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.view;
+
+import org.eclipse.emf.ecore.EObject;
+
+/**
+ * @author Eike Stepper
+ * @since 4.5
+ */
+public interface CDOUnit
+{
+ public CDOUnitManager getManager();
+
+ public EObject getRoot();
+
+ public void close();
+}
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/view/CDOUnitManager.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/view/CDOUnitManager.java
new file mode 100644
index 0000000000..d31139c633
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/view/CDOUnitManager.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2016 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:
+ * Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.view;
+
+import org.eclipse.emf.cdo.common.util.CDOException;
+
+import org.eclipse.net4j.util.container.IContainer;
+
+import org.eclipse.emf.ecore.EObject;
+
+/**
+ * @author Eike Stepper
+ * @since 4.5
+ */
+public interface CDOUnitManager extends IContainer<CDOUnit>
+{
+ public CDOView getView();
+
+ public boolean isUnit(EObject root);
+
+ public CDOUnit createUnit(EObject root) throws UnitExistsException;
+
+ public CDOUnit openUnit(EObject root) throws UnitNotFoundException;
+
+ public CDOUnit getOpenUnit(EObject object);
+
+ public CDOUnit[] getOpenUnits();
+
+ /**
+ * @author Eike Stepper
+ */
+ public static final class UnitExistsException extends CDOException
+ {
+ private static final long serialVersionUID = 1L;
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ public static final class UnitNotFoundException extends CDOException
+ {
+ private static final long serialVersionUID = 1L;
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/view/CDOView.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/view/CDOView.java
index 223ced6a12..23bba9b120 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/view/CDOView.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/view/CDOView.java
@@ -155,6 +155,11 @@ public interface CDOView extends CDOCommonView, CDOUpdatable, CDOCommitHistory.P
public URIHandler getURIHandler();
/**
+ * @since 4.5
+ */
+ public CDOUnitManager getUnitManager();
+
+ /**
* Sets the {@link CDOBranch branch} and the point in (repository) time this view should refer to. {@link CDOObject
* Objects} provided by this view will be {@link CDORevision#isValid(long) valid} at this time. The special value
* {@link CDOCommonView#UNSPECIFIED_DATE UNSPECIFIED_DATE} denotes a "floating view" that always shows the latest
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/DelegatingSessionProtocol.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/DelegatingSessionProtocol.java
index d616a5ad11..7ce0726286 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/DelegatingSessionProtocol.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/DelegatingSessionProtocol.java
@@ -1061,6 +1061,22 @@ public class DelegatingSessionProtocol extends Lifecycle implements CDOSessionPr
}
}
+ public boolean requestUnit(int viewID, CDOID rootID, byte opcode, CDORevisionHandler revisionHandler)
+ {
+ int attempt = 0;
+ for (;;)
+ {
+ try
+ {
+ return delegate.requestUnit(viewID, rootID, opcode, revisionHandler);
+ }
+ catch (Exception ex)
+ {
+ handleException(++attempt, ex);
+ }
+ }
+ }
+
@Override
protected void doActivate() throws Exception
{
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOViewImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOViewImpl.java
index 71f3f4ed2b..bfa3444de4 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOViewImpl.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOViewImpl.java
@@ -25,9 +25,11 @@ import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo.Operation;
import org.eclipse.emf.cdo.common.lock.CDOLockOwner;
import org.eclipse.emf.cdo.common.lock.CDOLockState;
import org.eclipse.emf.cdo.common.lock.CDOLockUtil;
+import org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants;
import org.eclipse.emf.cdo.common.revision.CDOIDAndBranch;
import org.eclipse.emf.cdo.common.revision.CDOIDAndVersion;
import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionHandler;
import org.eclipse.emf.cdo.common.revision.CDORevisionKey;
import org.eclipse.emf.cdo.common.revision.CDORevisionManager;
import org.eclipse.emf.cdo.common.revision.CDORevisionsLoadedEvent;
@@ -51,6 +53,8 @@ import org.eclipse.emf.cdo.view.CDOFeatureAnalyzer;
import org.eclipse.emf.cdo.view.CDOInvalidationPolicy;
import org.eclipse.emf.cdo.view.CDORevisionPrefetchingPolicy;
import org.eclipse.emf.cdo.view.CDOStaleReferencePolicy;
+import org.eclipse.emf.cdo.view.CDOUnit;
+import org.eclipse.emf.cdo.view.CDOUnitManager;
import org.eclipse.emf.cdo.view.CDOView;
import org.eclipse.emf.cdo.view.CDOViewDurabilityChangedEvent;
import org.eclipse.emf.cdo.view.CDOViewInvalidationEvent;
@@ -74,6 +78,7 @@ import org.eclipse.net4j.util.concurrent.IExecutorServiceProvider;
import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
import org.eclipse.net4j.util.concurrent.IWorkSerializer;
import org.eclipse.net4j.util.concurrent.RunnableWithName;
+import org.eclipse.net4j.util.container.Container;
import org.eclipse.net4j.util.event.IEvent;
import org.eclipse.net4j.util.event.IListener;
import org.eclipse.net4j.util.event.Notifier;
@@ -95,6 +100,7 @@ import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.NotificationChain;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.InternalEObject;
+import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.spi.cdo.CDOSessionProtocol;
import org.eclipse.emf.spi.cdo.CDOSessionProtocol.LockObjectsResult;
import org.eclipse.emf.spi.cdo.CDOSessionProtocol.UnlockObjectsResult;
@@ -113,6 +119,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -135,6 +142,8 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv
private String durableLockingID;
+ private final CDOUnitManagerImpl unitManager = new CDOUnitManagerImpl();
+
private ChangeSubscriptionManager changeSubscriptionManager = new ChangeSubscriptionManager();
private AdapterManager adapterManager = new AdapterManager();
@@ -1805,6 +1814,247 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv
return id;
}
+ public final CDOUnitManagerImpl getUnitManager()
+ {
+ return unitManager;
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ protected final class CDOUnitManagerImpl extends Container<CDOUnit> implements CDOUnitManager
+ {
+ private final Map<EObject, CDOUnit> unitPerRoot = new HashMap<EObject, CDOUnit>();
+
+ private final Map<EObject, CDOUnit> unitPerObject = new HashMap<EObject, CDOUnit>();
+
+ public CDOUnitManagerImpl()
+ {
+ }
+
+ public CDOView getView()
+ {
+ return CDOViewImpl.this;
+ }
+
+ public boolean isUnit(EObject root)
+ {
+ CDOUnitImpl unit = requestUnit(root, CDOProtocolConstants.UNIT_CHECK);
+ return unit != null;
+ }
+
+ public CDOUnit createUnit(EObject root) throws UnitExistsException
+ {
+ CDOUnitImpl unit = requestUnit(root, CDOProtocolConstants.UNIT_CREATE);
+ if (unit == null)
+ {
+ throw new UnitExistsException();
+ }
+
+ fireElementAddedEvent(unit);
+ return unit;
+ }
+
+ public CDOUnit openUnit(EObject root) throws UnitNotFoundException
+ {
+ CDOUnitImpl unit = requestUnit(root, CDOProtocolConstants.UNIT_OPEN);
+ if (unit == null)
+ {
+ throw new UnitNotFoundException();
+ }
+
+ fireElementAddedEvent(unit);
+ return unit;
+ }
+
+ public CDOUnit getOpenUnit(EObject object)
+ {
+ synchronized (getViewMonitor())
+ {
+ lockView();
+
+ try
+ {
+ return getOpenUnitUnsynced(object);
+ }
+ finally
+ {
+ unlockView();
+ }
+ }
+ }
+
+ public CDOUnit getOpenUnitUnsynced(EObject object)
+ {
+ return unitPerObject.get(object);
+ }
+
+ public CDOUnit[] getOpenUnits()
+ {
+ return getElements();
+ }
+
+ public CDOUnit[] getElements()
+ {
+ synchronized (getViewMonitor())
+ {
+ lockView();
+
+ try
+ {
+ return unitPerRoot.values().toArray(new CDOUnit[unitPerRoot.size()]);
+ }
+ finally
+ {
+ unlockView();
+ }
+ }
+ }
+
+ private CDOObject getCDORoot(EObject root)
+ {
+ CDOObject cdoRoot = CDOUtil.getCDOObject(root);
+ if (cdoRoot == null)
+ {
+ throw new IllegalArgumentException("Root " + root + " is not managed by CDO");
+ }
+
+ CDOView view = cdoRoot.cdoView();
+ if (view != CDOViewImpl.this)
+ {
+ throw new IllegalArgumentException("Root " + root + " is managed by " + view);
+ }
+
+ return cdoRoot;
+ }
+
+ private CDOUnitImpl requestUnit(EObject root, byte opcode)
+ {
+ synchronized (getViewMonitor())
+ {
+ lockView();
+
+ try
+ {
+ CDOUnit containingUnit = getOpenUnit(root);
+ if (containingUnit != null)
+ {
+ throw new IllegalArgumentException("Root " + root + " is contained by " + containingUnit);
+ }
+
+ for (CDOUnit existingUnit : unitPerRoot.values())
+ {
+ if (EcoreUtil.isAncestor(root, existingUnit.getRoot()))
+ {
+ throw new IllegalArgumentException("Root " + root + " contains " + existingUnit);
+ }
+ }
+
+ final InternalCDORevisionManager revisionManager = session.getRevisionManager();
+ final CDOUnitImpl unit = new CDOUnitImpl(root);
+
+ int viewID = getViewID();
+ CDOID rootID = getCDORoot(root).cdoID();
+
+ CDOSessionProtocol sessionProtocol = session.getSessionProtocol();
+ boolean success = sessionProtocol.requestUnit(viewID, rootID, opcode, new CDORevisionHandler()
+ {
+ public boolean handleRevision(CDORevision revision)
+ {
+ revisionManager.addRevision(revision);
+
+ InternalCDOObject object = getObject(revision.getID());
+ unitPerObject.put(object, unit);
+
+ int xxx; // TODO Release possible change subscriptions!
+ return true;
+ }
+ });
+
+ if (success)
+ {
+ if (opcode == CDOProtocolConstants.UNIT_CREATE || opcode == CDOProtocolConstants.UNIT_OPEN)
+ {
+ unitPerRoot.put(root, unit);
+ unitPerObject.put(root, unit);
+ }
+
+ return unit;
+ }
+
+ return null;
+ }
+ finally
+ {
+ unlockView();
+ }
+ }
+ }
+
+ private void closeUnit(CDOUnit unit)
+ {
+ synchronized (getViewMonitor())
+ {
+ lockView();
+
+ try
+ {
+ for (Iterator<CDOUnit> it = unitPerObject.values().iterator(); it.hasNext();)
+ {
+ if (it.next() == unit)
+ {
+ int xxx; // TODO Re-create needed change subscriptions?
+
+ it.remove();
+ }
+ }
+
+ unitPerRoot.remove(unit.getRoot());
+ }
+ finally
+ {
+ unlockView();
+ }
+ }
+
+ fireElementRemovedEvent(unit);
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ protected final class CDOUnitImpl implements CDOUnit
+ {
+ private final EObject root;
+
+ public CDOUnitImpl(EObject root)
+ {
+ this.root = root;
+ }
+
+ public CDOUnitManagerImpl getManager()
+ {
+ return CDOUnitManagerImpl.this;
+ }
+
+ public EObject getRoot()
+ {
+ return root;
+ }
+
+ public void close()
+ {
+ closeUnit(this);
+ }
+
+ @Override
+ public String toString()
+ {
+ return "CDOUnit[" + root + "]";
+ }
+ }
+ }
+
/**
* @author Simon McDuff
* @since 2.0
@@ -1926,7 +2176,7 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv
/**
* Register to the server all objects from the active list
*/
- private void notifyChangeSubcriptionPolicy()
+ private void handleChangeSubcriptionPoliciesChanged()
{
boolean policiesPresent = options().hasChangeSubscriptionPolicies();
subscriptions.clear();
@@ -2814,7 +3064,7 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv
{
if (changeSubscriptionPolicies.add(policy))
{
- changeSubscriptionManager.notifyChangeSubcriptionPolicy();
+ changeSubscriptionManager.handleChangeSubcriptionPoliciesChanged();
event = new ChangeSubscriptionPoliciesEventImpl();
}
}
@@ -2840,7 +3090,7 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv
{
if (changeSubscriptionPolicies.remove(policy) && !changeSubscriptionPolicies.contains(policy))
{
- changeSubscriptionManager.notifyChangeSubcriptionPolicy();
+ changeSubscriptionManager.handleChangeSubcriptionPoliciesChanged();
event = new ChangeSubscriptionPoliciesEventImpl();
}
}
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/CDOSessionProtocol.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/CDOSessionProtocol.java
index ec58ab8fcd..1b7fe9ab91 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/CDOSessionProtocol.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/CDOSessionProtocol.java
@@ -35,6 +35,7 @@ import org.eclipse.emf.cdo.common.protocol.CDODataInput;
import org.eclipse.emf.cdo.common.protocol.CDOProtocol;
import org.eclipse.emf.cdo.common.revision.CDOIDAndVersion;
import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionHandler;
import org.eclipse.emf.cdo.common.revision.CDORevisionKey;
import org.eclipse.emf.cdo.common.security.CDOPermission;
import org.eclipse.emf.cdo.common.util.CDOCommonUtil;
@@ -343,6 +344,11 @@ public interface CDOSessionProtocol extends CDOProtocol, PackageLoader, BranchLo
public void requestResetCredentials(String userID);
/**
+ * @since 4.5
+ */
+ public boolean requestUnit(int viewID, CDOID rootID, byte opcode, CDORevisionHandler revisionHandler);
+
+ /**
* If the meaning of this type isn't clear, there really should be more of a description here...
*
* @author Eike Stepper
diff --git a/plugins/org.eclipse.net4j.db.h2/H2 Browser.launch b/plugins/org.eclipse.net4j.db.h2/H2 Browser.launch
new file mode 100644
index 0000000000..acf966ae38
--- /dev/null
+++ b/plugins/org.eclipse.net4j.db.h2/H2 Browser.launch
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="org.eclipse.jdt.launching.localJavaApplication">
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
+<listEntry value="/org.eclipse.net4j.db.h2"/>
+</listAttribute>
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
+<listEntry value="4"/>
+</listAttribute>
+<booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD" value="true"/>
+<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.h2.tools.Server"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.net4j.db.h2"/>
+<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xms1G&#13;&#10;-Xmx1G"/>
+</launchConfiguration>

Back to the top