From c5ba80ea1b0b1c9f9bd8e3730112d078136a82c5 Mon Sep 17 00:00:00 2001 From: Eike Stepper Date: Thu, 28 Jan 2016 16:20:52 +0100 Subject: [486458] Provide support for optimized loading and notifying of object units https://bugs.eclipse.org/bugs/show_bug.cgi?id=486458--- .../org.eclipse.net4j.db.mysql-feature/feature.xml | 2 +- .../emf/cdo/common/revision/CDORevisionUtil.java | 37 +- .../emf/cdo/server/internal/db/CDODBSchema.java | 67 ++- .../cdo/server/internal/db/DBStoreAccessor.java | 78 +++- .../cdo/server/internal/db/MetaDataManager.java | 8 +- .../db/mapping/horizontal/UnitMappingTable.java | 173 +++++-- .../hibernate/HibernateRawCommitContext.java | 7 +- .../emf/cdo/internal/server/Repository.java | 42 +- .../internal/server/TransactionCommitContext.java | 2 +- .../emf/cdo/internal/server/UnitManager.java | 505 ++++++++++++++++++--- .../org/eclipse/emf/cdo/server/IStoreAccessor.java | 9 +- .../emf/cdo/spi/server/InternalCommitContext.java | 5 + .../emf/cdo/spi/server/InternalRepository.java | 5 + .../emf/cdo/spi/server/InternalUnitManager.java | 34 ++ .../eclipse/emf/cdo/spi/server/StoreAccessor.java | 22 +- .../src/org/eclipse/emf/cdo/tests/AllConfigs.java | 1 - .../META-INF/MANIFEST.MF | 6 +- .../org/eclipse/net4j/db/mysql/MYSQLAdapter.java | 77 ++-- .../src/org/eclipse/net4j/db/IDBAdapter.java | 5 + .../org/eclipse/net4j/internal/db/DBDatabase.java | 4 +- .../src/org/eclipse/net4j/spi/db/DBAdapter.java | 8 + .../eclipse/net4j/buffer/BufferInputStream.java | 10 +- 22 files changed, 880 insertions(+), 227 deletions(-) create mode 100644 plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalUnitManager.java diff --git a/features/org.eclipse.net4j.db.mysql-feature/feature.xml b/features/org.eclipse.net4j.db.mysql-feature/feature.xml index a76aadd927..41fbf937ee 100644 --- a/features/org.eclipse.net4j.db.mysql-feature/feature.xml +++ b/features/org.eclipse.net4j.db.mysql-feature/feature.xml @@ -12,7 +12,7 @@ diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/revision/CDORevisionUtil.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/revision/CDORevisionUtil.java index 5cccda0ea2..88b674503b 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/revision/CDORevisionUtil.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/revision/CDORevisionUtil.java @@ -323,20 +323,40 @@ public final class CDORevisionUtil return true; } - InternalCDORevision parent = getParentRevision(child, provider); + CDORevision parent = getParentRevision(child, provider); if (parent != null) { - return isContained(parent, container, provider); + return isContained((InternalCDORevision)parent, container, provider); } return false; } - private static InternalCDORevision getParentRevision(InternalCDORevision revision, CDORevisionProvider provider) + /** + * @since 4.5 + */ + public static void handleParentRevisions(CDORevision revision, CDORevisionProvider provider, + CDORevisionHandler handler) + { + CDORevision parentRevision = getParentRevision(revision, provider); + if (parentRevision != null) + { + if (handler.handleRevision(parentRevision)) + { + handleParentRevisions(parentRevision, provider, handler); + } + } + } + + /** + * @since 4.5 + */ + public static CDORevision getParentRevision(CDORevision revision, CDORevisionProvider provider) { CDOID parentID; + CDORevisionData data = revision.data(); - Object containerID = revision.getContainerID(); + Object containerID = data.getContainerID(); if (containerID instanceof CDOWithID) { parentID = ((CDOWithID)containerID).cdoID(); @@ -348,7 +368,7 @@ public final class CDORevisionUtil if (CDOIDUtil.isNull(parentID)) { - parentID = revision.getResourceID(); + parentID = data.getResourceID(); if (CDOIDUtil.isNull(parentID)) { return null; @@ -361,9 +381,12 @@ public final class CDORevisionUtil } } - return (InternalCDORevision)provider.getRevision(parentID); + return provider.getRevision(parentID); } + /** + * @since 4.5 + */ /** * @since 4.4 */ @@ -485,7 +508,7 @@ public final class CDORevisionUtil } else { - container = getParentRevision(revision, provider); + container = (InternalCDORevision)getParentRevision(revision, provider); } if (container != null) diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/CDODBSchema.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/CDODBSchema.java index 6b42da68b6..efc86e0dc7 100644 --- a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/CDODBSchema.java +++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/CDODBSchema.java @@ -35,13 +35,13 @@ public class CDODBSchema public static final IDBTable PROPERTIES = INSTANCE.addTable("cdo_properties"); //$NON-NLS-1$ public static final IDBField PROPERTIES_NAME = // - PROPERTIES.addField("name", DBType.VARCHAR, 255, true); //$NON-NLS-1$ + PROPERTIES.addField("name", DBType.VARCHAR, 255, true); //$NON-NLS-1$ public static final IDBField PROPERTIES_VALUE = // - PROPERTIES.addField("value", DBType.LONGVARCHAR); //$NON-NLS-1$ + PROPERTIES.addField("value", DBType.LONGVARCHAR); //$NON-NLS-1$ public static final IDBIndex INDEX_PROPERTIES_PK = // - PROPERTIES.addIndex(IDBIndex.Type.PRIMARY_KEY, PROPERTIES_NAME); + PROPERTIES.addIndex(IDBIndex.Type.PRIMARY_KEY, PROPERTIES_NAME); public static final String SQL_DELETE_PROPERTIES = "DELETE FROM " + PROPERTIES + " WHERE " + PROPERTIES_NAME + "=?"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ @@ -60,19 +60,19 @@ public class CDODBSchema public static final IDBTable PACKAGE_UNITS = INSTANCE.addTable("cdo_package_units"); //$NON-NLS-1$ public static final IDBField PACKAGE_UNITS_ID = // - PACKAGE_UNITS.addField("id", DBType.VARCHAR, 255, true); //$NON-NLS-1$ + PACKAGE_UNITS.addField("id", DBType.VARCHAR, 255, true); //$NON-NLS-1$ public static final IDBField PACKAGE_UNITS_ORIGINAL_TYPE = // - PACKAGE_UNITS.addField("original_type", DBType.INTEGER); //$NON-NLS-1$ + PACKAGE_UNITS.addField("original_type", DBType.INTEGER); //$NON-NLS-1$ public static final IDBField PACKAGE_UNITS_TIME_STAMP = // - PACKAGE_UNITS.addField("time_stamp", DBType.BIGINT); //$NON-NLS-1$ + PACKAGE_UNITS.addField("time_stamp", DBType.BIGINT); //$NON-NLS-1$ public static final IDBField PACKAGE_UNITS_PACKAGE_DATA = // - PACKAGE_UNITS.addField("package_data", DBType.BLOB); //$NON-NLS-1$ + PACKAGE_UNITS.addField("package_data", DBType.BLOB); //$NON-NLS-1$ public static final IDBIndex INDEX_PACKAGE_UNITS_PK = // - PACKAGE_UNITS.addIndex(IDBIndex.Type.PRIMARY_KEY, PACKAGE_UNITS_ID); + PACKAGE_UNITS.addIndex(IDBIndex.Type.PRIMARY_KEY, PACKAGE_UNITS_ID); /** * DBTable cdo_packages @@ -80,22 +80,22 @@ public class CDODBSchema public static final IDBTable PACKAGE_INFOS = INSTANCE.addTable("cdo_package_infos"); //$NON-NLS-1$ public static final IDBField PACKAGE_INFOS_URI = // - PACKAGE_INFOS.addField("uri", DBType.VARCHAR, 255, true); //$NON-NLS-1$ + PACKAGE_INFOS.addField("uri", DBType.VARCHAR, 255, true); //$NON-NLS-1$ public static final IDBField PACKAGE_INFOS_PARENT = // - PACKAGE_INFOS.addField("parent", DBType.VARCHAR, 255); //$NON-NLS-1$ + PACKAGE_INFOS.addField("parent", DBType.VARCHAR, 255); //$NON-NLS-1$ public static final IDBField PACKAGE_INFOS_UNIT = // - PACKAGE_INFOS.addField("unit", DBType.VARCHAR, 255); //$NON-NLS-1$ + PACKAGE_INFOS.addField("unit", DBType.VARCHAR, 255); //$NON-NLS-1$ public static final IDBIndex INDEX_PACKAGE_INFOS_PK = // - PACKAGE_INFOS.addIndex(IDBIndex.Type.PRIMARY_KEY, PACKAGE_INFOS_URI); + PACKAGE_INFOS.addIndex(IDBIndex.Type.PRIMARY_KEY, PACKAGE_INFOS_URI); public static final IDBIndex INDEX_PACKAGE_INFOS_PARENT = // - PACKAGE_INFOS.addIndex(IDBIndex.Type.NON_UNIQUE, PACKAGE_INFOS_PARENT); + PACKAGE_INFOS.addIndex(IDBIndex.Type.NON_UNIQUE, PACKAGE_INFOS_PARENT); public static final IDBIndex INDEX_PACKAGE_INFOS_UNIT = // - PACKAGE_INFOS.addIndex(IDBIndex.Type.NON_UNIQUE, PACKAGE_INFOS_UNIT); + PACKAGE_INFOS.addIndex(IDBIndex.Type.NON_UNIQUE, PACKAGE_INFOS_UNIT); /** * DBTable cdo_branches @@ -103,19 +103,19 @@ public class CDODBSchema public static final IDBTable BRANCHES = INSTANCE.addTable("cdo_branches"); //$NON-NLS-1$ public static final IDBField BRANCHES_ID = // - BRANCHES.addField("id", DBType.INTEGER, true); //$NON-NLS-1$ + BRANCHES.addField("id", DBType.INTEGER, true); //$NON-NLS-1$ public static final IDBField BRANCHES_NAME = // - BRANCHES.addField("name", DBType.VARCHAR); //$NON-NLS-1$ + BRANCHES.addField("name", DBType.VARCHAR); //$NON-NLS-1$ public static final IDBField BRANCHES_BASE_BRANCH_ID = // - BRANCHES.addField("base_id", DBType.INTEGER); //$NON-NLS-1$ + BRANCHES.addField("base_id", DBType.INTEGER); //$NON-NLS-1$ public static final IDBField BRANCHES_BASE_TIMESTAMP = // - BRANCHES.addField("base_time", DBType.BIGINT); //$NON-NLS-1$ + BRANCHES.addField("base_time", DBType.BIGINT); //$NON-NLS-1$ public static final IDBIndex INDEX_BRANCHES_ID = // - BRANCHES.addIndex(IDBIndex.Type.PRIMARY_KEY, BRANCHES_ID); + BRANCHES.addIndex(IDBIndex.Type.PRIMARY_KEY, BRANCHES_ID); public static final String SQL_CREATE_BRANCH = "INSERT INTO " + BRANCHES + " (" + BRANCHES_ID + ", " + BRANCHES_NAME //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + ", " + BRANCHES_BASE_BRANCH_ID + ", " + BRANCHES_BASE_TIMESTAMP + ") VALUES (?, ?, ?, ?)"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ @@ -139,33 +139,32 @@ public class CDODBSchema public static final IDBTable COMMIT_INFOS = INSTANCE.addTable("cdo_commit_infos"); //$NON-NLS-1$ public static final IDBField COMMIT_INFOS_TIMESTAMP = // - COMMIT_INFOS.addField("commit_time", DBType.BIGINT, true); //$NON-NLS-1$ + COMMIT_INFOS.addField("commit_time", DBType.BIGINT, true); //$NON-NLS-1$ public static final IDBField COMMIT_INFOS_PREVIOUS_TIMESTAMP = // - COMMIT_INFOS.addField("previous_time", DBType.BIGINT); //$NON-NLS-1$ + COMMIT_INFOS.addField("previous_time", DBType.BIGINT); //$NON-NLS-1$ public static final IDBField COMMIT_INFOS_BRANCH = // - COMMIT_INFOS.addField("branch_id", DBType.INTEGER); //$NON-NLS-1$ + COMMIT_INFOS.addField("branch_id", DBType.INTEGER); //$NON-NLS-1$ public static final IDBField COMMIT_INFOS_USER = // - COMMIT_INFOS.addField("user_id", DBType.VARCHAR); //$NON-NLS-1$ + COMMIT_INFOS.addField("user_id", DBType.VARCHAR); //$NON-NLS-1$ public static final IDBField COMMIT_INFOS_COMMENT = // - COMMIT_INFOS.addField("commit_comment", DBType.VARCHAR); //$NON-NLS-1$ + COMMIT_INFOS.addField("commit_comment", DBType.VARCHAR); //$NON-NLS-1$ public static final IDBIndex INDEX_COMMIT_INFOS_PK = // - COMMIT_INFOS.addIndex(IDBIndex.Type.PRIMARY_KEY, COMMIT_INFOS_TIMESTAMP); + COMMIT_INFOS.addIndex(IDBIndex.Type.PRIMARY_KEY, COMMIT_INFOS_TIMESTAMP); public static final IDBIndex INDEX_COMMIT_INFOS_BRANCH = // - COMMIT_INFOS.addIndex(IDBIndex.Type.NON_UNIQUE, COMMIT_INFOS_BRANCH); + COMMIT_INFOS.addIndex(IDBIndex.Type.NON_UNIQUE, COMMIT_INFOS_BRANCH); public static final IDBIndex INDEX_COMMIT_INFOS_USER = // - COMMIT_INFOS.addIndex(IDBIndex.Type.NON_UNIQUE, COMMIT_INFOS_USER); + COMMIT_INFOS.addIndex(IDBIndex.Type.NON_UNIQUE, COMMIT_INFOS_USER); public static final String SQL_CREATE_COMMIT_INFO = "INSERT INTO " + COMMIT_INFOS + "(" + COMMIT_INFOS_TIMESTAMP //$NON-NLS-1$ //$NON-NLS-2$ + ", " + COMMIT_INFOS_PREVIOUS_TIMESTAMP + ", " + COMMIT_INFOS_BRANCH + ", " + COMMIT_INFOS_USER + ", " //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ - + COMMIT_INFOS_COMMENT + ") " - + "VALUES (?, ?, ?, ?, ?)"; //$NON-NLS-1$ + + COMMIT_INFOS_COMMENT + ") " + "VALUES (?, ?, ?, ?, ?)"; //$NON-NLS-2$ /** * DBTable cdo_lobs @@ -173,19 +172,19 @@ public class CDODBSchema public static final IDBTable LOBS = INSTANCE.addTable("cdo_lobs"); //$NON-NLS-1$ public static final IDBField LOBS_ID = // - LOBS.addField("id", DBType.VARCHAR, 64, true); //$NON-NLS-1$ + LOBS.addField("id", DBType.VARCHAR, 64, true); //$NON-NLS-1$ public static final IDBField LOBS_SIZE = // - LOBS.addField("lsize", DBType.BIGINT); //$NON-NLS-1$ + LOBS.addField("lsize", DBType.BIGINT); //$NON-NLS-1$ public static final IDBField LOBS_BDATA = // - LOBS.addField("bdata", DBType.BLOB); //$NON-NLS-1$ + LOBS.addField("bdata", DBType.BLOB); //$NON-NLS-1$ public static final IDBField LOBS_CDATA = // - LOBS.addField("cdata", DBType.CLOB); //$NON-NLS-1$ + LOBS.addField("cdata", DBType.CLOB); //$NON-NLS-1$ public static final IDBIndex INDEX_LOBS_ID = // - LOBS.addIndex(IDBIndex.Type.PRIMARY_KEY, LOBS_ID); + LOBS.addIndex(IDBIndex.Type.PRIMARY_KEY, LOBS_ID); public static final String SQL_QUERY_LOBS = "SELECT 1 FROM " + CDODBSchema.LOBS + " WHERE " + CDODBSchema.LOBS_ID //$NON-NLS-1$ //$NON-NLS-2$ + "=?"; //$NON-NLS-1$ 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 3af8e796b4..6b68a0f219 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 @@ -65,6 +65,8 @@ import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionDelta; import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager; import org.eclipse.emf.cdo.spi.server.InternalCommitContext; import org.eclipse.emf.cdo.spi.server.InternalRepository; +import org.eclipse.emf.cdo.spi.server.InternalUnitManager; +import org.eclipse.emf.cdo.spi.server.InternalUnitManager.InternalObjectAttacher; import org.eclipse.emf.cdo.spi.server.StoreAccessor; import org.eclipse.net4j.db.DBException; @@ -120,10 +122,10 @@ public class DBStoreAccessor extends StoreAccessor implements IDBStoreAccessor, private ConnectionKeepAliveTask connectionKeepAliveTask; - private Set newObjects = new HashSet(); - private CDOID maxID = CDOID.NULL; + private InternalObjectAttacher objectAttacher; + public DBStoreAccessor(DBStore store, ISession session) throws DBException { super(store, session); @@ -493,7 +495,6 @@ public class DBStoreAccessor extends StoreAccessor implements IDBStoreAccessor, for (InternalCDORevision revision : context.getNewObjects()) { CDOID id = revision.getID(); - newObjects.add(id); if (adjustMaxID && idHandler.compare(id, maxID) > 0) { @@ -563,24 +564,52 @@ public class DBStoreAccessor extends StoreAccessor implements IDBStoreAccessor, } @Override - protected void writeRevisions(InternalCDORevision[] revisions, CDOBranch branch, OMMonitor monitor) + protected void writeNewObjectRevisions(InternalCommitContext context, InternalCDORevision[] newObjects, + CDOBranch branch, OMMonitor monitor) + { + writeRevisions(context, true, newObjects, branch, monitor); + } + + @Override + protected void writeDirtyObjectRevisions(InternalCommitContext context, InternalCDORevision[] dirtyObjects, + CDOBranch branch, OMMonitor monitor) + { + writeRevisions(context, false, dirtyObjects, branch, monitor); + } + + protected void writeRevisions(InternalCommitContext context, boolean attachNewObjects, + InternalCDORevision[] revisions, CDOBranch branch, OMMonitor monitor) { try { monitor.begin(revisions.length); for (InternalCDORevision revision : revisions) { - boolean mapType = newObjects.contains(revision.getID()); - writeRevision(revision, mapType, true, monitor.fork()); + writeRevision(revision, attachNewObjects, true, monitor.fork()); + } + + if (attachNewObjects) + { + InternalRepository repository = getStore().getRepository(); + if (repository.isSupportingUnits()) + { + InternalUnitManager unitManager = repository.getUnitManager(); + objectAttacher = unitManager.attachObjects(context); // TODO Fork a monitor. + } } } finally { - newObjects.clear(); monitor.done(); } } + @Override + protected void writeRevisions(InternalCDORevision[] revisions, CDOBranch branch, OMMonitor monitor) + { + throw new UnsupportedOperationException(); + } + protected void writeRevision(InternalCDORevision revision, boolean mapType, boolean revise, OMMonitor monitor) { if (TRACER.isEnabled()) @@ -711,6 +740,12 @@ public class DBStoreAccessor extends StoreAccessor implements IDBStoreAccessor, getStore().getIDHandler().adjustLastObjectID(maxID); maxID = CDOID.NULL; } + + if (objectAttacher != null) + { + objectAttacher.finishedCommit(true); + objectAttacher = null; + } } finally { @@ -733,6 +768,12 @@ public class DBStoreAccessor extends StoreAccessor implements IDBStoreAccessor, @Override protected final void doRollback(IStoreAccessor.CommitContext commitContext) { + if (objectAttacher != null) + { + objectAttacher.finishedCommit(false); + objectAttacher = null; + } + getStore().getMetaDataManager().clearMetaIDMappings(); if (TRACER.isEnabled()) @@ -761,6 +802,7 @@ public class DBStoreAccessor extends StoreAccessor implements IDBStoreAccessor, DBStore store = getStore(); connection = store.getDatabase().getConnection(); connectionKeepAliveTask = new ConnectionKeepAliveTask(this); + objectAttacher = null; long keepAlivePeriod = ConnectionKeepAliveTask.EXECUTION_PERIOD; Map storeProps = store.getProperties(); @@ -1459,17 +1501,29 @@ public class DBStoreAccessor extends StoreAccessor implements IDBStoreAccessor, return unitMappingTable.readUnitRoots(this); } - public void initUnit(IView view, CDOID rootID, CDORevisionHandler revisionHandler) + public void readUnit(IView view, CDOID rootID, CDORevisionHandler revisionHandler) { - long created = getStore().getRepository().getTimeStamp(); UnitMappingTable unitMappingTable = getStore().getUnitMappingTable(); - unitMappingTable.initUnit(this, view, rootID, created, revisionHandler); + unitMappingTable.readUnitRevisions(this, view, rootID, revisionHandler); } - public void readUnit(IView view, CDOID rootID, CDORevisionHandler revisionHandler) + public Object initUnit(IView view, CDOID rootID, CDORevisionHandler revisionHandler, long timeStamp) { UnitMappingTable unitMappingTable = getStore().getUnitMappingTable(); - unitMappingTable.readUnitRevisions(this, view, rootID, revisionHandler); + return unitMappingTable.initUnit(this, timeStamp, view, rootID, revisionHandler); + } + + public void finishUnit(IView view, CDOID rootID, CDORevisionHandler revisionHandler, long timeStamp, + Object initResult, List ids) + { + UnitMappingTable unitMappingTable = getStore().getUnitMappingTable(); + unitMappingTable.finishUnit(rootID, timeStamp, initResult, ids); + } + + public void writeUnits(Map unitMappings, long timeStamp) + { + UnitMappingTable unitMappingTable = getStore().getUnitMappingTable(); + unitMappingTable.writeUnitMappings(this, unitMappings, timeStamp); } /** diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/MetaDataManager.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/MetaDataManager.java index 71ad7546e0..77abb2bd05 100644 --- a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/MetaDataManager.java +++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/MetaDataManager.java @@ -238,8 +238,11 @@ public class MetaDataManager extends Lifecycle implements IMetaDataManager try { - String sql = "INSERT INTO " + CDODBSchema.PACKAGE_UNITS + " VALUES (?, ?, ?, ?)"; //$NON-NLS-1$ //$NON-NLS-2$ + String sql = "INSERT INTO " + CDODBSchema.PACKAGE_UNITS + " (" + CDODBSchema.PACKAGE_UNITS_ID + ", " //$NON-NLS-1$ //$NON-NLS-2$ + + CDODBSchema.PACKAGE_UNITS_ORIGINAL_TYPE + ", " + CDODBSchema.PACKAGE_UNITS_TIME_STAMP + ", " + + CDODBSchema.PACKAGE_UNITS_PACKAGE_DATA + ") VALUES (?, ?, ?, ?)"; DBUtil.trace(sql); + IDBPreparedStatement stmt = connection.prepareStatement(sql, ReuseProbability.MEDIUM); try @@ -311,7 +314,8 @@ public class MetaDataManager extends Lifecycle implements IMetaDataManager String parentURI = packageInfo.getParentURI(); String unitID = packageInfo.getPackageUnit().getID(); - String sql = "INSERT INTO " + CDODBSchema.PACKAGE_INFOS + " VALUES (?, ?, ?)"; //$NON-NLS-1$ //$NON-NLS-2$ + String sql = "INSERT INTO " + CDODBSchema.PACKAGE_INFOS + " (" + CDODBSchema.PACKAGE_INFOS_URI + ", " //$NON-NLS-1$ //$NON-NLS-2$ + + CDODBSchema.PACKAGE_INFOS_PARENT + ", " + CDODBSchema.PACKAGE_INFOS_UNIT + ") VALUES (?, ?, ?)"; DBUtil.trace(sql); IDBPreparedStatement stmt = connection.prepareStatement(sql, ReuseProbability.MEDIUM); 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 index f44d2456da..4fcc7fcd0d 100644 --- 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 @@ -37,6 +37,7 @@ 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.collection.Pair; import org.eclipse.net4j.util.lifecycle.Lifecycle; import org.eclipse.emf.ecore.EClass; @@ -46,6 +47,8 @@ import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.Map.Entry; /** * @author Eike Stepper @@ -63,7 +66,8 @@ public class UnitMappingTable extends Lifecycle implements IMappingConstants 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_INSERT_MAPPINGS = "INSERT INTO " + UNITS + " (" + UNITS_ELEM + ", " + UNITS_UNIT + + ") 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 + "=?"; @@ -113,24 +117,32 @@ public class UnitMappingTable extends Lifecycle implements IMappingConstants return rootIDs; } - public void initUnit(IDBStoreAccessor accessor, IView view, CDOID rootID, long created, - CDORevisionHandler revisionHandler) + public void readUnitRevisions(IDBStoreAccessor accessor, IView view, CDOID rootID, CDORevisionHandler revisionHandler) { - IIDHandler idHandler = mappingStrategy.getStore().getIDHandler(); + IDBStore store = mappingStrategy.getStore(); + IIDHandler idHandler = store.getIDHandler(); + IMetaDataManager metaDataManager = store.getMetaDataManager(); + IDBConnection connection = accessor.getDBConnection(); - IDBPreparedStatement stmt = connection.prepareStatement(SQL_INSERT_MAPPINGS, ReuseProbability.HIGH); + IDBPreparedStatement stmt = connection.prepareStatement(SQL_SELECT_CLASSES, ReuseProbability.HIGH); + int oldFetchSize = -1; try { - CDORevision revision = view.getRevision(rootID); - int batchCount = 0; + idHandler.setCDOID(stmt, 1, rootID); + + oldFetchSize = stmt.getFetchSize(); + stmt.setFetchSize(100000); + ResultSet resultSet = stmt.executeQuery(); - if (initUnit(accessor, idHandler, stmt, view, rootID, created, revisionHandler, revision, batchCount) != 0) + while (resultSet.next()) { - stmt.executeBatch(); - } + CDOID classID = idHandler.getCDOID(resultSet, 1); + EClass eClass = (EClass)metaDataManager.getMetaInstance(classID); - connection.commit(); + IClassMappingUnitSupport classMapping = (IClassMappingUnitSupport)mappingStrategy.getClassMapping(eClass); + classMapping.readUnitRevisions(accessor, view, rootID, revisionHandler); + } } catch (SQLException ex) { @@ -138,63 +150,88 @@ public class UnitMappingTable extends Lifecycle implements IMappingConstants } finally { + if (oldFetchSize != -1) + { + try + { + stmt.setFetchSize(oldFetchSize); + } + catch (SQLException ex) + { + throw new DBException(ex); + } + } + 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 + public Object initUnit(IDBStoreAccessor accessor, long timeStamp, IView view, CDOID rootID, + CDORevisionHandler revisionHandler) { - revisionHandler.handleRevision(revision); + IIDHandler idHandler = mappingStrategy.getStore().getIDHandler(); + IDBConnection connection = accessor.getDBConnection(); + IDBPreparedStatement stmt = connection.prepareStatement(SQL_INSERT_MAPPINGS, ReuseProbability.HIGH); - CDOID id = revision.getID(); - idHandler.setCDOID(stmt, 1, id); - idHandler.setCDOID(stmt, 2, rootID); - // stmt.setLong(3, created); - stmt.addBatch(); + try + { + CDORevision revision = view.getRevision(rootID); - if (++batchCount > WRITE_UNIT_MAPPING_BATCH_SIZE) + int batchCount = initUnit(stmt, view, rootID, revisionHandler, timeStamp, idHandler, revision, 0); + return Pair.create(stmt, batchCount); + } + catch (SQLException ex) { - stmt.executeBatch(); - batchCount = 0; + throw new DBException(ex); + } + finally + { + // Don't close the statement; that's done later in finishUnit(). } + } + + private int initUnit(IDBPreparedStatement stmt, IView view, CDOID rootID, CDORevisionHandler revisionHandler, + long timeStamp, IIDHandler idHandler, CDORevision revision, int batchCount) throws SQLException + { + revisionHandler.handleRevision(revision); + + CDOID id = revision.getID(); + batchCount = writeUnitMapping(stmt, rootID, timeStamp, idHandler, id, batchCount); List children = CDORevisionUtil.getChildRevisions(revision, view, true); for (CDORevision child : children) { - batchCount = initUnit(accessor, idHandler, stmt, view, rootID, created, revisionHandler, child, batchCount); + batchCount = initUnit(stmt, view, rootID, revisionHandler, timeStamp, idHandler, child, batchCount); } return batchCount; } - public void readUnitRevisions(IDBStoreAccessor accessor, IView view, CDOID rootID, CDORevisionHandler revisionHandler) + public void finishUnit(CDOID rootID, long timeStamp, Object initResult, List ids) { + @SuppressWarnings("unchecked") + Pair pair = (Pair)initResult; + + IDBPreparedStatement stmt = pair.getElement1(); + int batchCount = pair.getElement2(); + 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()) + for (CDOID id : ids) { - CDOID classID = idHandler.getCDOID(resultSet, 1); - EClass eClass = (EClass)metaDataManager.getMetaInstance(classID); + batchCount = writeUnitMapping(stmt, rootID, timeStamp, idHandler, id, batchCount); + } - IClassMappingUnitSupport classMapping = (IClassMappingUnitSupport)mappingStrategy.getClassMapping(eClass); - classMapping.readUnitRevisions(accessor, view, rootID, revisionHandler); + if (batchCount != 0) + { + stmt.executeBatch(); } + + IDBConnection connection = stmt.getConnection(); + connection.commit(); } catch (SQLException ex) { @@ -202,22 +239,58 @@ public class UnitMappingTable extends Lifecycle implements IMappingConstants } finally { - if (oldFetchSize != -1) + DBUtil.close(stmt); + } + } + + public void writeUnitMappings(IDBStoreAccessor accessor, Map unitMappings, long timeStamp) + { + IIDHandler idHandler = mappingStrategy.getStore().getIDHandler(); + IDBConnection connection = accessor.getDBConnection(); + IDBPreparedStatement stmt = connection.prepareStatement(SQL_INSERT_MAPPINGS, ReuseProbability.HIGH); + int batchCount = 0; + + try + { + for (Entry entry : unitMappings.entrySet()) { - try - { - stmt.setFetchSize(oldFetchSize); - } - catch (SQLException ex) - { - throw new DBException(ex); - } + CDOID id = entry.getKey(); + CDOID rootID = entry.getValue(); + batchCount = writeUnitMapping(stmt, rootID, timeStamp, idHandler, id, batchCount); } + if (batchCount != 0) + { + stmt.executeBatch(); + } + } + catch (SQLException ex) + { + throw new DBException(ex); + } + finally + { DBUtil.close(stmt); } } + private int writeUnitMapping(IDBPreparedStatement stmt, CDOID rootID, long timeStamp, IIDHandler idHandler, CDOID id, + int batchCount) throws SQLException + { + idHandler.setCDOID(stmt, 1, id); + idHandler.setCDOID(stmt, 2, rootID); + // stmt.setLong(3, timeStamp); + stmt.addBatch(); + + if (++batchCount > WRITE_UNIT_MAPPING_BATCH_SIZE) + { + stmt.executeBatch(); + batchCount = 0; + } + + return batchCount; + } + @Override protected void doActivate() throws Exception { diff --git a/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/HibernateRawCommitContext.java b/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/HibernateRawCommitContext.java index abf8fb61a0..c6ce59833c 100644 --- a/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/HibernateRawCommitContext.java +++ b/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/HibernateRawCommitContext.java @@ -20,6 +20,7 @@ import org.eclipse.emf.cdo.common.id.CDOIDUtil; import org.eclipse.emf.cdo.common.lock.CDOLockState; import org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants; import org.eclipse.emf.cdo.common.revision.CDORevision; +import org.eclipse.emf.cdo.server.IStoreAccessor; import org.eclipse.emf.cdo.server.IView; import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry; import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageUnit; @@ -47,7 +48,6 @@ import java.util.Set; */ public class HibernateRawCommitContext implements InternalCommitContext { - private Map idMappings = CDOIDUtil.createMap(); private List dirtyObjects = new ArrayList(); @@ -245,6 +245,11 @@ public class HibernateRawCommitContext implements InternalCommitContext this.newObjects = newObjects; } + public IStoreAccessor getAccessor() + { + return null; + } + public void preWrite() { } 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 a21da01059..bb485055dd 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 @@ -92,6 +92,7 @@ import org.eclipse.emf.cdo.spi.server.InternalSession; import org.eclipse.emf.cdo.spi.server.InternalSessionManager; import org.eclipse.emf.cdo.spi.server.InternalStore; import org.eclipse.emf.cdo.spi.server.InternalTransaction; +import org.eclipse.emf.cdo.spi.server.InternalUnitManager; import org.eclipse.emf.cdo.spi.server.InternalView; import org.eclipse.emf.internal.cdo.object.CDOFactoryImpl; @@ -200,12 +201,12 @@ public class Repository extends Container implements InternalRepository, private InternalLockManager lockingManager; + private InternalUnitManager unitManager; + private IQueryHandlerProvider queryHandlerProvider; private IManagedContainer container; - private final UnitManager unitManager = new UnitManager(this); - private final List readAccessHandlers = new ArrayList(); private final List writeAccessHandlers = new ArrayList(); @@ -972,11 +973,6 @@ public class Repository extends Container implements InternalRepository, return sessionManager; } - public UnitManager getUnitManager() - { - return unitManager; - } - /** * @since 2.0 */ @@ -986,6 +982,17 @@ public class Repository extends Container implements InternalRepository, this.sessionManager = sessionManager; } + public InternalUnitManager getUnitManager() + { + return unitManager; + } + + public void setUnitManager(InternalUnitManager unitManager) + { + checkInactive(); + this.unitManager = unitManager; + } + public InternalCDOBranchManager getBranchManager() { return branchManager; @@ -2221,6 +2228,11 @@ public class Repository extends Container implements InternalRepository, LifecycleUtil.activate(commitManager); LifecycleUtil.activate(queryHandlerProvider); + if (supportingUnits) + { + LifecycleUtil.activate(unitManager); + } + if (!skipInitialization) { long creationTime = store.getCreationTime(); @@ -2243,12 +2255,6 @@ public class Repository extends Container implements InternalRepository, } LifecycleUtil.activate(lockingManager); // Needs an initialized main branch / branch manager - - if (supportingUnits) - { - LifecycleUtil.activate(unitManager); - } - setPostActivateState(); } @@ -2322,6 +2328,11 @@ public class Repository extends Container implements InternalRepository, setLockingManager(createLockManager()); } + if (getUnitManager() == null) + { + setUnitManager(createUnitManager()); + } + super.doBeforeActivate(); } @@ -2360,6 +2371,11 @@ public class Repository extends Container implements InternalRepository, return new CommitManager(); } + protected InternalUnitManager createUnitManager() + { + return new UnitManager(this); + } + @Deprecated protected InternalLockManager createLockManager() { 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 009f70f55f..ccaafe45c7 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 @@ -1325,7 +1325,7 @@ public class TransactionCommitContext implements InternalCommitContext } } - protected IStoreAccessor getAccessor() + public IStoreAccessor getAccessor() { return accessor; } 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 index d22194f39b..cf107c59f6 100644 --- 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 @@ -11,21 +11,32 @@ package org.eclipse.emf.cdo.internal.server; 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.server.IRepository; +import org.eclipse.emf.cdo.common.revision.CDORevisionProvider; +import org.eclipse.emf.cdo.common.revision.CDORevisionUtil; 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.common.revision.InternalCDORevision; +import org.eclipse.emf.cdo.spi.server.InternalCommitContext; import org.eclipse.emf.cdo.spi.server.InternalRepository; +import org.eclipse.emf.cdo.spi.server.InternalUnitManager; import org.eclipse.net4j.util.container.Container; +import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Set; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock; import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; @@ -33,12 +44,16 @@ import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; /** * @author Eike Stepper */ -public final class UnitManager extends Container implements IUnitManager +public class UnitManager extends Container implements InternalUnitManager { private final InternalRepository repository; private final Map units = new HashMap(); + private final Map unitInitializers = new HashMap(); + + private final Set objectAttachers = new HashSet(); + private final ReentrantReadWriteLock managerLock = new ReentrantReadWriteLock(); public UnitManager(InternalRepository repository) @@ -46,18 +61,21 @@ public final class UnitManager extends Container implements IUnitManager this.repository = repository; } - public final IRepository getRepository() + public final InternalRepository getRepository() { return repository; } public boolean isUnit(CDOID rootID) { + checkActive(); + ReadLock readLock = managerLock.readLock(); readLock.lock(); try { + // No need to synchronize on units because all other modifiers hold the manager write lock. return units.containsKey(rootID); } finally @@ -68,48 +86,121 @@ public final class UnitManager extends Container implements IUnitManager public IUnit createUnit(CDOID rootID, IView view, CDORevisionHandler revisionHandler) { + checkActive(); + + int xxx; // TODO Check that units are not nested. + WriteLock writeLock = managerLock.writeLock(); + UnitInitializer unitInitializer; + boolean hook = false; + + //////////////////////////////////// + // Phase 1: Register (short, locked) + //////////////////////////////////// + writeLock.lock(); try { - Unit unit; + // No need to synchronize on units because all other access holds the manager lock. if (units.containsKey(rootID)) { return null; } - int xxx; // TODO Check that units are not nested. - - unit = new Unit(rootID); - units.put(rootID, unit); + // No need to synchronize on unitInitializers because all other access holds the manager lock. + unitInitializer = unitInitializers.get(rootID); + if (unitInitializer != null) + { + hook = true; + } + else + { + unitInitializer = new UnitInitializer(rootID, view, revisionHandler); - // Acquire unit write lock early here, release it in Unit.init() - unit.unitLock.writeLock().lock(); + // No need to synchronize on unitInitializers because all other access holds the manager lock. + unitInitializers.put(rootID, unitInitializer); + // Synchronize on objectAttachers because objectAttacherFinishedCommit() doesn't acquire the manager lock! + synchronized (objectAttachers) + { + for (ObjectAttacher objectAttacher : objectAttachers) + { + List ids = objectAttacher.removeUnmappedRevisionsFor(unitInitializer); + if (!ids.isEmpty()) + { + unitInitializer.addObjectAttacher(objectAttacher, ids); + } + } + } + } + } + finally + { writeLock.unlock(); - writeLock = null; + } - unit.init(view, revisionHandler); - fireElementAddedEvent(unit); - return unit; + if (hook) + { + return unitInitializer.hook(rootID, view, revisionHandler); + } + + IUnit unit = null; + + try + { + ///////////////////////////////////////////////////// + // Phase 2: Initialize (potentially long, not locked) + ///////////////////////////////////////////////////// + + unit = unitInitializer.initialize(); } finally { - if (writeLock != null) + /////////////////////////////////// + // Phase 3: Publish (short, locked) + /////////////////////////////////// + + try { - writeLock.unlock(); + writeLock.lock(); + + try + { + // No need to synchronize on unitInitializers because all other access holds the manager lock. + unitInitializers.remove(rootID); + + if (unit != null) + { + // No need to synchronize on units because all other access holds the manager lock. + units.put(rootID, unit); + } + } + finally + { + writeLock.unlock(); + } + } + finally + { + unitInitializer.notifyHookedInitializers(); } } + + fireElementAddedEvent(unit); + return unit; } public IUnit getUnit(CDOID rootID) { + checkActive(); + ReadLock readLock = managerLock.readLock(); readLock.lock(); try { + // No need to synchronize on units because all other modifiers hold the manager write lock. return units.get(rootID); } finally @@ -120,6 +211,7 @@ public final class UnitManager extends Container implements IUnitManager public IUnit[] getUnits() { + checkActive(); return getElements(); } @@ -130,6 +222,7 @@ public final class UnitManager extends Container implements IUnitManager try { + // No need to synchronize on units because all other modifiers hold the manager write lock. return units.values().toArray(new IUnit[units.size()]); } finally @@ -138,46 +231,146 @@ public final class UnitManager extends Container implements IUnitManager } } + public InternalObjectAttacher attachObjects(InternalCommitContext commitContext) + { + checkActive(); + + long timeStamp = commitContext.getTimeStamp(); + + ObjectAttacher objectAttacher; + Map unitMappings = new HashMap(); + + /////////////////////////////////////////////// + // Phase 1: Analyze new objects (short, locked) + /////////////////////////////////////////////// + + ReadLock readLock = managerLock.readLock(); + readLock.lock(); + + try + { + Set rootIDs = new HashSet(); + + // No need to synchronize on units because all other modifiers hold the manager write lock. + rootIDs.addAll(units.keySet()); + + // No need to synchronize on unitInitializers because all other modifiers hold the manager write lock. + rootIDs.addAll(unitInitializers.keySet()); + + List unmappedRevisions = new ArrayList(); + for (InternalCDORevision revision : commitContext.getNewObjects()) + { + CDOID rootID = getUnit(revision, commitContext, rootIDs); + if (rootID != null) + { + unitMappings.put(revision.getID(), rootID); + } + else + { + unmappedRevisions.add(revision); + } + } + + if (unmappedRevisions.isEmpty()) + { + return null; + } + + objectAttacher = new ObjectAttacher(commitContext, unmappedRevisions); + + // Read lock holders must synchronize modifications of the private collections. + synchronized (objectAttachers) + { + objectAttachers.add(objectAttacher); + } + } + finally + { + readLock.unlock(); + } + + ////////////////////////////////////////////////////////// + // Phase 2: Map objects to existing units (long, unlocked) + ////////////////////////////////////////////////////////// + + UnitSupport storeAccessor = (UnitSupport)commitContext.getAccessor(); + storeAccessor.writeUnits(unitMappings, timeStamp); // TODO Fork a monitor. + + return objectAttacher; + } + + /** + * Does not hold any manager lock when called. + */ + public void objectAttacherFinishedCommit(ObjectAttacher objectAttacher) + { + checkActive(); + + synchronized (objectAttachers) + { + objectAttachers.remove(objectAttacher); + } + } + @Override protected void doActivate() throws Exception { super.doActivate(); - UnitSupport unitSupport = (UnitSupport)repository.getStore().getReader(null); + UnitSupport storeAccessor = (UnitSupport)repository.getStore().getReader(null); try { - List roots = unitSupport.readUnitRoots(); + List roots = storeAccessor.readUnitRoots(); for (CDOID root : roots) { IUnit unit = new Unit(root); + + // No need to synchronize on units because all other access call checkActive() units.put(root, unit); } } finally { - unitSupport.release(); + storeAccessor.release(); } } @Override protected void doDeactivate() throws Exception { + // No need to synchronize on units because all other access call checkActive() units.clear(); + super.doDeactivate(); } + private static CDOID getUnit(InternalCDORevision revision, CDORevisionProvider revisionProvider, Set rootIDs) + { + CDOID id = revision.getID(); + if (rootIDs.contains(id)) + { + return id; + } + + CDORevision parentRevision = CDORevisionUtil.getParentRevision(revision, revisionProvider); + if (parentRevision != null) + { + return getUnit((InternalCDORevision)parentRevision, revisionProvider, rootIDs); + } + + return null; + } + /** * @author Eike Stepper */ - public final class Unit implements IUnit + private final class Unit implements IUnit { private final CDOID rootID; private final Set views = new HashSet(); - private final ReentrantReadWriteLock unitLock = new ReentrantReadWriteLock(); - public Unit(CDOID rootID) { this.rootID = rootID; @@ -193,90 +386,272 @@ public final class UnitManager extends Container implements IUnitManager return rootID; } - public void init(IView view, CDORevisionHandler revisionHandler) + public boolean isOpen() { - // Write lock has been acquired by UnitManager.createUnit() + synchronized (views) + { + return !views.isEmpty(); + } + } - try + public void open(IView view, final CDORevisionHandler revisionHandler) + { + synchronized (views) { - UnitSupport unitSupport = (UnitSupport)repository.getStore().getWriter(null); + views.add(view); + } - try - { - unitSupport.initUnit(view, rootID, revisionHandler); - } - finally - { - unitSupport.release(); - } + UnitSupport storeAccessor = (UnitSupport)repository.getStore().getReader(null); + + try + { + storeAccessor.readUnit(view, rootID, revisionHandler); } finally { - // Write lock has been acquired by UnitManager.createUnit() - unitLock.writeLock().unlock(); + storeAccessor.release(); } } - public boolean isOpen() + public void close(IView view) { - ReadLock readLock = unitLock.readLock(); - readLock.lock(); + synchronized (views) + { + views.remove(view); + } + } + + @Override + public String toString() + { + return "Unit[" + rootID + "]"; + } + + /** + * Does not hold any manager lock when called. + */ + public void initialize(IView view, long timeStamp, CDORevisionHandler revisionHandler, + Map> objectAttachers) + { + UnitSupport storeAccessor = (UnitSupport)repository.getStore().getWriter(null); try { - return !views.isEmpty(); + Object initResult = storeAccessor.initUnit(view, rootID, revisionHandler, timeStamp); + + List ids = new ArrayList(); + for (Entry> entry : objectAttachers.entrySet()) + { + ObjectAttacher objectAttacher = entry.getKey(); + if (objectAttacher.awaitFinishedCommit()) + { + ids.addAll(entry.getValue()); + } + } + + storeAccessor.finishUnit(view, rootID, revisionHandler, timeStamp, initResult, ids); } finally { - readLock.unlock(); + storeAccessor.release(); } } + } - public void open(IView view, final CDORevisionHandler revisionHandler) + /** + * @author Eike Stepper + */ + private final class UnitInitializer implements CDORevisionHandler + { + private final long timeStamp = repository.getTimeStamp(); + + private final Map> concurrentObjectAttachers = new HashMap>(); + + private final CountDownLatch unitInitialized = new CountDownLatch(1); + + private final CDOID rootID; + + private final IView view; + + private final CDORevisionHandler revisionHandler; + + private final List hookedRevisionHandlers = new CopyOnWriteArrayList(); + + private volatile boolean hasHookedRevisionHandlers; + + private Unit unit; + + public UnitInitializer(CDOID rootID, IView view, CDORevisionHandler revisionHandler) { - ReadLock readLock = unitLock.readLock(); - readLock.lock(); + this.rootID = rootID; + this.view = view; + this.revisionHandler = revisionHandler; + } - try + public CDOID getRootID() + { + return rootID; + } + + /** + * Does not hold any manager lock when called. + */ + public IUnit initialize() + { + unit = new Unit(rootID); + unit.initialize(view, timeStamp, revisionHandler, concurrentObjectAttachers); + return unit; + } + + /** + * Does not hold any manager lock when called. + */ + public IUnit hook(CDOID rootID, IView view, final CDORevisionHandler revisionHandler) + { + final Set ids = new HashSet(); + + hookedRevisionHandlers.add(new CDORevisionHandler() { - views.add(view); + public boolean handleRevision(CDORevision revision) + { + ids.add(revision.getID()); + return revisionHandler.handleRevision(revision); + } + }); - UnitSupport unitSupport = (UnitSupport)repository.getStore().getReader(null); + // It's okay to do this unsynchronized. The worst thing that could happen is that the hooked revision handler is + // missed a few times during UnitInitializer.handleRevision(), but that's okay because it probably missed many + // revisions already and therefore performs an openUnit() subsequently, anyways. After all, hooked revision + // handlers, + // i.e., concurrent createUnit() calls for the same unit, are extremely rare. + hasHookedRevisionHandlers = true; - try + try + { + // Now wait for the main revision handler to finish. + unitInitialized.await(); + } + catch (InterruptedException ex) + { + return null; + } + + // Now send the missed revisions. + unit.open(view, new CDORevisionHandler() + { + public boolean handleRevision(CDORevision revision) { - unitSupport.readUnit(view, rootID, revisionHandler); + if (ids.contains(revision.getID())) + { + // This revision has already been sent. Skip to the next one. + return true; + } + + return revisionHandler.handleRevision(revision); } - finally + }); + + return unit; + } + + /** + * Does not hold any manager lock when called. + */ + public void notifyHookedInitializers() + { + unitInitialized.countDown(); + } + + public boolean handleRevision(CDORevision revision) + { + if (revisionHandler.handleRevision(revision)) + { + if (hasHookedRevisionHandlers) { - unitSupport.release(); + for (CDORevisionHandler hookedRevisionHandler : hookedRevisionHandlers) + { + hookedRevisionHandler.handleRevision(revision); + } } + + return true; } - finally + + return false; + } + + /** + * Holds the manager write lock when called. + */ + public void addObjectAttacher(ObjectAttacher objectAttacher, List ids) + { + concurrentObjectAttachers.put(objectAttacher, ids); + } + } + + /** + * @author Eike Stepper + */ + private final class ObjectAttacher implements InternalObjectAttacher + { + private final InternalCommitContext commitContext; + + private final List unmappedRevisions; + + private final CountDownLatch commitFinished = new CountDownLatch(1); + + private boolean commitSucceeded; + + public ObjectAttacher(InternalCommitContext commitContext, List unmappedRevisions) + { + this.commitContext = commitContext; + this.unmappedRevisions = unmappedRevisions; + } + + /** + * Does not hold any manager lock when called. + */ + public void finishedCommit(boolean success) + { + objectAttacherFinishedCommit(this); + + commitSucceeded = success; + commitFinished.countDown(); + } + + /** + * Holds the manager write lock when called. + */ + public List removeUnmappedRevisionsFor(UnitInitializer unitInitializer) + { + List ids = new ArrayList(); + + Set rootIDs = Collections.singleton(unitInitializer.getRootID()); + for (Iterator it = unmappedRevisions.iterator(); it.hasNext();) { - readLock.unlock(); + InternalCDORevision revision = it.next(); + if (getUnit(revision, commitContext, rootIDs) != null) + { + ids.add(revision.getID()); + it.remove(); + } } + + return ids; } - public void close(IView view) + public boolean awaitFinishedCommit() { - ReadLock readLock = unitLock.readLock(); - readLock.lock(); - try { - views.remove(view); + commitFinished.await(); } - finally + catch (InterruptedException ex) { - readLock.unlock(); + return false; } - } - @Override - public String toString() - { - return "Unit[" + rootID + "]"; + return commitSucceeded; } } } 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 2255128941..e64dfb509b 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 @@ -810,8 +810,13 @@ public interface IStoreAccessor extends IQueryHandlerProvider, BranchLoader, Com { public List readUnitRoots(); - public void initUnit(IView view, CDOID rootID, CDORevisionHandler revisionHandler); - public void readUnit(IView view, CDOID rootID, CDORevisionHandler revisionHandler); + + public Object initUnit(IView view, CDOID rootID, CDORevisionHandler revisionHandler, long timeStamp); + + public void finishUnit(IView view, CDOID rootID, CDORevisionHandler revisionHandler, long timeStamp, + Object initResult, List ids); + + public void writeUnits(Map unitMappings, long timeStamp); } } diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalCommitContext.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalCommitContext.java index d304a713df..f911de3243 100644 --- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalCommitContext.java +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalCommitContext.java @@ -66,6 +66,11 @@ public interface InternalCommitContext extends IStoreAccessor.CommitContext, CDO public InternalTransaction getTransaction(); + /** + * @since 4.5 + */ + public IStoreAccessor getAccessor(); + /** * @since 4.2 */ 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 6b60df51a4..d59d24bb48 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 @@ -116,6 +116,11 @@ public interface InternalRepository extends IRepository, PackageProcessor, Packa */ public InternalLockManager getLockingManager(); + /** + * @since 4.5 + */ + public InternalUnitManager getUnitManager(); + public InternalQueryManager getQueryManager(); public void setQueryHandlerProvider(IQueryHandlerProvider queryHandlerProvider); diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalUnitManager.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalUnitManager.java new file mode 100644 index 0000000000..731ffbfc01 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalUnitManager.java @@ -0,0 +1,34 @@ +/* + * 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.spi.server; + +import org.eclipse.emf.cdo.server.IUnitManager; + +/** + * @author Eike Stepper + * @since 4.5 + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. +*/ +public interface InternalUnitManager extends IUnitManager +{ + public InternalRepository getRepository(); + + public InternalObjectAttacher attachObjects(InternalCommitContext commitContext); + + /** + * @author Eike Stepper + */ + public interface InternalObjectAttacher + { + public void finishedCommit(boolean success); + } +} 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 c570d5a32c..c054b27bc6 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 @@ -97,7 +97,7 @@ public abstract class StoreAccessor extends StoreAccessorBase if (newObjects.length != 0) { - writeRevisions(newObjects, branch, monitor.fork(newObjects.length)); + writeNewObjectRevisions(context, newObjects, branch, monitor.fork(newObjects.length)); } if (dirtyCount != 0) @@ -108,7 +108,7 @@ public abstract class StoreAccessor extends StoreAccessorBase } else { - writeRevisions(dirtyObjects, branch, monitor.fork(dirtyCount)); + writeDirtyObjectRevisions(context, dirtyObjects, branch, monitor.fork(dirtyCount)); } } @@ -168,6 +168,24 @@ public abstract class StoreAccessor extends StoreAccessorBase protected abstract void writeCommitInfo(CDOBranch branch, long timeStamp, long previousTimeStamp, String userID, String comment, OMMonitor monitor); + /** + * @since 4.5 + */ + protected void writeNewObjectRevisions(InternalCommitContext context, InternalCDORevision[] newObjects, + CDOBranch branch, OMMonitor monitor) + { + writeRevisions(newObjects, branch, monitor); + } + + /** + * @since 4.5 + */ + protected void writeDirtyObjectRevisions(InternalCommitContext context, InternalCDORevision[] dirtyObjects, + CDOBranch branch, OMMonitor monitor) + { + writeRevisions(dirtyObjects, branch, monitor); + } + /** * @since 3.0 */ 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 af1783cc04..419531a15d 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 @@ -117,7 +117,6 @@ public class AllConfigs extends ConfigTestSuite testClasses.add(BackupTest.class); testClasses.add(ResourceModificationTrackingTest.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.net4j.db.mysql/META-INF/MANIFEST.MF b/plugins/org.eclipse.net4j.db.mysql/META-INF/MANIFEST.MF index 282416a59f..bb9bcb9331 100644 --- a/plugins/org.eclipse.net4j.db.mysql/META-INF/MANIFEST.MF +++ b/plugins/org.eclipse.net4j.db.mysql/META-INF/MANIFEST.MF @@ -1,7 +1,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-SymbolicName: org.eclipse.net4j.db.mysql;singleton:=true -Bundle-Version: 4.2.200.qualifier +Bundle-Version: 4.2.300.qualifier Bundle-Name: %pluginName Bundle-Vendor: %providerName Bundle-Localization: plugin @@ -13,6 +13,6 @@ Require-Bundle: org.eclipse.net4j.db;bundle-version="[4.0.0,5.0.0)";visibility:= Import-Package: com.mysql.jdbc;version="[5.0.0,6.0.0)";resolution:=optional;x-installation:=greedy, com.mysql.jdbc.jdbc2.optional;version="[5.0.0,6.0.0)";resolution:=optional;x-installation:=greedy, org.osgi.framework;version="[1.0.0,2.0.0)" -Export-Package: org.eclipse.net4j.db.internal.mysql.bundle;version="4.2.200";x-internal:=true, - org.eclipse.net4j.db.mysql;version="4.2.200" +Export-Package: org.eclipse.net4j.db.internal.mysql.bundle;version="4.2.300";x-internal:=true, + org.eclipse.net4j.db.mysql;version="4.2.300" Eclipse-RegisterBuddy: org.eclipse.net4j.db diff --git a/plugins/org.eclipse.net4j.db.mysql/src/org/eclipse/net4j/db/mysql/MYSQLAdapter.java b/plugins/org.eclipse.net4j.db.mysql/src/org/eclipse/net4j/db/mysql/MYSQLAdapter.java index 87469593c4..87f9d0cf15 100644 --- a/plugins/org.eclipse.net4j.db.mysql/src/org/eclipse/net4j/db/mysql/MYSQLAdapter.java +++ b/plugins/org.eclipse.net4j.db.mysql/src/org/eclipse/net4j/db/mysql/MYSQLAdapter.java @@ -16,6 +16,9 @@ import org.eclipse.net4j.db.ddl.IDBField; import org.eclipse.net4j.db.ddl.IDBIndex; import org.eclipse.net4j.spi.db.DBAdapter; +import com.mysql.jdbc.ConnectionProperties; + +import java.sql.Connection; import java.sql.SQLException; /** @@ -32,39 +35,39 @@ public class MYSQLAdapter extends DBAdapter private static final String[] RESERVED_WORDS = { "ACCESSIBLE", "ACTION", "ADD", "ALL", "ALTER", "ANALYZE", "AND", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ "AS", //$NON-NLS-1$ - "ASC", "ASENSITIVE", "BEFORE", "BETWEEN", "BIGINT", "BINARY", "BIT", "BLOB", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ - "BOTH", "BY", "CALL", "CASCADE", "CASE", "CHANGE", "CHAR", "CHARACTER", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ - "CHECK", "COLLATE", "COLUMN", "COLUMNS", "CONDITION", "CONNECTION", "CONSTRAINT", "CONTINUE", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ - "CONVERT", "CREATE", "CROSS", "CURRENT_DATE", "CURRENT_TIME", "CURRENT_TIMESTAMP", "CURRENT_USER", "CURSOR", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ - "DATABASE", "DATABASES", "DATE", "DAY_HOUR", "DAY_MICROSECOND", "DAY_MINUTE", "DAY_SECOND", "DEC", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ - "DECIMAL", "DECLARE", "DEFAULT", "DELAYED", "DELETE", "DESC", "DESCRIBE", "DETERMINISTIC", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ - "DISTINCT", "DISTINCTROW", "DIV", "DOUBLE", "DROP", "DUAL", "EACH", "ELSE", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ - "ELSEIF", "ENCLOSED", "ENUM", "ESCAPED", "EXISTS", "EXIT", "EXPLAIN", "FALSE", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ - "FETCH", "FIELDS", "FLOAT", "FLOAT4", "FLOAT8", "FOR", "FORCE", "FOREIGN", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ - "FROM", "FULLTEXT", "GENERAL", "GOTO", "GRANT", "GROUP", "HAVING", "HIGH_PRIORITY", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ - "HOUR_MICROSECOND", "HOUR_MINUTE", "HOUR_SECOND", "IF", "IGNORE", "IGNORE_SERVER_IDS", "IN", "INDEX", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ - "INFILE", "INNER", "INOUT", "INSENSITIVE", "INSERT", "INT", "INT1", "INT2", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ - "INT3", "INT4", "INT8", "INTEGER", "INTERVAL", "INTO", "IS", "ITERATE", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ - "JOIN", "KEY", "KEYS", "KILL", "LABEL", "LEADING", "LEAVE", "LEFT", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ - "LIKE", "LIMIT", "LINEAR", "LINES", "LOAD", "LOCALTIME", "LOCALTIMESTAMP", "LOCK", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ - "LONG", "LONGBLOB", "LONGTEXT", "LOOP", "LOW_PRIORITY", "MASTER_HEARTBEAT_PERIOD", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ + "ASC", "ASENSITIVE", "BEFORE", "BETWEEN", "BIGINT", "BINARY", "BIT", "BLOB", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ + "BOTH", "BY", "CALL", "CASCADE", "CASE", "CHANGE", "CHAR", "CHARACTER", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ + "CHECK", "COLLATE", "COLUMN", "COLUMNS", "CONDITION", "CONNECTION", "CONSTRAINT", "CONTINUE", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ + "CONVERT", "CREATE", "CROSS", "CURRENT_DATE", "CURRENT_TIME", "CURRENT_TIMESTAMP", "CURRENT_USER", "CURSOR", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ + "DATABASE", "DATABASES", "DATE", "DAY_HOUR", "DAY_MICROSECOND", "DAY_MINUTE", "DAY_SECOND", "DEC", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ + "DECIMAL", "DECLARE", "DEFAULT", "DELAYED", "DELETE", "DESC", "DESCRIBE", "DETERMINISTIC", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ + "DISTINCT", "DISTINCTROW", "DIV", "DOUBLE", "DROP", "DUAL", "EACH", "ELSE", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ + "ELSEIF", "ENCLOSED", "ENUM", "ESCAPED", "EXISTS", "EXIT", "EXPLAIN", "FALSE", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ + "FETCH", "FIELDS", "FLOAT", "FLOAT4", "FLOAT8", "FOR", "FORCE", "FOREIGN", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ + "FROM", "FULLTEXT", "GENERAL", "GOTO", "GRANT", "GROUP", "HAVING", "HIGH_PRIORITY", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ + "HOUR_MICROSECOND", "HOUR_MINUTE", "HOUR_SECOND", "IF", "IGNORE", "IGNORE_SERVER_IDS", "IN", "INDEX", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ + "INFILE", "INNER", "INOUT", "INSENSITIVE", "INSERT", "INT", "INT1", "INT2", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ + "INT3", "INT4", "INT8", "INTEGER", "INTERVAL", "INTO", "IS", "ITERATE", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ + "JOIN", "KEY", "KEYS", "KILL", "LABEL", "LEADING", "LEAVE", "LEFT", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ + "LIKE", "LIMIT", "LINEAR", "LINES", "LOAD", "LOCALTIME", "LOCALTIMESTAMP", "LOCK", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ + "LONG", "LONGBLOB", "LONGTEXT", "LOOP", "LOW_PRIORITY", "MASTER_HEARTBEAT_PERIOD", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ "MASTER_SSL_VERIFY_SERVER_CERT", "MATCH", //$NON-NLS-1$ //$NON-NLS-2$ - "MAXVALUE", "MEDIUMBLOB", "MEDIUMINT", "MEDIUMTEXT", "MIDDLEINT", "MINUTE_MICROSECOND", "MINUTE_SECOND", "MOD", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ - "MODIFIES", "NATURAL", "NO", "NOT", "NO_WRITE_TO_BINLOG", "NULL", "NUMERIC", "ON", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ - "OPTIMIZE", "OPTION", "OPTIONALLY", "OR", "ORDER", "OUT", "OUTER", "OUTFILE", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ - "PRECISION", "PRIMARY", "PRIVILEGES", "PROCEDURE", "PURGE", "RAID0", "RANGE", "READ", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ - "READS", "READ_WRITE", "REAL", "REFERENCES", "REGEXP", "RELEASE", "RENAME", "REPEAT", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ - "REPLACE", "REQUIRE", "RESIGNAL", "RESTRICT", "RETURN", "REVOKE", "RIGHT", "RLIKE", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ - "SCHEMA", "SCHEMAS", "SECOND_MICROSECOND", "SELECT", "SENSITIVE", "SEPARATOR", "SET", "SHOW", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ - "SIGNAL", "SLOW", "SMALLINT", "SONAME", "SPATIAL", "SPECIFIC", "SQL", "SQL_BIG_RESULT", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ - "SQL_CALC_FOUND_ROWS", "SQLEXCEPTION", "SQL_SMALL_RESULT", "SQLSTATE", "SQLWARNING", "SSL", "STARTING", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ + "MAXVALUE", "MEDIUMBLOB", "MEDIUMINT", "MEDIUMTEXT", "MIDDLEINT", "MINUTE_MICROSECOND", "MINUTE_SECOND", "MOD", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ + "MODIFIES", "NATURAL", "NO", "NOT", "NO_WRITE_TO_BINLOG", "NULL", "NUMERIC", "ON", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ + "OPTIMIZE", "OPTION", "OPTIONALLY", "OR", "ORDER", "OUT", "OUTER", "OUTFILE", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ + "PRECISION", "PRIMARY", "PRIVILEGES", "PROCEDURE", "PURGE", "RAID0", "RANGE", "READ", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ + "READS", "READ_WRITE", "REAL", "REFERENCES", "REGEXP", "RELEASE", "RENAME", "REPEAT", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ + "REPLACE", "REQUIRE", "RESIGNAL", "RESTRICT", "RETURN", "REVOKE", "RIGHT", "RLIKE", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ + "SCHEMA", "SCHEMAS", "SECOND_MICROSECOND", "SELECT", "SENSITIVE", "SEPARATOR", "SET", "SHOW", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ + "SIGNAL", "SLOW", "SMALLINT", "SONAME", "SPATIAL", "SPECIFIC", "SQL", "SQL_BIG_RESULT", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ + "SQL_CALC_FOUND_ROWS", "SQLEXCEPTION", "SQL_SMALL_RESULT", "SQLSTATE", "SQLWARNING", "SSL", "STARTING", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ "STRAIGHT_JOIN", //$NON-NLS-1$ - "TABLE", "TABLES", "TERMINATED", "TEXT", "THEN", "TIME", "TIMESTAMP", "TINYBLOB", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ - "TINYINT", "TINYTEXT", "TO", "TRAILING", "TRIGGER", "TRUE", "UNDO", "UNION", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ - "UNIQUE", "UNLOCK", "UNSIGNED", "UPDATE", "UPGRADE", "USAGE", "USE", "USING", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ - "UTC_DATE", "UTC_TIME", "UTC_TIMESTAMP", "VALUES", "VARBINARY", "VARCHAR", "VARCHARACTER", "VARYING", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ - "WHEN", "WHERE", "WHILE", "WITH", "WRITE", "X509", "XOR", "YEAR_MONTH", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ - "ZEROFILL" }; //$NON-NLS-1$ + "TABLE", "TABLES", "TERMINATED", "TEXT", "THEN", "TIME", "TIMESTAMP", "TINYBLOB", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ + "TINYINT", "TINYTEXT", "TO", "TRAILING", "TRIGGER", "TRUE", "UNDO", "UNION", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ + "UNIQUE", "UNLOCK", "UNSIGNED", "UPDATE", "UPGRADE", "USAGE", "USE", "USING", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ + "UTC_DATE", "UTC_TIME", "UTC_TIMESTAMP", "VALUES", "VARBINARY", "VARCHAR", "VARCHARACTER", "VARYING", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ + "WHEN", "WHERE", "WHILE", "WITH", "WRITE", "X509", "XOR", "YEAR_MONTH", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ + "ZEROFILL" }; //$NON-NLS-1$ public MYSQLAdapter() { @@ -161,4 +164,16 @@ public class MYSQLAdapter extends DBAdapter { return "ALTER TABLE " + tableName + " MODIFY " + fieldName + " " + definition; } + + @Override + public Connection modifyConnection(Connection connection) + { + if (connection instanceof ConnectionProperties) + { + ConnectionProperties connectionProperties = (ConnectionProperties)connection; + connectionProperties.setUseLocalSessionState(true); + } + + return super.modifyConnection(connection); + } } diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/IDBAdapter.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/IDBAdapter.java index a4fe9b7dfa..571f676f1c 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/IDBAdapter.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/IDBAdapter.java @@ -59,6 +59,11 @@ public interface IDBAdapter */ public IDBConnectionProvider createConnectionProvider(DataSource dataSource); + /** + * @since 4.5 + */ + public Connection modifyConnection(Connection connection); + /** * @since 4.2 */ diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBDatabase.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBDatabase.java index da9434e860..72665bb84c 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBDatabase.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBDatabase.java @@ -33,7 +33,7 @@ import java.util.LinkedList; /** * @author Eike Stepper */ -public final class DBDatabase extends SetContainerimplements IDBDatabase +public final class DBDatabase extends SetContainer implements IDBDatabase { private DBAdapter adapter; @@ -142,6 +142,8 @@ public final class DBDatabase extends SetContainerimplements IDBD throw new DBException("No connection from connection provider: " + connectionProvider); } + delegate = adapter.modifyConnection(delegate); + DBConnection connection = new DBConnection(this, delegate); addElement(connection); return connection; diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/spi/db/DBAdapter.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/spi/db/DBAdapter.java index fbd52b6c73..c50be818e5 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/spi/db/DBAdapter.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/spi/db/DBAdapter.java @@ -143,6 +143,14 @@ public abstract class DBAdapter implements IDBAdapter return DBUtil.createConnectionProvider(dataSource); } + /** + * @since 4.5 + */ + public Connection modifyConnection(Connection connection) + { + return connection; + } + /** * @since 4.2 */ diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/buffer/BufferInputStream.java b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/buffer/BufferInputStream.java index 52ab739f85..ca3e4b6f74 100644 --- a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/buffer/BufferInputStream.java +++ b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/buffer/BufferInputStream.java @@ -40,6 +40,9 @@ public class BufferInputStream extends InputStream implements IBufferHandler public static final long DEFAULT_MILLIS_INTERRUPT_CHECK = 100; + private static final boolean DISABLE_TIMEOUT = Boolean + .getBoolean("org.eclipse.net4j.buffer.BufferInputStream.disableTimeout"); + private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG_BUFFER_STREAM, BufferInputStream.class); private final boolean tracerEnabled; @@ -205,7 +208,7 @@ public class BufferInputStream extends InputStream implements IBufferHandler } long timeout; - if (noTimeout) + if (noTimeout || DISABLE_TIMEOUT) { timeout = check; } @@ -240,6 +243,11 @@ public class BufferInputStream extends InputStream implements IBufferHandler private long computeTimeout(final long check) throws IOTimeoutException { + if (DISABLE_TIMEOUT) + { + return Integer.MAX_VALUE; + } + long remaining; synchronized (this) { -- cgit v1.2.3