diff options
46 files changed, 895 insertions, 548 deletions
diff --git a/features/org.eclipse.emf.cdo.server.db-feature/feature.xml b/features/org.eclipse.emf.cdo.server.db-feature/feature.xml index ceecb79463..a410324f66 100644 --- a/features/org.eclipse.emf.cdo.server.db-feature/feature.xml +++ b/features/org.eclipse.emf.cdo.server.db-feature/feature.xml @@ -12,7 +12,7 @@ <feature id="org.eclipse.emf.cdo.server.db" label="%featureName" - version="4.5.100.qualifier" + version="4.6.0.qualifier" provider-name="%providerName" license-feature="org.eclipse.emf.cdo.license" license-feature-version="0.0.0"> diff --git a/features/org.eclipse.emf.cdo.server.db-feature/pom.xml b/features/org.eclipse.emf.cdo.server.db-feature/pom.xml index dd4ede5429..10a59e8c12 100644 --- a/features/org.eclipse.emf.cdo.server.db-feature/pom.xml +++ b/features/org.eclipse.emf.cdo.server.db-feature/pom.xml @@ -25,7 +25,7 @@ <groupId>org.eclipse.emf.cdo.features</groupId> <artifactId>org.eclipse.emf.cdo.server.db</artifactId> - <version>4.5.100-SNAPSHOT</version> + <version>4.6.0-SNAPSHOT</version> <packaging>eclipse-feature</packaging> </project> diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/model/CDOModelUtil.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/model/CDOModelUtil.java index 848d8c2586..da7536b02b 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/model/CDOModelUtil.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/model/CDOModelUtil.java @@ -258,6 +258,14 @@ public final class CDOModelUtil implements CDOModelConstants } /** + * @since 4.7 + */ + public static boolean isSystemPackageURI(String nsURI) + { + return CORE_PACKAGE_URI.equals(nsURI) || RESOURCE_PACKAGE_URI.equals(nsURI) || TYPES_PACKAGE_URI.equals(nsURI); + } + + /** * @since 4.0 */ public static boolean isLob(EClassifier eClassifier) diff --git a/plugins/org.eclipse.emf.cdo.examples.installer/examples/org.eclipse.emf.cdo.examples.master/config/cdo-server.xml b/plugins/org.eclipse.emf.cdo.examples.installer/examples/org.eclipse.emf.cdo.examples.master/config/cdo-server.xml index 4f9f109c36..1017a5871c 100644 --- a/plugins/org.eclipse.emf.cdo.examples.installer/examples/org.eclipse.emf.cdo.examples.master/config/cdo-server.xml +++ b/plugins/org.eclipse.emf.cdo.examples.installer/examples/org.eclipse.emf.cdo.examples.master/config/cdo-server.xml @@ -61,6 +61,7 @@ <mappingStrategy type="horizontal"> <!-- callout --> <property name="qualifiedNames" value="true"/> <property name="withRanges" value="false"/> + <property name="eagerTableCreation" value="false"/> <!-- Per default, the objectTypeCache is in-memory and contains diff --git a/plugins/org.eclipse.emf.cdo.examples.master/config/cdo-server.xml b/plugins/org.eclipse.emf.cdo.examples.master/config/cdo-server.xml index 4f9f109c36..1017a5871c 100644 --- a/plugins/org.eclipse.emf.cdo.examples.master/config/cdo-server.xml +++ b/plugins/org.eclipse.emf.cdo.examples.master/config/cdo-server.xml @@ -61,6 +61,7 @@ <mappingStrategy type="horizontal"> <!-- callout --> <property name="qualifiedNames" value="true"/> <property name="withRanges" value="false"/> + <property name="eagerTableCreation" value="false"/> <!-- Per default, the objectTypeCache is in-memory and contains diff --git a/plugins/org.eclipse.emf.cdo.server.db/.options b/plugins/org.eclipse.emf.cdo.server.db/.options index 2654631df9..41c094ccae 100644 --- a/plugins/org.eclipse.emf.cdo.server.db/.options +++ b/plugins/org.eclipse.emf.cdo.server.db/.options @@ -2,4 +2,3 @@ org.eclipse.emf.cdo.server.db/debug = true org.eclipse.emf.cdo.server.db/debug.units = true -org.eclipse.emf.cdo.server.db/debug.units.perf = false diff --git a/plugins/org.eclipse.emf.cdo.server.db/META-INF/MANIFEST.MF b/plugins/org.eclipse.emf.cdo.server.db/META-INF/MANIFEST.MF index f607a3111a..c647e64286 100644 --- a/plugins/org.eclipse.emf.cdo.server.db/META-INF/MANIFEST.MF +++ b/plugins/org.eclipse.emf.cdo.server.db/META-INF/MANIFEST.MF @@ -1,7 +1,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-SymbolicName: org.eclipse.emf.cdo.server.db;singleton:=true -Bundle-Version: 4.5.100.qualifier +Bundle-Version: 4.6.0.qualifier Bundle-Name: %pluginName Bundle-Vendor: %providerName Bundle-Localization: plugin @@ -12,11 +12,11 @@ Bundle-ClassPath: . Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.5.0,4.0.0)", org.eclipse.net4j.db;bundle-version="[4.0.0,5.0.0)";visibility:=reexport, org.eclipse.emf.cdo.server;bundle-version="[4.0.0,5.0.0)";visibility:=reexport -Export-Package: org.eclipse.emf.cdo.server.db;version="4.5.100", - org.eclipse.emf.cdo.server.db.mapping;version="4.5.100", - org.eclipse.emf.cdo.server.internal.db;version="4.5.100";x-friends:="org.eclipse.emf.cdo.tests,org.eclipse.emf.cdo.tests.db,org.eclipse.emf.cdo.explorer.ui", - org.eclipse.emf.cdo.server.internal.db.bundle;version="4.5.100";x-internal:=true, - org.eclipse.emf.cdo.server.internal.db.mapping;version="4.5.100";x-friends:="org.eclipse.emf.cdo.tests,org.eclipse.emf.cdo.tests.db", - org.eclipse.emf.cdo.server.internal.db.mapping.horizontal;version="4.5.100";x-friends:="org.eclipse.emf.cdo.tests,org.eclipse.emf.cdo.tests.db", - org.eclipse.emf.cdo.server.internal.db.messages;version="4.5.100";x-internal:=true +Export-Package: org.eclipse.emf.cdo.server.db;version="4.6.0", + org.eclipse.emf.cdo.server.db.mapping;version="4.6.0", + org.eclipse.emf.cdo.server.internal.db;version="4.6.0";x-friends:="org.eclipse.emf.cdo.tests,org.eclipse.emf.cdo.tests.db,org.eclipse.emf.cdo.explorer.ui", + org.eclipse.emf.cdo.server.internal.db.bundle;version="4.6.0";x-internal:=true, + org.eclipse.emf.cdo.server.internal.db.mapping;version="4.6.0";x-friends:="org.eclipse.emf.cdo.tests,org.eclipse.emf.cdo.tests.db", + org.eclipse.emf.cdo.server.internal.db.mapping.horizontal;version="4.6.0";x-friends:="org.eclipse.emf.cdo.tests,org.eclipse.emf.cdo.tests.db", + org.eclipse.emf.cdo.server.internal.db.messages;version="4.6.0";x-internal:=true Automatic-Module-Name: org.eclipse.emf.cdo.server.db diff --git a/plugins/org.eclipse.emf.cdo.server.db/pom.xml b/plugins/org.eclipse.emf.cdo.server.db/pom.xml index 392db663a2..507a6822e1 100644 --- a/plugins/org.eclipse.emf.cdo.server.db/pom.xml +++ b/plugins/org.eclipse.emf.cdo.server.db/pom.xml @@ -25,7 +25,7 @@ <groupId>org.eclipse.emf.cdo</groupId> <artifactId>org.eclipse.emf.cdo.server.db</artifactId> - <version>4.5.100-SNAPSHOT</version> + <version>4.6.0-SNAPSHOT</version> <packaging>eclipse-plugin</packaging> </project> 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 3f158fccab..5ea040bfd9 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 @@ -15,6 +15,7 @@ import org.eclipse.emf.cdo.server.IStoreAccessor; import org.eclipse.emf.cdo.server.IStoreAccessor.UnitSupport; import org.eclipse.net4j.db.IDBConnection; +import org.eclipse.net4j.db.ddl.IDBTable; import org.eclipse.emf.ecore.EClass; @@ -49,4 +50,9 @@ public interface IDBStoreAccessor extends IStoreAccessor.Raw2, UnitSupport */ @Deprecated public IPreparedStatementCache getStatementCache(); + + /** + * @since 4.6 + */ + public void tableCreated(IDBTable table); } diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/IMappingStrategy.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/IMappingStrategy.java index 111a561b05..9e96dbfc52 100644 --- a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/IMappingStrategy.java +++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/IMappingStrategy.java @@ -33,6 +33,7 @@ import org.eclipse.net4j.util.om.monitor.OMMonitor; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.ENamedElement; +import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.EStructuralFeature; import java.io.IOException; @@ -431,5 +432,12 @@ public interface IMappingStrategy * Name of a String property that specifies the name of a {@link ColumnTypeModifier column type modifier}. */ public static final String COLUMN_TYPE_MODIFIER = "columnTypeModifier"; //$NON-NLS-1$ + + /** + * Name of a boolean property that configures whether all tables for a {@link EPackage package} are created eagerly. + * + * @since 4.6 + */ + public static final String EAGER_TABLE_CREATION = "eagerTableCreation"; //$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 01d50f44b3..2dc3271642 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 @@ -72,8 +72,11 @@ import org.eclipse.net4j.db.BatchedStatement; import org.eclipse.net4j.db.DBException; import org.eclipse.net4j.db.DBUtil; import org.eclipse.net4j.db.IDBConnection; +import org.eclipse.net4j.db.IDBDatabase; import org.eclipse.net4j.db.IDBPreparedStatement; import org.eclipse.net4j.db.IDBPreparedStatement.ReuseProbability; +import org.eclipse.net4j.db.IDBSchemaTransaction; +import org.eclipse.net4j.db.ddl.IDBTable; import org.eclipse.net4j.internal.db.ddl.DBField; import org.eclipse.net4j.util.HexUtil; import org.eclipse.net4j.util.ObjectUtil; @@ -126,6 +129,8 @@ public class DBStoreAccessor extends StoreAccessor implements IDBStoreAccessor, private InternalObjectAttacher objectAttacher; + private List<IDBTable> createdTables; + public DBStoreAccessor(DBStore store, ISession session) throws DBException { super(store, session); @@ -786,7 +791,9 @@ public class DBStoreAccessor extends StoreAccessor implements IDBStoreAccessor, objectAttacher = null; } - getStore().getMetaDataManager().clearMetaIDMappings(); + IDBStore store = getStore(); + IMetaDataManager metaDataManager = store.getMetaDataManager(); + metaDataManager.clearMetaIDMappings(); if (TRACER.isEnabled()) { @@ -795,10 +802,31 @@ public class DBStoreAccessor extends StoreAccessor implements IDBStoreAccessor, try { - getConnection().rollback(); + connection.rollback(); // Bug 298632: Must rollback DBSchema to its prior state and drop the tables - getStore().getMappingStrategy().removeMapping(getConnection(), commitContext.getNewPackageUnits()); + IMappingStrategy mappingStrategy = store.getMappingStrategy(); + mappingStrategy.removeMapping(connection, commitContext.getNewPackageUnits()); + + if (createdTables != null) + { + IDBDatabase database = store.getDatabase(); + IDBSchemaTransaction schemaTransaction = database.openSchemaTransaction(); + + try + { + for (IDBTable table : createdTables) + { + table.remove(); + } + + schemaTransaction.commit(); + } + finally + { + schemaTransaction.close(); + } + } } catch (SQLException ex) { @@ -848,6 +876,12 @@ public class DBStoreAccessor extends StoreAccessor implements IDBStoreAccessor, // this is called when the accessor is put back into the pool // we want to make sure that no DB lock is held (see Bug 276926) getConnection().rollback(); + + if (createdTables != null) + { + createdTables.clear(); + createdTables = null; + } } @Override @@ -1204,7 +1238,17 @@ public class DBStoreAccessor extends StoreAccessor implements IDBStoreAccessor, // rawImportPackageUnits(in, fromCommitTime, toCommitTime, packageUnits, monitor.fork()); - mappingStrategy.rawImport(this, in, fromCommitTime, toCommitTime, monitor.fork(size)); + IDBSchemaTransaction schemaTransaction = store.getDatabase().openSchemaTransaction(); + + try + { + mappingStrategy.rawImport(this, in, fromCommitTime, toCommitTime, monitor.fork(size)); + schemaTransaction.commit(); + } + finally + { + schemaTransaction.close(); + } rawCommit(commitWork, monitor); } @@ -1464,6 +1508,16 @@ public class DBStoreAccessor extends StoreAccessor implements IDBStoreAccessor, unitMappingTable.writeUnitMappings(this, unitMappings, timeStamp); } + public void tableCreated(IDBTable table) + { + if (createdTables == null) + { + createdTables = new ArrayList<IDBTable>(); + } + + createdTables.add(table); + } + /** * @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 3c88814253..3fc5999933 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 @@ -21,13 +21,8 @@ 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.model.CDOFeatureType; -import org.eclipse.emf.cdo.common.model.CDOModelUtil; -import org.eclipse.emf.cdo.common.model.CDOPackageRegistry; -import org.eclipse.emf.cdo.common.model.CDOPackageUnit; import org.eclipse.emf.cdo.common.model.EMFUtil; import org.eclipse.emf.cdo.common.revision.CDORevisionHandler; -import org.eclipse.emf.cdo.eresource.EresourcePackage; -import org.eclipse.emf.cdo.etypes.EtypesPackage; import org.eclipse.emf.cdo.server.IStoreAccessor.CommitContext; import org.eclipse.emf.cdo.server.StoreThreadLocal; import org.eclipse.emf.cdo.server.db.IDBStore; @@ -48,12 +43,10 @@ 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.IDBSchemaTransaction; import org.eclipse.net4j.db.ddl.IDBSchema; import org.eclipse.net4j.db.ddl.IDBTable; import org.eclipse.net4j.util.ImplementationError; 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; @@ -67,24 +60,19 @@ import org.eclipse.emf.ecore.ENamedElement; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.EStructuralFeature; -import org.eclipse.emf.ecore.EcorePackage; import org.eclipse.emf.ecore.util.FeatureMapUtil; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; -import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; -import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.Semaphore; /** * This abstract base class implements those methods which are most likely common to most mapping strategies. It can be @@ -123,8 +111,6 @@ public abstract class AbstractMappingStrategy extends Lifecycle implements IMapp private boolean allClassMappingsCreated; - private SystemPackageMappingInfo systemPackageMappingInfo; - private Set<CDOFeatureType> forceIndexes; public AbstractMappingStrategy() @@ -149,31 +135,31 @@ public abstract class AbstractMappingStrategy extends Lifecycle implements IMapp this.properties = properties; } - private int getMaxTableNameLength() + public int getMaxTableNameLength() { String value = getProperties().get(Props.MAX_TABLE_NAME_LENGTH); return value == null ? store.getDBAdapter().getMaxTableNameLength() : Integer.valueOf(value); } - private int getMaxFieldNameLength() + public int getMaxFieldNameLength() { String value = getProperties().get(Props.MAX_FIELD_NAME_LENGTH); return value == null ? store.getDBAdapter().getMaxFieldNameLength() : Integer.valueOf(value); } - private boolean isQualifiedNames() + public boolean isQualifiedNames() { String value = getProperties().get(Props.QUALIFIED_NAMES); return value == null ? false : Boolean.valueOf(value); } - private boolean isForceNamesWithID() + public boolean isForceNamesWithID() { String value = getProperties().get(Props.FORCE_NAMES_WITH_ID); return value == null ? false : Boolean.valueOf(value); } - private String getTableNamePrefix() + public String getTableNamePrefix() { String value = getProperties().get(Props.TABLE_NAME_PREFIX); return StringUtil.safe(value); @@ -221,25 +207,6 @@ public abstract class AbstractMappingStrategy extends Lifecycle implements IMapp } else { - EPackage ePackage = eClass.getEPackage(); - if (CDOModelUtil.isCorePackage(ePackage)) - { - initSystemPackageMappingInfo(); - if (!systemPackageMappingInfo.ecoreMapped) - { - return; - } - } - - if (CDOModelUtil.isTypesPackage(ePackage)) - { - initSystemPackageMappingInfo(); - if (!systemPackageMappingInfo.etypesMapped) - { - return; - } - } - IClassMapping classMapping = getClassMapping(eClass); classMapping.handleRevisions(accessor, branch, timeStamp, exactTime, handler); } @@ -493,92 +460,18 @@ public abstract class AbstractMappingStrategy extends Lifecycle implements IMapp return builder.toString(); } - // -- factories for mapping of classes, values, lists ------------------ - public void createMapping(Connection connection, InternalCDOPackageUnit[] packageUnits, OMMonitor monitor) { - boolean passedPackageUnits = packageUnits != null && packageUnits.length != 0; - Semaphore packageRegistryCommitLock = null; - boolean ecoreNew = false; - boolean etypesNew = false; - - Async async = null; monitor.begin(); + Async async = null; try { - async = monitor.forkAsync(); - - boolean isInitialCommit = passedPackageUnits && containsPackageUnit(packageUnits, EresourcePackage.eINSTANCE.getNsURI()); - if (isInitialCommit) - { - systemPackageMappingInfo = new SystemPackageMappingInfo(); - } - else - { - CommitContext commitContext = StoreThreadLocal.getCommitContext(); - if (commitContext != null && (commitContext.isUsingEcore() || commitContext.isUsingEtypes())) - { - InternalRepository repository = (InternalRepository)store.getRepository(); - if (!passedPackageUnits) - { - try - { - packageRegistryCommitLock = repository.getPackageRegistryCommitLock(); - packageRegistryCommitLock.acquire(); - } - catch (InterruptedException ex) - { - throw WrappedException.wrap(ex); - } - } - - initSystemPackageMappingInfo(); - - if (!systemPackageMappingInfo.ecoreMapped || !systemPackageMappingInfo.etypesMapped) - { - CDOPackageRegistry packageRegistry = repository.getPackageRegistry(); - List<InternalCDOPackageUnit> extendedPackageUnits = new ArrayList<InternalCDOPackageUnit>(); - if (passedPackageUnits) - { - extendedPackageUnits.addAll(Arrays.asList(packageUnits)); - } - - if (!systemPackageMappingInfo.ecoreMapped && commitContext.isUsingEcore()) - { - CDOPackageUnit packageUnit = packageRegistry.getPackageUnit(EcorePackage.eINSTANCE); - extendedPackageUnits.add((InternalCDOPackageUnit)packageUnit); - ecoreNew = true; - } - - if (!systemPackageMappingInfo.etypesMapped && commitContext.isUsingEtypes()) - { - CDOPackageUnit packageUnit = packageRegistry.getPackageUnit(EtypesPackage.eINSTANCE); - extendedPackageUnits.add((InternalCDOPackageUnit)packageUnit); - etypesNew = true; - } - - if (ecoreNew || etypesNew) - { - packageUnits = extendedPackageUnits.toArray(new InternalCDOPackageUnit[extendedPackageUnits.size()]); - } - } - } - } - if (packageUnits != null && packageUnits.length != 0) { - IDBSchemaTransaction schemaTransaction = store.getDatabase().openSchemaTransaction(); + async = monitor.forkAsync(); - try - { - mapPackageUnits(packageUnits, connection, false); - schemaTransaction.commit(); - } - finally - { - schemaTransaction.close(); - } + mapPackageUnits(packageUnits, connection, false); } } finally @@ -588,46 +481,13 @@ public abstract class AbstractMappingStrategy extends Lifecycle implements IMapp async.stop(); } - if (packageRegistryCommitLock != null) - { - systemPackageMappingInfo.ecoreMapped |= ecoreNew; - systemPackageMappingInfo.etypesMapped |= etypesNew; - packageRegistryCommitLock.release(); - } - monitor.done(); } } - private void initSystemPackageMappingInfo() - { - if (systemPackageMappingInfo == null) - { - systemPackageMappingInfo = new SystemPackageMappingInfo(); - systemPackageMappingInfo.ecoreMapped = hasTableFor(EcorePackage.eINSTANCE.getEPackage()); - systemPackageMappingInfo.etypesMapped = hasTableFor(EtypesPackage.eINSTANCE.getAnnotation()); - } - } - public void removeMapping(Connection connection, InternalCDOPackageUnit[] packageUnits) { - IDBSchemaTransaction schemaTransaction = store.getDatabase().openSchemaTransaction(); - - try - { - mapPackageUnits(packageUnits, connection, true); - schemaTransaction.commit(); - } - finally - { - schemaTransaction.close(); - } - } - - private boolean hasTableFor(EClass eClass) - { - String tableName = getTableName(eClass); - return store.getDBSchema().getTable(tableName) != null; + mapPackageUnits(packageUnits, connection, true); } protected Set<IClassMapping> mapPackageUnits(InternalCDOPackageUnit[] packageUnits, Connection connection, boolean unmap) @@ -837,19 +697,6 @@ public abstract class AbstractMappingStrategy extends Lifecycle implements IMapp } } - private static boolean containsPackageUnit(InternalCDOPackageUnit[] packageUnits, String packageUnitID) - { - for (InternalCDOPackageUnit packageUnit : packageUnits) - { - if (packageUnit.getID().equals(packageUnitID)) - { - return true; - } - } - - return false; - } - private static Set<CDOFeatureType> doGetForceIndexes(IMappingStrategy mappingStrategy) { return CDOFeatureType.readCombination(mappingStrategy.getProperties().get(Props.FORCE_INDEXES)); @@ -865,13 +712,9 @@ public abstract class AbstractMappingStrategy extends Lifecycle implements IMapp return doGetForceIndexes(mappingStrategy); } - /** - * @author Eike Stepper - */ - private static final class SystemPackageMappingInfo + public static boolean isEagerTableCreation(IMappingStrategy mappingStrategy) { - public boolean ecoreMapped; - - public boolean etypesMapped; + String value = mappingStrategy.getProperties().get(Props.EAGER_TABLE_CREATION); + return value == null ? false : Boolean.valueOf(value); } } 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 c579cd8377..2f50b8e20b 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 @@ -12,6 +12,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.common.model.CDOFeatureType; +import org.eclipse.emf.cdo.common.model.CDOModelUtil; 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; @@ -28,7 +30,9 @@ 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.cdo.server.db.mapping.ITypeMapping; +import org.eclipse.emf.cdo.server.internal.db.DBIndexAnnotation; import org.eclipse.emf.cdo.server.internal.db.bundle.OM; +import org.eclipse.emf.cdo.server.internal.db.mapping.AbstractMappingStrategy; import org.eclipse.net4j.db.DBException; import org.eclipse.net4j.db.DBUtil; @@ -45,6 +49,7 @@ import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; +import java.util.Set; /** * @author Stefan Winkler @@ -102,6 +107,33 @@ public abstract class AbstractBasicListTableMapping implements IListMapping3, IM public abstract void rawDeleted(IDBStoreAccessor accessor, CDOID id, CDOBranch branch, int version); + protected final boolean needsIndexOnValueField(EStructuralFeature feature) + { + IMappingStrategy mappingStrategy = getMappingStrategy(); + Set<CDOFeatureType> forceIndexes = AbstractMappingStrategy.getForceIndexes(mappingStrategy); + + if (CDOFeatureType.matchesCombination(feature, forceIndexes)) + { + return true; + } + + EClass eClass = getContainingClass(); + EStructuralFeature[] allPersistentFeatures = CDOModelUtil.getClassInfo(eClass).getAllPersistentFeatures(); + + for (List<EStructuralFeature> features : DBIndexAnnotation.getIndices(eClass, allPersistentFeatures)) + { + if (features.size() == 1) + { + if (features.get(0) == feature) + { + return true; + } + } + } + + return false; + } + /** * @author Eike Stepper */ 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 97d49c19b6..8a53e2bb2e 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 @@ -32,6 +32,8 @@ import org.eclipse.emf.cdo.common.revision.delta.CDORemoveFeatureDelta; import org.eclipse.emf.cdo.eresource.EresourcePackage; import org.eclipse.emf.cdo.server.IRepository; import org.eclipse.emf.cdo.server.IStoreAccessor.QueryXRefsContext; +import org.eclipse.emf.cdo.server.StoreThreadLocal; +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.mapping.IClassMapping; @@ -78,6 +80,7 @@ import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; @@ -117,222 +120,229 @@ public abstract class AbstractHorizontalClassMapping implements IClassMapping, I this.mappingStrategy = mappingStrategy; this.eClass = eClass; - initTable(); - initFields(); - initSQLStrings(); + IDBStoreAccessor accessor = null; + if (AbstractHorizontalMappingStrategy.isEagerTableCreation(mappingStrategy)) + { + accessor = (IDBStoreAccessor)StoreThreadLocal.getAccessor(); + } + + initTable(accessor); } - private void initTable() + protected void initTable(IDBStoreAccessor accessor) { - final String tableName = mappingStrategy.getTableName(eClass); - final DBType idType = mappingStrategy.getStore().getIDHandler().getDBType(); - final int idLength = mappingStrategy.getStore().getIDColumnLength(); + IDBStore store = mappingStrategy.getStore(); + IDBDatabase database = store.getDatabase(); + String tableName = mappingStrategy.getTableName(eClass); - IDBDatabase database = mappingStrategy.getStore().getDatabase(); table = database.getSchema().getTable(tableName); if (table == null) { - IDBSchemaTransaction schemaTransaction = database.getSchemaTransaction(); - IDBSchema workingCopy = schemaTransaction.getWorkingCopy(); - - table = workingCopy.addTable(tableName); - table.addField(ATTRIBUTES_ID, idType, idLength, true); - table.addField(ATTRIBUTES_VERSION, DBType.INTEGER, true); - - IDBField branchField = addBranchField(table); - - table.addField(ATTRIBUTES_CREATED, DBType.BIGINT, true); - table.addField(ATTRIBUTES_REVISED, DBType.BIGINT, true); - table.addField(ATTRIBUTES_RESOURCE, idType, idLength, true); - addContainerField(table, idType, idLength); - table.addField(ATTRIBUTES_FEATURE, DBType.INTEGER, true); - - IDBIndex primaryKey = table.addIndex(IDBIndex.Type.PRIMARY_KEY, ATTRIBUTES_ID, ATTRIBUTES_VERSION); - if (branchField != null) + if (accessor != null) { - primaryKey.addIndexField(branchField); - } + IDBSchemaTransaction schemaTransaction = database.openSchemaTransaction(); - table.addIndex(IDBIndex.Type.NON_UNIQUE, ATTRIBUTES_REVISED); - } - } + try + { + DBType idType = store.getIDHandler().getDBType(); + int idLength = store.getIDColumnLength(); - private void initFields() - { - final EStructuralFeature[] allPersistentFeatures = CDOModelUtil.getClassInfo(eClass).getAllPersistentFeatures(); - if (allPersistentFeatures == null) - { - valueMappings = Collections.emptyList(); - listMappings = Collections.emptyList(); - } - else - { - valueMappings = new ArrayList<ITypeMapping>(); - listMappings = new ArrayList<IListMapping>(); + IDBSchema workingCopy = schemaTransaction.getWorkingCopy(); + IDBTable table = workingCopy.addTable(tableName); + table.addField(ATTRIBUTES_ID, idType, idLength, true); + table.addField(ATTRIBUTES_VERSION, DBType.INTEGER, true); - boolean hasUnsettableFeatures = false; - for (EStructuralFeature feature : allPersistentFeatures) - { - String fieldName = mappingStrategy.getFieldName(feature); - if (feature.isMany()) - { - IListMapping mapping = null; - if (FeatureMapUtil.isFeatureMap(feature)) - { - mapping = mappingStrategy.createFeatureMapMapping(eClass, feature); - } - else - { - mapping = mappingStrategy.createListMapping(eClass, feature); - } + IDBField branchField = addBranchField(table); - if (mapping == null) - { - continue; - } + table.addField(ATTRIBUTES_CREATED, DBType.BIGINT, true); + table.addField(ATTRIBUTES_REVISED, DBType.BIGINT, true); + table.addField(ATTRIBUTES_RESOURCE, idType, idLength, true); + addContainerField(table, idType, idLength); + table.addField(ATTRIBUTES_FEATURE, DBType.INTEGER, true); - if (mapping instanceof IListMapping3) + IDBIndex primaryKey = table.addIndex(IDBIndex.Type.PRIMARY_KEY, ATTRIBUTES_ID, ATTRIBUTES_VERSION); + if (branchField != null) { - ((IListMapping3)mapping).setClassMapping(this); + primaryKey.addIndexField(branchField); } - listMappings.add(mapping); + table.addIndex(IDBIndex.Type.NON_UNIQUE, ATTRIBUTES_REVISED); - // Add field for list sizes - if (listSizeFields == null) - { - listSizeFields = new LinkedHashMap<EStructuralFeature, IDBField>(); - } + EStructuralFeature[] allPersistentFeatures = CDOModelUtil.getClassInfo(eClass).getAllPersistentFeatures(); + Map<EStructuralFeature, ITypeMapping> valueMappings = new HashMap<EStructuralFeature, ITypeMapping>(); + List<EStructuralFeature> unsettableFeatures = new ArrayList<EStructuralFeature>(); - IDBField field = table.getField(fieldName); - if (field == null) + for (EStructuralFeature feature : allPersistentFeatures) { - field = table.addField(fieldName, DBType.INTEGER); + String fieldName = mappingStrategy.getFieldName(feature); + if (feature.isMany()) + { + IListMapping mapping = createListMapping(feature); + if (mapping != null) + { + // Add field for list sizes. + table.addField(fieldName, DBType.INTEGER); + } + } + else + { + ITypeMapping valueMapping = mappingStrategy.createValueMapping(feature); + valueMapping.createDBField(table, fieldName); + valueMappings.put(feature, valueMapping); + + Set<CDOFeatureType> forceIndexes = AbstractMappingStrategy.getForceIndexes(mappingStrategy); + if (CDOFeatureType.matchesCombination(feature, forceIndexes)) + { + IDBField field = table.getField(fieldName); + if (!table.hasIndexFor(field)) + { + IDBIndex index = table.addIndex(IDBIndex.Type.NON_UNIQUE, field); + DBUtil.setOptional(index, true); // Creation might fail for unsupported column type! + } + } + + if (feature.isUnsettable()) + { + unsettableFeatures.add(feature); + } + } } - listSizeFields.put(feature, field); - } - else - { - ITypeMapping mapping = mappingStrategy.createValueMapping(feature); - IDBField field = table.getField(fieldName); - if (field == null) + // Add unsettable fields to end of table. + for (EStructuralFeature feature : unsettableFeatures) { - mapping.createDBField(table, fieldName); - } - else - { - mapping.setDBField(table, fieldName); + String fieldName = mappingStrategy.getUnsettableFieldName(feature); + table.addField(fieldName, DBType.BOOLEAN); } - valueMappings.add(mapping); - - Set<CDOFeatureType> forceIndexes = AbstractMappingStrategy.getForceIndexes(mappingStrategy); - if (CDOFeatureType.matchesCombination(feature, forceIndexes)) + // Create optional feature indices. + for (List<EStructuralFeature> features : DBIndexAnnotation.getIndices(eClass, allPersistentFeatures)) { - if (field == null) + int size = features.size(); + IDBField[] fields = new IDBField[size]; + + for (int i = 0; i < size; i++) { - field = table.getField(fieldName); + EStructuralFeature feature = features.get(i); + + ITypeMapping valueMapping = valueMappings.get(feature); + IDBField field = valueMapping.getField(); + fields[i] = field; } - if (!table.hasIndexFor(field)) + if (!table.hasIndexFor(fields)) { - IDBIndex index = table.addIndex(IDBIndex.Type.NON_UNIQUE, field); + IDBIndex index = table.addIndex(IDBIndex.Type.NON_UNIQUE, fields); DBUtil.setOptional(index, true); // Creation might fail for unsupported column type! } } - if (feature.isUnsettable()) - { - hasUnsettableFeatures = true; - } + schemaTransaction.commit(); } - } - - // Add unsettable fields to end of table - if (hasUnsettableFeatures) - { - unsettableFields = new LinkedHashMap<EStructuralFeature, IDBField>(); - for (EStructuralFeature feature : allPersistentFeatures) + finally { - if (!feature.isMany() && feature.isUnsettable()) - { - String fieldName = mappingStrategy.getUnsettableFieldName(feature); - IDBField field = table.getField(fieldName); - if (field == null) - { - field = table.addField(fieldName, DBType.BOOLEAN); - } - - unsettableFields.put(feature, field); - } + schemaTransaction.close(); } - } - initIndices(allPersistentFeatures); + initTable(null); + accessor.tableCreated(table); + } } - } - - private void initIndices(EStructuralFeature[] allPersistentFeatures) - { - for (List<EStructuralFeature> features : DBIndexAnnotation.getIndices(eClass, allPersistentFeatures)) + else { - int size = features.size(); - if (size > 1) - { - IDBField[] fields = new IDBField[size]; + valueMappings = null; + listMappings = null; + listSizeFields = null; + unsettableFields = null; - for (int i = 0; i < size; i++) - { - EStructuralFeature feature = features.get(i); - - ITypeMapping typeMapping = getValueMapping(feature); - IDBField field = typeMapping.getField(); - fields[i] = field; - } + EStructuralFeature[] allPersistentFeatures = CDOModelUtil.getClassInfo(eClass).getAllPersistentFeatures(); + List<EStructuralFeature> unsettableFeatures = new ArrayList<EStructuralFeature>(); - if (!table.hasIndexFor(fields)) - { - IDBIndex index = table.addIndex(IDBIndex.Type.NON_UNIQUE, fields); - DBUtil.setOptional(index, true); // Creation might fail for unsupported column type! - } - } - else + for (EStructuralFeature feature : allPersistentFeatures) { - EStructuralFeature feature = features.get(0); + String fieldName = mappingStrategy.getFieldName(feature); if (feature.isMany()) { - IListMapping listMapping = getListMapping(feature); - if (listMapping instanceof AbstractListTableMapping) + IListMapping mapping = createListMapping(feature); + if (mapping != null) { - AbstractListTableMapping mapping = (AbstractListTableMapping)listMapping; + if (mapping instanceof IListMapping3) + { + ((IListMapping3)mapping).setClassMapping(this); + } + + if (listMappings == null) + { + listMappings = new ArrayList<IListMapping>(); + } + + listMappings.add(mapping); - IDBTable table = mapping.getDBTables().iterator().next(); - ITypeMapping typeMapping = mapping.getTypeMapping(); - IDBField field = typeMapping.getField(); + IDBField listSizeField = table.getField(fieldName); - if (!table.hasIndexFor(field)) + if (listSizeFields == null) { - IDBIndex index = table.addIndex(IDBIndex.Type.NON_UNIQUE, field); - DBUtil.setOptional(index, true); // Creation might fail for unsupported column type! + listSizeFields = new LinkedHashMap<EStructuralFeature, IDBField>(); } + + listSizeFields.put(feature, listSizeField); } } else { - ITypeMapping typeMapping = getValueMapping(feature); - IDBField field = typeMapping.getField(); + ITypeMapping mapping = mappingStrategy.createValueMapping(feature); + mapping.setDBField(table, fieldName); - if (!table.hasIndexFor(field)) + if (valueMappings == null) { - IDBIndex index = table.addIndex(IDBIndex.Type.NON_UNIQUE, field); - DBUtil.setOptional(index, true); // Creation might fail for unsupported column type! + valueMappings = new ArrayList<ITypeMapping>(); } + + valueMappings.add(mapping); + + if (feature.isUnsettable()) + { + unsettableFeatures.add(feature); + } + } + } + + // Register unsettable fields. + if (!unsettableFeatures.isEmpty()) + { + unsettableFields = new LinkedHashMap<EStructuralFeature, IDBField>(); + for (EStructuralFeature feature : unsettableFeatures) + { + String fieldName = mappingStrategy.getUnsettableFieldName(feature); + IDBField field = table.getField(fieldName); + unsettableFields.put(feature, field); } } + + if (valueMappings == null) + { + valueMappings = Collections.emptyList(); + } + + if (listMappings == null) + { + listMappings = Collections.emptyList(); + } + + initSQLStrings(); } } + private IListMapping createListMapping(EStructuralFeature feature) + { + if (FeatureMapUtil.isFeatureMap(feature)) + { + return mappingStrategy.createFeatureMapMapping(eClass, feature); + } + + return mappingStrategy.createListMapping(eClass, feature); + } + protected void initSQLStrings() { // ----------- Select all revisions (for handleRevisions) --- @@ -574,9 +584,12 @@ public abstract class AbstractHorizontalClassMapping implements IClassMapping, I List<IDBTable> tables = new ArrayList<IDBTable>(); tables.add(table); - for (IListMapping listMapping : listMappings) + if (listMappings != null) { - tables.addAll(listMapping.getDBTables()); + for (IListMapping listMapping : listMappings) + { + tables.addAll(listMapping.getDBTables()); + } } return tables; @@ -610,6 +623,11 @@ public abstract class AbstractHorizontalClassMapping implements IClassMapping, I public void writeRevision(IDBStoreAccessor accessor, InternalCDORevision revision, boolean mapType, boolean revise, OMMonitor monitor) { + if (table == null) + { + initTable(accessor); + } + CDOID id = revision.getID(); InternalCDOBranch branch = revision.getBranch(); long timeStamp = revision.getTimeStamp(); @@ -723,6 +741,11 @@ public abstract class AbstractHorizontalClassMapping implements IClassMapping, I public void handleRevisions(IDBStoreAccessor accessor, CDOBranch branch, long timeStamp, boolean exactTime, CDORevisionHandler handler) { + if (table == null) + { + return; + } + // branch parameter is ignored, because either it is null or main branch. // this does not make any difference for non-branching store. // see #handleRevisions() implementation in HorizontalBranchingClassMapping @@ -828,6 +851,12 @@ public abstract class AbstractHorizontalClassMapping implements IClassMapping, I public Set<CDOID> readChangeSet(IDBStoreAccessor accessor, CDOChangeSetSegment[] segments) { + Set<CDOID> result = new HashSet<CDOID>(); + if (table == null) + { + return result; + } + StringBuilder builder = new StringBuilder(sqlSelectForChangeSet); boolean isFirst = true; @@ -855,8 +884,6 @@ public abstract class AbstractHorizontalClassMapping implements IClassMapping, I IDBPreparedStatement stmt = accessor.getDBConnection().prepareStatement(builder.toString(), ReuseProbability.LOW); ResultSet resultSet = null; - Set<CDOID> result = new HashSet<CDOID>(); - try { int column = 1; @@ -888,6 +915,11 @@ public abstract class AbstractHorizontalClassMapping implements IClassMapping, I public void detachObject(IDBStoreAccessor accessor, CDOID id, int version, CDOBranch branch, long timeStamp, OMMonitor monitor) { + if (table == null) + { + return; + } + Async async = null; monitor.begin(1 + listMappings.size()); @@ -925,6 +957,11 @@ public abstract class AbstractHorizontalClassMapping implements IClassMapping, I public void rawDelete(IDBStoreAccessor accessor, CDOID id, int version, CDOBranch branch, OMMonitor monitor) { + if (table == null) + { + return; + } + Async async = null; monitor.begin(1 + listMappings.size()); @@ -968,6 +1005,11 @@ public abstract class AbstractHorizontalClassMapping implements IClassMapping, I public final boolean queryXRefs(IDBStoreAccessor accessor, QueryXRefsContext context, String idString) { + if (table == null) + { + return true; + } + String tableName = table.getName(); List<EReference> refs = context.getSourceCandidates().get(eClass); List<EReference> scalarRefs = new ArrayList<EReference>(); @@ -1153,6 +1195,11 @@ public abstract class AbstractHorizontalClassMapping implements IClassMapping, I this.created = created; id = delta.getID(); + if (table == null) + { + initTable(accessor); + } + doProcess(delta); } diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AbstractHorizontalMappingStrategy.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AbstractHorizontalMappingStrategy.java index a4e316cad5..d56e94911c 100644 --- a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AbstractHorizontalMappingStrategy.java +++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AbstractHorizontalMappingStrategy.java @@ -443,6 +443,11 @@ public abstract class AbstractHorizontalMappingStrategy extends AbstractMappingS IIDHandler idHandler = getStore().getIDHandler(); PreparedStatement stmt = classMapping.createResourceQueryStatement(accessor, folderID, name, exactMatch, context); + if (stmt == null) + { + return true; + } + ResultSet resultSet = null; try diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AbstractListTableMapping.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AbstractListTableMapping.java index 07778bef59..395196fd91 100644 --- a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AbstractListTableMapping.java +++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AbstractListTableMapping.java @@ -14,11 +14,11 @@ package org.eclipse.emf.cdo.server.internal.db.mapping.horizontal; import org.eclipse.emf.cdo.common.id.CDOID; -import org.eclipse.emf.cdo.common.model.CDOFeatureType; import org.eclipse.emf.cdo.common.revision.CDOList; import org.eclipse.emf.cdo.common.revision.CDORevision; import org.eclipse.emf.cdo.server.IStoreAccessor.QueryXRefsContext; import org.eclipse.emf.cdo.server.IStoreChunkReader.Chunk; +import org.eclipse.emf.cdo.server.StoreThreadLocal; import org.eclipse.emf.cdo.server.db.IDBStore; import org.eclipse.emf.cdo.server.db.IDBStoreAccessor; import org.eclipse.emf.cdo.server.db.IDBStoreChunkReader; @@ -26,7 +26,6 @@ import org.eclipse.emf.cdo.server.db.IIDHandler; 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.server.internal.db.mapping.AbstractMappingStrategy; import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; import org.eclipse.net4j.db.DBException; @@ -35,9 +34,11 @@ import org.eclipse.net4j.db.DBUtil; import org.eclipse.net4j.db.IDBDatabase; import org.eclipse.net4j.db.IDBPreparedStatement; import org.eclipse.net4j.db.IDBPreparedStatement.ReuseProbability; +import org.eclipse.net4j.db.IDBSchemaTransaction; import org.eclipse.net4j.db.ddl.IDBField; import org.eclipse.net4j.db.ddl.IDBIndex; import org.eclipse.net4j.db.ddl.IDBIndex.Type; +import org.eclipse.net4j.db.ddl.IDBSchema; import org.eclipse.net4j.db.ddl.IDBTable; import org.eclipse.net4j.util.collection.MoveableList; import org.eclipse.net4j.util.om.trace.ContextTracer; @@ -53,7 +54,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; -import java.util.Set; /** * This abstract base class provides basic behavior needed for mapping many-valued attributes to tables. @@ -87,11 +87,17 @@ public abstract class AbstractListTableMapping extends AbstractBasicListTableMap public AbstractListTableMapping(IMappingStrategy mappingStrategy, EClass eClass, EStructuralFeature feature) { super(mappingStrategy, eClass, feature); - initTable(); - initSQLStrings(); + + IDBStoreAccessor accessor = null; + if (AbstractHorizontalMappingStrategy.isEagerTableCreation(mappingStrategy)) + { + accessor = (IDBStoreAccessor)StoreThreadLocal.getAccessor(); + } + + initTable(accessor); } - private void initTable() + protected void initTable(IDBStoreAccessor accessor) { IMappingStrategy mappingStrategy = getMappingStrategy(); EStructuralFeature feature = getFeature(); @@ -103,41 +109,59 @@ public abstract class AbstractListTableMapping extends AbstractBasicListTableMap table = database.getSchema().getTable(tableName); if (table == null) { - table = database.getSchemaTransaction().getWorkingCopy().addTable(tableName); - - IDBIndex primaryKey = table.addIndexEmpty(Type.PRIMARY_KEY); - for (FieldInfo info : getKeyFields()) + if (accessor != null) { - IDBField field = table.addField(info.getName(), info.getType(), info.getPrecision(), true); - primaryKey.addIndexField(field); - } + IDBSchemaTransaction schemaTransaction = database.openSchemaTransaction(); + + try + { + IDBSchema workingCopy = schemaTransaction.getWorkingCopy(); + IDBTable table = workingCopy.addTable(tableName); + + IDBIndex primaryKey = table.addIndexEmpty(Type.PRIMARY_KEY); + for (FieldInfo info : getKeyFields()) + { + IDBField field = table.addField(info.getName(), info.getType(), info.getPrecision(), true); + primaryKey.addIndexField(field); + } - // Add field for list index - IDBField field = table.addField(LIST_IDX, DBType.INTEGER, true); - primaryKey.addIndexField(field); + // Add field for list index. + IDBField listIndexField = table.addField(LIST_IDX, DBType.INTEGER, true); + primaryKey.addIndexField(listIndexField); - // Add field for value - typeMapping.createDBField(table, LIST_VALUE); + // Add field for value. + typeMapping.createDBField(table, LIST_VALUE); + + if (needsIndexOnValueField(feature)) + { + IDBField field = table.getField(LIST_VALUE); + + if (!table.hasIndexFor(field)) + { + IDBIndex index = table.addIndex(IDBIndex.Type.NON_UNIQUE, field); + DBUtil.setOptional(index, true); // Creation might fail for unsupported column type! + } + } + + schemaTransaction.commit(); + } + finally + { + schemaTransaction.close(); + } + + initTable(null); + accessor.tableCreated(table); + } } else { typeMapping.setDBField(table, LIST_VALUE); - } - - Set<CDOFeatureType> forceIndexes = AbstractMappingStrategy.getForceIndexes(mappingStrategy); - if (CDOFeatureType.matchesCombination(feature, forceIndexes)) - { - IDBField field = table.getField(LIST_VALUE); - - if (!table.hasIndexFor(field)) - { - IDBIndex index = table.addIndex(IDBIndex.Type.NON_UNIQUE, field); - DBUtil.setOptional(index, true); // Creation might fail for unsupported column type! - } + initSQLStrings(); } } - private void initSQLStrings() + protected void initSQLStrings() { String tableName = table.getName(); FieldInfo[] fields = getKeyFields(); @@ -233,6 +257,12 @@ public abstract class AbstractListTableMapping extends AbstractBasicListTableMap public void readValues(IDBStoreAccessor accessor, InternalCDORevision revision, int listChunk) { + if (table == null) + { + // Nothing to read. Take shortcut. + return; + } + if (listChunk == 0) { // Nothing to read. Take shortcut. @@ -397,8 +427,13 @@ public abstract class AbstractListTableMapping extends AbstractBasicListTableMap public void writeValues(IDBStoreAccessor accessor, InternalCDORevision revision) { CDOList values = revision.getListOrNull(getFeature()); - if (values != null) + if (values != null && !values.isEmpty()) { + if (table == null) + { + initTable(accessor); + } + int idx = 0; for (Object element : values) { @@ -437,6 +472,12 @@ public abstract class AbstractListTableMapping extends AbstractBasicListTableMap public boolean queryXRefs(IDBStoreAccessor accessor, String mainTableName, String mainTableWhere, QueryXRefsContext context, String idString) { + if (table == null) + { + // Nothing to read. Take shortcut. + return true; + } + String tableName = table.getName(); String listJoin = getMappingStrategy().getListJoin("a_t", "l_t"); diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AuditListTableMapping.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AuditListTableMapping.java index d004937683..90e7d5d9e7 100644 --- a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AuditListTableMapping.java +++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AuditListTableMapping.java @@ -45,11 +45,13 @@ public class AuditListTableMapping extends AbstractListTableMapping public AuditListTableMapping(IMappingStrategy mappingStrategy, EClass eClass, EStructuralFeature feature) { super(mappingStrategy, eClass, feature); - initSQLStrings(); } - private void initSQLStrings() + @Override + protected void initSQLStrings() { + super.initSQLStrings(); + IDBTable table = getTable(); // ----------- clear list ------------------------- @@ -86,6 +88,11 @@ public class AuditListTableMapping extends AbstractListTableMapping @Override public void rawDeleted(IDBStoreAccessor accessor, CDOID id, CDOBranch branch, int version) { + if (getTable() == null) + { + initTable(accessor); + } + IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler(); IDBPreparedStatement stmt = accessor.getDBConnection().prepareStatement(sqlClear, ReuseProbability.HIGH); 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 ac85dac311..a821408f31 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 @@ -32,6 +32,7 @@ import org.eclipse.emf.cdo.common.revision.delta.CDOUnsetFeatureDelta; import org.eclipse.emf.cdo.server.IRepository; import org.eclipse.emf.cdo.server.IStoreAccessor.QueryXRefsContext; import org.eclipse.emf.cdo.server.IStoreChunkReader.Chunk; +import org.eclipse.emf.cdo.server.StoreThreadLocal; import org.eclipse.emf.cdo.server.db.IDBStore; import org.eclipse.emf.cdo.server.db.IDBStoreAccessor; import org.eclipse.emf.cdo.server.db.IDBStoreChunkReader; @@ -51,7 +52,9 @@ import org.eclipse.net4j.db.DBUtil; import org.eclipse.net4j.db.IDBDatabase; import org.eclipse.net4j.db.IDBPreparedStatement; import org.eclipse.net4j.db.IDBPreparedStatement.ReuseProbability; +import org.eclipse.net4j.db.IDBSchemaTransaction; import org.eclipse.net4j.db.ddl.IDBIndex.Type; +import org.eclipse.net4j.db.ddl.IDBSchema; import org.eclipse.net4j.db.ddl.IDBTable; import org.eclipse.net4j.util.ImplementationError; import org.eclipse.net4j.util.collection.MoveableList; @@ -123,11 +126,17 @@ public class AuditListTableMappingWithRanges extends AbstractBasicListTableMappi public AuditListTableMappingWithRanges(IMappingStrategy mappingStrategy, EClass eClass, EStructuralFeature feature) { super(mappingStrategy, eClass, feature); - initTable(); - initSQLStrings(); + + IDBStoreAccessor accessor = null; + if (AbstractHorizontalMappingStrategy.isEagerTableCreation(mappingStrategy)) + { + accessor = (IDBStoreAccessor)StoreThreadLocal.getAccessor(); + } + + initTable(accessor); } - private void initTable() + private void initTable(IDBStoreAccessor accessor) { String tableName = getMappingStrategy().getTableName(getContainingClass(), getFeature()); typeMapping = getMappingStrategy().createValueMapping(getFeature()); @@ -140,20 +149,40 @@ public class AuditListTableMappingWithRanges extends AbstractBasicListTableMappi table = database.getSchema().getTable(tableName); if (table == null) { - table = database.getSchemaTransaction().getWorkingCopy().addTable(tableName); - table.addField(LIST_REVISION_ID, idType, idLength, true); - table.addField(LIST_REVISION_VERSION_ADDED, DBType.INTEGER); - table.addField(LIST_REVISION_VERSION_REMOVED, DBType.INTEGER); - table.addField(LIST_IDX, DBType.INTEGER, true); + if (accessor != null) + { + IDBSchemaTransaction schemaTransaction = database.openSchemaTransaction(); - // TODO think about indexes - table.addIndex(Type.NON_UNIQUE, LIST_REVISION_ID, LIST_REVISION_VERSION_ADDED, LIST_REVISION_VERSION_REMOVED, LIST_IDX); + try + { + IDBSchema workingCopy = schemaTransaction.getWorkingCopy(); + IDBTable table = workingCopy.addTable(tableName); + + table.addField(LIST_REVISION_ID, idType, idLength, true); + table.addField(LIST_REVISION_VERSION_ADDED, DBType.INTEGER); + table.addField(LIST_REVISION_VERSION_REMOVED, DBType.INTEGER); + table.addField(LIST_IDX, DBType.INTEGER, true); + + // TODO think about indexes + table.addIndex(Type.NON_UNIQUE, LIST_REVISION_ID, LIST_REVISION_VERSION_ADDED, LIST_REVISION_VERSION_REMOVED, LIST_IDX); - typeMapping.createDBField(table, LIST_VALUE); + typeMapping.createDBField(table, LIST_VALUE); + + schemaTransaction.commit(); + } + finally + { + schemaTransaction.close(); + } + + initTable(null); + accessor.tableCreated(table); + } } else { typeMapping.setDBField(table, LIST_VALUE); + initSQLStrings(); } } @@ -278,10 +307,11 @@ public class AuditListTableMappingWithRanges extends AbstractBasicListTableMappi @Override public void setClassMapping(IClassMapping classMapping) { - InternalRepository repository = (InternalRepository)getMappingStrategy().getStore().getRepository(); + IMappingStrategy mappingStrategy = getMappingStrategy(); + InternalRepository repository = (InternalRepository)mappingStrategy.getStore().getRepository(); if (repository.isSupportingUnits()) { - String listTableName = getTable().getName(); + String listTableName = mappingStrategy.getTableName(getContainingClass(), getFeature()); String attributesTableName = classMapping.getDBTables().get(0).getName(); sqlSelectUnitEntries = "SELECT " + (CHECK_UNIT_ENTRIES ? ATTRIBUTES_ID + ", " : "") + "cdo_list." + LIST_VALUE + // @@ -314,6 +344,12 @@ public class AuditListTableMappingWithRanges extends AbstractBasicListTableMappi public void readValues(IDBStoreAccessor accessor, InternalCDORevision revision, int listChunk) { + if (table == null) + { + // Nothing to read. Take shortcut. + return; + } + MoveableList<Object> list = revision.getListOrNull(getFeature()); if (list == null) { @@ -470,8 +506,13 @@ public class AuditListTableMappingWithRanges extends AbstractBasicListTableMappi public void writeValues(IDBStoreAccessor accessor, InternalCDORevision revision) { CDOList values = revision.getListOrNull(getFeature()); - if (values != null) + if (values != null && !values.isEmpty()) { + if (table == null) + { + initTable(accessor); + } + int idx = 0; for (Object element : values) { @@ -545,6 +586,11 @@ public class AuditListTableMappingWithRanges extends AbstractBasicListTableMappi public void objectDetached(IDBStoreAccessor accessor, CDOID id, long revised) { + if (table == null) + { + initTable(accessor); + } + if (TRACER.isEnabled()) { TRACER.format("objectRevised {0}: {1}", id, revised); //$NON-NLS-1$ @@ -745,6 +791,11 @@ public class AuditListTableMappingWithRanges extends AbstractBasicListTableMappi public final boolean queryXRefs(IDBStoreAccessor accessor, String mainTableName, String mainTableWhere, QueryXRefsContext context, String idString) { + if (table == null) + { + // Nothing to read. Take shortcut. + return true; + } String tableName = getTable().getName(); String listJoin = getMappingStrategy().getListJoin("a_t", "l_t"); @@ -821,6 +872,19 @@ public class AuditListTableMappingWithRanges extends AbstractBasicListTableMappi public void processDelta(final IDBStoreAccessor accessor, final CDOID id, final int branchId, int oldVersion, final int newVersion, long created, CDOListFeatureDelta delta) { + List<CDOFeatureDelta> listChanges = delta.getListChanges(); + int size = listChanges.size(); + if (size == 0) + { + // nothing to do. + return; + } + + if (table == null) + { + initTable(accessor); + } + IRepository repo = accessor.getStore().getRepository(); InternalCDORevision originalRevision = (InternalCDORevision)repo.getRevisionManager().getRevision(id, repo.getBranchManager().getMainBranch().getHead(), /* chunksize = */0, CDORevision.DEPTH_NONE, true); @@ -841,7 +905,7 @@ public class AuditListTableMappingWithRanges extends AbstractBasicListTableMappi TRACER.format("Processing deltas..."); //$NON-NLS-1$ } - for (CDOFeatureDelta listDelta : delta.getListChanges()) + for (CDOFeatureDelta listDelta : listChanges) { listDelta.accept(visitor); } diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/BranchingListTableMapping.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/BranchingListTableMapping.java index 51709f7939..7189656930 100644 --- a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/BranchingListTableMapping.java +++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/BranchingListTableMapping.java @@ -47,11 +47,13 @@ public class BranchingListTableMapping extends AbstractListTableMapping public BranchingListTableMapping(IMappingStrategy mappingStrategy, EClass eClass, EStructuralFeature feature) { super(mappingStrategy, eClass, feature); - initSQLStrings(); } - private void initSQLStrings() + @Override + protected void initSQLStrings() { + super.initSQLStrings(); + IDBTable table = getTable(); // ----------- clear list ------------------------- @@ -92,6 +94,11 @@ public class BranchingListTableMapping extends AbstractListTableMapping @Override public void rawDeleted(IDBStoreAccessor accessor, CDOID id, CDOBranch branch, int version) { + if (getTable() == null) + { + initTable(accessor); + } + IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler(); IDBPreparedStatement stmt = accessor.getDBConnection().prepareStatement(sqlClear, ReuseProbability.HIGH); diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/BranchingListTableMappingWithRanges.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/BranchingListTableMappingWithRanges.java index aac4f79ff2..f64306e4cd 100644 --- a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/BranchingListTableMappingWithRanges.java +++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/BranchingListTableMappingWithRanges.java @@ -33,6 +33,7 @@ import org.eclipse.emf.cdo.server.IStoreAccessor.QueryXRefsContext; import org.eclipse.emf.cdo.server.IStoreChunkReader; import org.eclipse.emf.cdo.server.IStoreChunkReader.Chunk; import org.eclipse.emf.cdo.server.ITransaction; +import org.eclipse.emf.cdo.server.StoreThreadLocal; import org.eclipse.emf.cdo.server.db.IDBStore; import org.eclipse.emf.cdo.server.db.IDBStoreAccessor; import org.eclipse.emf.cdo.server.db.IDBStoreChunkReader; @@ -51,7 +52,9 @@ import org.eclipse.net4j.db.DBUtil; import org.eclipse.net4j.db.IDBDatabase; import org.eclipse.net4j.db.IDBPreparedStatement; import org.eclipse.net4j.db.IDBPreparedStatement.ReuseProbability; +import org.eclipse.net4j.db.IDBSchemaTransaction; import org.eclipse.net4j.db.ddl.IDBIndex.Type; +import org.eclipse.net4j.db.ddl.IDBSchema; import org.eclipse.net4j.db.ddl.IDBTable; import org.eclipse.net4j.util.ImplementationError; import org.eclipse.net4j.util.collection.MoveableList; @@ -120,11 +123,17 @@ public class BranchingListTableMappingWithRanges extends AbstractBasicListTableM public BranchingListTableMappingWithRanges(IMappingStrategy mappingStrategy, EClass eClass, EStructuralFeature feature) { super(mappingStrategy, eClass, feature); - initTable(); - initSQLStrings(); + + IDBStoreAccessor accessor = null; + if (AbstractHorizontalMappingStrategy.isEagerTableCreation(mappingStrategy)) + { + accessor = (IDBStoreAccessor)StoreThreadLocal.getAccessor(); + } + + initTable(accessor); } - private void initTable() + private void initTable(IDBStoreAccessor accessor) { String tableName = getMappingStrategy().getTableName(getContainingClass(), getFeature()); typeMapping = getMappingStrategy().createValueMapping(getFeature()); @@ -137,29 +146,43 @@ public class BranchingListTableMappingWithRanges extends AbstractBasicListTableM table = database.getSchema().getTable(tableName); if (table == null) { - table = database.getSchemaTransaction().getWorkingCopy().addTable(tableName); - table.addField(LIST_REVISION_ID, idType, idLength, true); - table.addField(LIST_REVISION_BRANCH, DBType.INTEGER, true); - table.addField(LIST_REVISION_VERSION_ADDED, DBType.INTEGER); - table.addField(LIST_REVISION_VERSION_REMOVED, DBType.INTEGER); - table.addField(LIST_IDX, DBType.INTEGER, true); + if (accessor != null) + { + IDBSchemaTransaction schemaTransaction = database.openSchemaTransaction(); - // TODO think about indexes - table.addIndex(Type.NON_UNIQUE, LIST_REVISION_ID, LIST_REVISION_BRANCH, LIST_REVISION_VERSION_ADDED, LIST_REVISION_VERSION_REMOVED, LIST_IDX); + try + { + IDBSchema workingCopy = schemaTransaction.getWorkingCopy(); + IDBTable table = workingCopy.addTable(tableName); + table.addField(LIST_REVISION_ID, idType, idLength, true); + table.addField(LIST_REVISION_BRANCH, DBType.INTEGER, true); + table.addField(LIST_REVISION_VERSION_ADDED, DBType.INTEGER); + table.addField(LIST_REVISION_VERSION_REMOVED, DBType.INTEGER); + table.addField(LIST_IDX, DBType.INTEGER, true); + + // TODO think about indexes + table.addIndex(Type.NON_UNIQUE, LIST_REVISION_ID, LIST_REVISION_BRANCH, LIST_REVISION_VERSION_ADDED, LIST_REVISION_VERSION_REMOVED, LIST_IDX); + + typeMapping.createDBField(table, LIST_VALUE); + + schemaTransaction.commit(); + } + finally + { + schemaTransaction.close(); + } - typeMapping.createDBField(table, LIST_VALUE); + initTable(null); + accessor.tableCreated(table); + } } else { typeMapping.setDBField(table, LIST_VALUE); + initSQLStrings(); } } - public Collection<IDBTable> getDBTables() - { - return Collections.singleton(table); - } - private void initSQLStrings() { String tableName = getTable().getName(); @@ -284,6 +307,11 @@ public class BranchingListTableMappingWithRanges extends AbstractBasicListTableM sqlClearList = builder.toString(); } + public Collection<IDBTable> getDBTables() + { + return Collections.singleton(table); + } + protected final IDBTable getTable() { return table; @@ -296,6 +324,12 @@ public class BranchingListTableMappingWithRanges extends AbstractBasicListTableM public void readValues(IDBStoreAccessor accessor, InternalCDORevision revision, final int listChunk) { + if (table == null) + { + // Nothing to read. Take shortcut. + return; + } + MoveableList<Object> list = revision.getListOrNull(getFeature()); if (list == null) { @@ -617,8 +651,13 @@ public class BranchingListTableMappingWithRanges extends AbstractBasicListTableM public void writeValues(IDBStoreAccessor accessor, InternalCDORevision revision) { CDOList values = revision.getListOrNull(getFeature()); - if (values != null) + if (values != null && !values.isEmpty()) { + if (table == null) + { + initTable(accessor); + } + int idx = 0; for (Object element : values) { @@ -699,6 +738,11 @@ public class BranchingListTableMappingWithRanges extends AbstractBasicListTableM return; } + if (table == null) + { + initTable(accessor); + } + if (TRACER.isEnabled()) { TRACER.format("objectDetached {1}", revision); //$NON-NLS-1$ @@ -721,12 +765,18 @@ public class BranchingListTableMappingWithRanges extends AbstractBasicListTableM CDOListFeatureDelta delta) { List<CDOFeatureDelta> listChanges = delta.getListChanges(); - if (listChanges.size() == 0) + int size = listChanges.size(); + if (size == 0) { // nothing to do. return; } + if (table == null) + { + initTable(accessor); + } + InternalCDORevision originalRevision = (InternalCDORevision)accessor.getTransaction().getRevision(id); int oldListSize = originalRevision.size(getFeature()); @@ -747,7 +797,7 @@ public class BranchingListTableMappingWithRanges extends AbstractBasicListTableM // optimization: it's only necessary to process deltas // starting with the last feature delta which clears the list // (any operation before the clear is cascaded by it anyway) - int index = listChanges.size() - 1; + int index = size - 1; while (index > 0) { CDOFeatureDelta listDelta = listChanges.get(index); @@ -755,9 +805,10 @@ public class BranchingListTableMappingWithRanges extends AbstractBasicListTableM { break; } + index--; } - while (index < listChanges.size()) + while (index < size) { listChanges.get(index++).accept(visitor); } @@ -1380,6 +1431,11 @@ public class BranchingListTableMappingWithRanges extends AbstractBasicListTableM public final boolean queryXRefs(IDBStoreAccessor accessor, String mainTableName, String mainTableWhere, QueryXRefsContext context, String idString) { + if (table == null) + { + // Nothing to read. Take shortcut. + return true; + } String tableName = getTable().getName(); String listJoin = getMappingStrategy().getListJoin("a_t", "l_t"); 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 6feb25ebd9..e4ff0cd3e3 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 @@ -102,7 +102,6 @@ public class HorizontalAuditClassMapping extends AbstractHorizontalClassMapping public HorizontalAuditClassMapping(AbstractHorizontalMappingStrategy mappingStrategy, EClass eClass) { super(mappingStrategy, eClass); - initSQLStrings(); } @Override @@ -361,6 +360,11 @@ public class HorizontalAuditClassMapping extends AbstractHorizontalClassMapping public IDBPreparedStatement createResourceQueryStatement(IDBStoreAccessor accessor, CDOID folderId, String name, boolean exactMatch, CDOBranchPoint branchPoint) { + if (getTable() == null) + { + return null; + } + EStructuralFeature nameFeature = EresourcePackage.eINSTANCE.getCDOResourceNode_Name(); long timeStamp = branchPoint.getTimeStamp(); diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalBranchingClassMapping.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalBranchingClassMapping.java index e393717ea9..303a75a8fd 100644 --- a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalBranchingClassMapping.java +++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalBranchingClassMapping.java @@ -92,7 +92,6 @@ public class HorizontalBranchingClassMapping extends AbstractHorizontalClassMapp public HorizontalBranchingClassMapping(AbstractHorizontalMappingStrategy mappingStrategy, EClass eClass) { super(mappingStrategy, eClass); - initSQLStrings(); } @Override @@ -311,6 +310,11 @@ public class HorizontalBranchingClassMapping extends AbstractHorizontalClassMapp public IDBPreparedStatement createResourceQueryStatement(IDBStoreAccessor accessor, CDOID folderId, String name, boolean exactMatch, CDOBranchPoint branchPoint) { + if (getTable() == null) + { + return null; + } + EStructuralFeature nameFeature = EresourcePackage.eINSTANCE.getCDOResourceNode_Name(); ITypeMapping nameValueMapping = getValueMapping(nameFeature); @@ -576,6 +580,11 @@ public class HorizontalBranchingClassMapping extends AbstractHorizontalClassMapp @Override public void writeRevision(IDBStoreAccessor accessor, InternalCDORevision revision, boolean mapType, boolean revise, OMMonitor monitor) { + if (getTable() == null) + { + initTable(accessor); + } + CDOID id = revision.getID(); int version = revision.getVersion(); InternalCDOBranch branch = revision.getBranch(); @@ -691,6 +700,11 @@ public class HorizontalBranchingClassMapping extends AbstractHorizontalClassMapp @Override public void handleRevisions(IDBStoreAccessor accessor, CDOBranch branch, long timeStamp, boolean exactTime, CDORevisionHandler handler) { + if (getTable() == null) + { + return; + } + StringBuilder builder = new StringBuilder(getSQLSelectForHandle()); boolean whereAppend = false; @@ -805,6 +819,12 @@ public class HorizontalBranchingClassMapping extends AbstractHorizontalClassMapp @Override public Set<CDOID> readChangeSet(IDBStoreAccessor accessor, CDOChangeSetSegment[] segments) { + Set<CDOID> result = new HashSet<CDOID>(); + if (getTable() == null) + { + return result; + } + StringBuilder builder = new StringBuilder(getSQLSelectForChangeSet()); boolean isFirst = true; @@ -836,7 +856,6 @@ public class HorizontalBranchingClassMapping extends AbstractHorizontalClassMapp IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler(); IDBPreparedStatement stmt = accessor.getDBConnection().prepareStatement(sql, ReuseProbability.LOW); ResultSet resultSet = null; - Set<CDOID> result = new HashSet<CDOID>(); try { 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 b0946c36e4..49db7d7db0 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 @@ -85,13 +85,13 @@ public class HorizontalNonAuditClassMapping extends AbstractHorizontalClassMappi public HorizontalNonAuditClassMapping(AbstractHorizontalMappingStrategy mappingStrategy, EClass eClass) { super(mappingStrategy, eClass); - initSQLStrings(); - hasLists = !getListMappings().isEmpty(); } @Override protected void initSQLStrings() { + hasLists = !getListMappings().isEmpty(); + super.initSQLStrings(); // ----------- Select Revision --------------------------- @@ -274,6 +274,11 @@ public class HorizontalNonAuditClassMapping extends AbstractHorizontalClassMappi public IDBPreparedStatement createResourceQueryStatement(IDBStoreAccessor accessor, CDOID folderId, String name, boolean exactMatch, CDOBranchPoint branchPoint) { + if (getTable() == null) + { + return null; + } + long timeStamp = branchPoint.getTimeStamp(); if (timeStamp != CDORevision.UNSPECIFIED_DATE) { diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/NonAuditListTableMapping.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/NonAuditListTableMapping.java index bc791c94ac..ea04a417cd 100644 --- a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/NonAuditListTableMapping.java +++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/NonAuditListTableMapping.java @@ -69,11 +69,13 @@ public class NonAuditListTableMapping extends AbstractListTableMapping implement public NonAuditListTableMapping(IMappingStrategy mappingStrategy, EClass eClass, EStructuralFeature feature) { super(mappingStrategy, eClass, feature); - initSQLStrings(); } - private void initSQLStrings() + @Override + protected void initSQLStrings() { + super.initSQLStrings(); + IDBTable table = getTable(); // ----------- clear list ------------------------- @@ -205,6 +207,11 @@ public class NonAuditListTableMapping extends AbstractListTableMapping implement public void processDelta(IDBStoreAccessor accessor, CDOID id, int branchId, int oldVersion, int newVersion, long created, CDOListFeatureDelta delta) { + if (getTable() == null) + { + initTable(accessor); + } + List<CDOFeatureDelta> listChanges = delta.getListChanges(); int oldListSize = delta.getOriginSize(); @@ -228,6 +235,11 @@ public class NonAuditListTableMapping extends AbstractListTableMapping implement */ private void clearList(IDBStoreAccessor accessor, CDOID id) { + if (getTable() == null) + { + return; + } + IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler(); IDBPreparedStatement stmt = accessor.getDBConnection().prepareStatement(sqlClear, ReuseProbability.HIGH); @@ -248,6 +260,12 @@ public class NonAuditListTableMapping extends AbstractListTableMapping implement private int getCurrentIndexOffset(IDBStoreAccessor accessor, CDOID id) { + if (getTable() == null) + { + // List is empty. Return the default offset of 0. + return 0; + } + IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler(); IDBPreparedStatement stmt = accessor.getDBConnection().prepareStatement(sqlReadCurrentIndexOffset, ReuseProbability.HIGH); ResultSet rset = null; diff --git a/plugins/org.eclipse.emf.cdo.server.product/CDOServer.launch b/plugins/org.eclipse.emf.cdo.server.product/CDOServer.launch index 9ef9177045..dba19e1e70 100644 --- a/plugins/org.eclipse.emf.cdo.server.product/CDOServer.launch +++ b/plugins/org.eclipse.emf.cdo.server.product/CDOServer.launch @@ -31,7 +31,7 @@ <stringAttribute key="pde.version" value="3.3"/> <stringAttribute key="product" value="org.eclipse.platform.ide"/> <stringAttribute key="selectedPlugin" value="org.eclipse.emf.cdo"/> -<stringAttribute key="selected_target_plugins" value="com.ibm.icu@default:default,com.mysql.jdbc@default:default,javax.xml@default:default,org.apache.derby@default:default,org.apache.felix.gogo.command@default:default,org.apache.felix.gogo.runtime@default:default,org.apache.felix.gogo.shell@default:default,org.eclipse.ant.core@default:default,org.eclipse.compare.core@default:default,org.eclipse.core.contenttype@default:default,org.eclipse.core.expressions@default:default,org.eclipse.core.filesystem.win32.x86_64@default:false,org.eclipse.core.filesystem@default:default,org.eclipse.core.jobs@default:default,org.eclipse.core.runtime@default:true,org.eclipse.core.variables@default:default,org.eclipse.emf.common@default:default,org.eclipse.emf.ecore.change@default:default,org.eclipse.emf.ecore.xmi@default:default,org.eclipse.emf.ecore@default:default,org.eclipse.equinox.app@default:default,org.eclipse.equinox.common@2:true,org.eclipse.equinox.console@default:default,org.eclipse.equinox.preferences@default:default,org.eclipse.equinox.registry@default:default,org.eclipse.osgi.compatibility.state@default:false,org.eclipse.osgi@-1:true,org.h2@default:default,org.hsqldb@default:default,org.postgresql@default:default"/> +<stringAttribute key="selected_target_plugins" value="com.ibm.icu@default:default,com.mysql.jdbc@default:default,org.apache.derby@default:default,org.apache.felix.gogo.command@default:default,org.apache.felix.gogo.runtime@default:default,org.apache.felix.gogo.shell@default:default,org.eclipse.ant.core@default:default,org.eclipse.compare.core@default:default,org.eclipse.core.contenttype@default:default,org.eclipse.core.expressions@default:default,org.eclipse.core.filesystem.win32.x86_64@default:false,org.eclipse.core.filesystem@default:default,org.eclipse.core.jobs@default:default,org.eclipse.core.runtime@default:true,org.eclipse.core.variables@default:default,org.eclipse.emf.common@default:default,org.eclipse.emf.ecore.change@default:default,org.eclipse.emf.ecore.xmi@default:default,org.eclipse.emf.ecore@default:default,org.eclipse.equinox.app@default:default,org.eclipse.equinox.common@2:true,org.eclipse.equinox.console@default:default,org.eclipse.equinox.preferences@default:default,org.eclipse.equinox.registry@default:default,org.eclipse.osgi.compatibility.state@default:false,org.eclipse.osgi@-1:true,org.h2@default:default,org.hsqldb@default:default,org.postgresql@default:default"/> <stringAttribute key="selected_workspace_plugins" value="org.eclipse.emf.cdo.common@default:default,org.eclipse.emf.cdo.ecore.retrofit@default:false,org.eclipse.emf.cdo.examples.company@default:default,org.eclipse.emf.cdo.expressions@default:default,org.eclipse.emf.cdo.net4j@default:default,org.eclipse.emf.cdo.security@default:default,org.eclipse.emf.cdo.server.admin@default:default,org.eclipse.emf.cdo.server.db@default:default,org.eclipse.emf.cdo.server.net4j@default:default,org.eclipse.emf.cdo.server.security@default:default,org.eclipse.emf.cdo.server@default:default,org.eclipse.emf.cdo@default:default,org.eclipse.net4j.db.derby@default:default,org.eclipse.net4j.db.h2@default:default,org.eclipse.net4j.db.hsqldb@default:default,org.eclipse.net4j.db.jdbc@default:default,org.eclipse.net4j.db.mysql@default:default,org.eclipse.net4j.db.postgresql@default:default,org.eclipse.net4j.db@default:default,org.eclipse.net4j.jvm@default:default,org.eclipse.net4j.tcp@default:default,org.eclipse.net4j.util@default:default,org.eclipse.net4j@default:default"/> <booleanAttribute key="show_selected_only" value="true"/> <stringAttribute key="templateConfig" value="${target_home}\configuration\config.ini"/> diff --git a/plugins/org.eclipse.emf.cdo.server.product/config/cdo-server.xml b/plugins/org.eclipse.emf.cdo.server.product/config/cdo-server.xml index 28ff34c9c2..fa292f2dc9 100644 --- a/plugins/org.eclipse.emf.cdo.server.product/config/cdo-server.xml +++ b/plugins/org.eclipse.emf.cdo.server.product/config/cdo-server.xml @@ -61,6 +61,7 @@ <mappingStrategy type="horizontal"> <!-- callout --> <property name="qualifiedNames" value="true"/> <property name="withRanges" value="false"/> + <property name="eagerTableCreation" value="false"/> <!-- Per default, the objectTypeCache is in-memory and contains 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 79b61a60e2..63fe994b61 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 @@ -51,6 +51,7 @@ import org.eclipse.emf.cdo.common.util.CurrentTimeProvider; import org.eclipse.emf.cdo.common.util.RepositoryStateChangedEvent; import org.eclipse.emf.cdo.common.util.RepositoryTypeChangedEvent; import org.eclipse.emf.cdo.eresource.EresourcePackage; +import org.eclipse.emf.cdo.etypes.EtypesPackage; import org.eclipse.emf.cdo.internal.common.model.CDOPackageRegistryImpl; import org.eclipse.emf.cdo.internal.server.bundle.OM; import org.eclipse.emf.cdo.server.IQueryHandler; @@ -96,8 +97,6 @@ import org.eclipse.emf.cdo.spi.server.InternalUnitManager; import org.eclipse.emf.cdo.spi.server.InternalView; import org.eclipse.emf.internal.cdo.object.CDOFactoryImpl; -import org.eclipse.emf.internal.cdo.util.CompletePackageClosure; -import org.eclipse.emf.internal.cdo.util.IPackageClosure; import org.eclipse.net4j.util.AdapterUtil; import org.eclipse.net4j.util.ReflectUtil.ExcludeFromDump; @@ -2138,30 +2137,37 @@ public class Repository extends Container<Object> implements InternalRepository, public void initSystemPackages(final boolean firstStart) { + final List<InternalCDOPackageUnit> list = new ArrayList<InternalCDOPackageUnit>(); IStoreAccessor writer = store.getWriter(null); StoreThreadLocal.setAccessor(writer); try { - List<InternalCDOPackageUnit> list = new ArrayList<InternalCDOPackageUnit>(); - boolean nonSystemPackages = false; + long timeStamp; + if (firstStart) + { + timeStamp = store.getCreationTime(); + list.add(initPackage(timeStamp, EcorePackage.eINSTANCE)); + list.add(initPackage(timeStamp, EresourcePackage.eINSTANCE)); + list.add(initPackage(timeStamp, EtypesPackage.eINSTANCE)); + } + else + { + timeStamp = getTimeStamp(); + } + if (initialPackages != null) { for (EPackage initialPackage : initialPackages) { if (!packageRegistry.containsKey(initialPackage.getNsURI())) { - list.add(initPackage(initialPackage)); - nonSystemPackages = true; + InternalCDOPackageUnit packageUnit = initPackage(timeStamp, initialPackage); + list.add(packageUnit); } } } - if (nonSystemPackages && !firstStart) - { - OM.LOG.info("Initial packages are about to be pre-registered. They may not become part of replications."); - } - if (!list.isEmpty()) { InternalCDOPackageUnit[] initialUnits = list.toArray(new InternalCDOPackageUnit[list.size()]); @@ -2185,16 +2191,21 @@ public class Repository extends Container<Object> implements InternalRepository, { return firstStart; } + + public List<InternalCDOPackageUnit> getPackageUnits() + { + return Collections.unmodifiableList(list); + } }); } - protected InternalCDOPackageUnit initPackage(EPackage ePackage) + protected InternalCDOPackageUnit initPackage(long timeStamp, EPackage ePackage) { EMFUtil.registerPackage(ePackage, packageRegistry); InternalCDOPackageInfo packageInfo = packageRegistry.getPackageInfo(ePackage); InternalCDOPackageUnit packageUnit = packageInfo.getPackageUnit(); - packageUnit.setTimeStamp(store.getCreationTime()); + packageUnit.setTimeStamp(timeStamp); packageUnit.setState(CDOPackageUnit.State.LOADED); return packageUnit; } @@ -2244,7 +2255,6 @@ public class Repository extends Container<Object> implements InternalRepository, }; commitContext.setNewObjects(new InternalCDORevision[] { rootResource }); - commitContext.setNewPackageUnits(getNewPackageUnitsForRootResource(commitContext.getPackageRegistry())); commitContext.preWrite(); commitContext.write(new Monitor()); @@ -2262,23 +2272,6 @@ public class Repository extends Container<Object> implements InternalRepository, session.close(); } - private InternalCDOPackageUnit[] getNewPackageUnitsForRootResource(InternalCDOPackageRegistry commitContextPackageRegistry) - { - Collection<InternalCDOPackageUnit> newPackageUnitsForRootResource = new ArrayList<InternalCDOPackageUnit>(); - IPackageClosure closure = new CompletePackageClosure(); - Set<EPackage> ePackages = closure.calculate(Collections.<EPackage> singletonList(EresourcePackage.eINSTANCE)); - for (EPackage ePackage : ePackages) - { - InternalCDOPackageUnit packageUnit = commitContextPackageRegistry.getPackageUnit(ePackage); - if (packageUnit != null) - { - newPackageUnitsForRootResource.add(packageUnit); - } - } - - return newPackageUnitsForRootResource.toArray(new InternalCDOPackageUnit[0]); - } - protected CDOID createRootResourceID() { if (getIDGenerationLocation() == IDGenerationLocation.STORE) diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/bundle/CDOCommandProvider.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/bundle/CDOCommandProvider.java index 3b1495ce90..7d1206775f 100644 --- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/bundle/CDOCommandProvider.java +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/bundle/CDOCommandProvider.java @@ -124,6 +124,15 @@ public class CDOCommandProvider implements CommandProvider CDOServerExporter.XML exporter = new CDOServerExporter.XML(repository); exporter.exportRepository(out); + + if (args.length > 1) + { + if ("withSystemPackages".equalsIgnoreCase(args[1])) + { + exporter.setExportSystemPackages(true); + } + } + println("Repository exported"); } finally diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/CDOServerExporter.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/CDOServerExporter.java index dc8f036b9f..8b5e0971fd 100644 --- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/CDOServerExporter.java +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/CDOServerExporter.java @@ -69,6 +69,8 @@ public abstract class CDOServerExporter<OUT> { private InternalRepository repository; + private boolean exportSystemPackages; + public CDOServerExporter(IRepository repository) { this.repository = (InternalRepository)repository; @@ -79,6 +81,22 @@ public abstract class CDOServerExporter<OUT> return repository; } + /** + * @since 4.7 + */ + public boolean isExportSystemPackages() + { + return exportSystemPackages; + } + + /** + * @since 4.7 + */ + public void setExportSystemPackages(boolean exportSystemPackages) + { + this.exportSystemPackages = exportSystemPackages; + } + public final void exportRepository(OutputStream out) throws Exception { boolean wasActive = LifecycleUtil.isActive(repository); @@ -130,6 +148,11 @@ public abstract class CDOServerExporter<OUT> InternalCDOPackageUnit[] packageUnits = packageRegistry.getPackageUnits(true); for (InternalCDOPackageUnit packageUnit : packageUnits) { + if (packageUnit.isSystem() && !exportSystemPackages) + { + continue; + } + String id = packageUnit.getID(); CDOPackageUnit.Type type = packageUnit.getOriginalType(); long time = packageUnit.getTimeStamp(); diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/CDOServerImporter.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/CDOServerImporter.java index 56b7189308..dbc5542491 100644 --- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/CDOServerImporter.java +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/CDOServerImporter.java @@ -399,15 +399,21 @@ public abstract class CDOServerImporter else if (PACKAGE_UNIT.equals(qName)) { String id = attributes.getValue(PACKAGE_UNIT_ID); - Type type = CDOPackageUnit.Type.valueOf(attributes.getValue(PACKAGE_UNIT_TYPE)); - long time = Long.parseLong(attributes.getValue(PACKAGE_UNIT_TIME)); - String data = attributes.getValue(PACKAGE_UNIT_DATA); - handler.handlePackageUnit(id, type, time, data); + if (!CDOModelUtil.isSystemPackageURI(id)) + { + Type type = CDOPackageUnit.Type.valueOf(attributes.getValue(PACKAGE_UNIT_TYPE)); + long time = Long.parseLong(attributes.getValue(PACKAGE_UNIT_TIME)); + String data = attributes.getValue(PACKAGE_UNIT_DATA); + handler.handlePackageUnit(id, type, time, data); + } } else if (PACKAGE_INFO.equals(qName)) { String packageURI = attributes.getValue(PACKAGE_INFO_URI); - handler.handlePackageInfo(packageURI); + if (!CDOModelUtil.isSystemPackageURI(packageURI)) + { + handler.handlePackageInfo(packageURI); + } } else if (BRANCH.equals(qName)) { 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 406201d695..8318b3b274 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 @@ -36,6 +36,7 @@ import org.eclipse.emf.cdo.spi.common.commit.InternalCDOCommitInfoManager.Commit import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry; import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry.PackageLoader; import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry.PackageProcessor; +import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageUnit; import org.eclipse.emf.cdo.spi.common.revision.CDORevisionUnchunker; import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager; @@ -324,6 +325,8 @@ public interface InternalRepository extends IRepository, PackageProcessor, Packa public void setOptimisticLockingTimeout(long optimisticLockingTimeout); /** + * @noimplement This interface is not intended to be implemented by clients. + * @noextend This interface is not intended to be extended by clients. * @author Eike Stepper * @since 4.6 */ @@ -332,5 +335,10 @@ public interface InternalRepository extends IRepository, PackageProcessor, Packa public InternalRepository getSource(); public boolean isFirstStart(); + + /** + * @since 4.7 + */ + public List<InternalCDOPackageUnit> getPackageUnits(); } } diff --git a/plugins/org.eclipse.emf.cdo.tests.hibernate/src/org/eclipse/emf/cdo/tests/hibernate/AuditFeatureMapTest.java b/plugins/org.eclipse.emf.cdo.tests.hibernate/src/org/eclipse/emf/cdo/tests/hibernate/AuditFeatureMapTest.java index 30096edc93..1e27d26adb 100644 --- a/plugins/org.eclipse.emf.cdo.tests.hibernate/src/org/eclipse/emf/cdo/tests/hibernate/AuditFeatureMapTest.java +++ b/plugins/org.eclipse.emf.cdo.tests.hibernate/src/org/eclipse/emf/cdo/tests/hibernate/AuditFeatureMapTest.java @@ -37,11 +37,12 @@ import java.util.Map; * @Author Martin Taal */ @Requires(IRepositoryConfig.CAPABILITY_AUDITING) +@Deprecated public class AuditFeatureMapTest extends AbstractCDOTest { @Skips("Postgresql") - public void testFeatureMaps() throws Exception + public void _testFeatureMaps() throws Exception { skipStoreWithoutFeatureMaps(); diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AbstractSyncingTest.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AbstractSyncingTest.java index 39fef3be7c..4a4161eb4d 100644 --- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AbstractSyncingTest.java +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AbstractSyncingTest.java @@ -34,6 +34,7 @@ import org.eclipse.emf.cdo.util.CommitException; import org.eclipse.net4j.util.WrappedException; import org.eclipse.net4j.util.concurrent.ConcurrencyUtil; import org.eclipse.net4j.util.event.IEvent; +import org.eclipse.net4j.util.io.IOUtil; import org.eclipse.emf.ecore.EObject; @@ -195,17 +196,30 @@ public abstract class AbstractSyncingTest extends AbstractCDOTest protected static void waitForOnline(CDOCommonRepository repository) { + String what = repository.getName() + " becoming online"; + while (repository.getState() != CDOCommonRepository.State.ONLINE) { - waitFor("ONLINE"); + waitFor(what); + } + + if (VERBOSE_WAIT) + { + IOUtil.OUT().println(repository.getName() + " is online."); } } protected static void waitForOffline(CDOCommonRepository repository) { + String what = repository.getName() + " becoming offline"; while (repository.getState() == CDOCommonRepository.State.ONLINE) { - waitFor("OFFLINE"); + waitFor(what); + } + + if (VERBOSE_WAIT) + { + IOUtil.OUT().println(repository.getName() + " is offline."); } } @@ -251,7 +265,7 @@ public abstract class AbstractSyncingTest extends AbstractCDOTest { if (VERBOSE_WAIT) { - System.out.println("Waiting for " + what + "..."); + IOUtil.OUT().println("Waiting for " + what + "..."); sleep(SLEEP_MILLIS); } else diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/BackupTest.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/BackupTest.java index f0483c9f4a..7a541ec2fc 100644 --- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/BackupTest.java +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/BackupTest.java @@ -226,7 +226,8 @@ public class BackupTest extends AbstractCDOTest exporter.exportRepository(baos); } - public void testExportFeatureMap() throws Exception + @Deprecated + public void _testExportFeatureMap() throws Exception { CDOSession session = openSession(); CDOTransaction transaction = session.openTransaction(); @@ -506,7 +507,8 @@ public class BackupTest extends AbstractCDOTest } @CleanRepositoriesBefore(reason = "Inactive repository required") - public void testImportFeatureMap() throws Exception + @Deprecated + public void _testImportFeatureMap() throws Exception { CDOSession session = openSession(); CDOTransaction transaction = session.openTransaction(); diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/FeatureMapTest.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/FeatureMapTest.java index c2c44fa62e..d3fa864075 100644 --- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/FeatureMapTest.java +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/FeatureMapTest.java @@ -207,7 +207,7 @@ public class FeatureMapTest extends AbstractCDOTest } @Skips("Postgresql") - public void testFeatureMaps() throws Exception + public void _testFeatureMaps() throws Exception { skipStoreWithoutFeatureMaps(); diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_289932_Test.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_289932_Test.java index fde199f7ae..9903a62003 100644 --- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_289932_Test.java +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_289932_Test.java @@ -24,9 +24,10 @@ import org.eclipse.emf.cdo.transaction.CDOTransaction; * * @author Simon McDuff */ +@Deprecated public class Bugzilla_289932_Test extends AbstractCDOTest { - public void testBugzilla_289932() throws Exception + public void _testBugzilla_289932() throws Exception { CDOSession session = openSession(); session.getPackageRegistry().putEPackage(getModel5Package()); diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/impl/RepositoryConfig.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/impl/RepositoryConfig.java index ed7f7b2daa..1ef3a32610 100644 --- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/impl/RepositoryConfig.java +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/impl/RepositoryConfig.java @@ -1099,7 +1099,7 @@ public abstract class RepositoryConfig extends Config implements IRepositoryConf if (event instanceof ThrowableEvent) { ThrowableEvent e = (ThrowableEvent)event; - IOUtil.print(e.getThrowable()); + throw new RuntimeException(e.getThrowable()); } } }); diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/offline/FailoverTest.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/offline/FailoverTest.java index 710a7295d9..807749264d 100644 --- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/offline/FailoverTest.java +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/offline/FailoverTest.java @@ -158,17 +158,19 @@ public class FailoverTest extends AbstractSyncingTest public void testClientCommitsToBackupForbidden() throws Exception { - InternalRepository backup = getRepository(); - InternalRepository master = getRepository("master"); - TestListener listener = new TestListener(); CDOSession masterSession = openSession(master.getName()); + waitForOnline(masterSession.getRepositoryInfo()); + + TestListener listener = new TestListener(); masterSession.addListener(listener); + dumpEvents(masterSession); Company company = getModel1Factory().createCompany(); company.setName("Test"); + InternalRepository backup = getRepository(); CDOSession backupSession = openSession(backup.getName()); waitForOnline(backupSession.getRepositoryInfo()); diff --git a/plugins/org.eclipse.emf.cdo.workspace/src/org/eclipse/emf/cdo/internal/workspace/CDOWorkspaceImpl.java b/plugins/org.eclipse.emf.cdo.workspace/src/org/eclipse/emf/cdo/internal/workspace/CDOWorkspaceImpl.java index 4d71b4f845..5be3af6d02 100644 --- a/plugins/org.eclipse.emf.cdo.workspace/src/org/eclipse/emf/cdo/internal/workspace/CDOWorkspaceImpl.java +++ b/plugins/org.eclipse.emf.cdo.workspace/src/org/eclipse/emf/cdo/internal/workspace/CDOWorkspaceImpl.java @@ -206,7 +206,7 @@ public class CDOWorkspaceImpl extends Notifier implements InternalCDOWorkspace localRepository.setRootResourceID(rootResourceID); InternalCDOPackageRegistry localPackageRegistry = localRepository.getPackageRegistry(false); - InternalCDOPackageUnit[] remotePackageUnits = remoteSession.getPackageRegistry().getPackageUnits(true); + InternalCDOPackageUnit[] remotePackageUnits = remoteSession.getPackageRegistry().getPackageUnits(false); for (InternalCDOPackageUnit remotePackageUnit : remotePackageUnits) { InternalCDOPackageUnit localPackageUnit = remotePackageUnit.copy(); diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/util/CompletePackageClosure.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/util/CompletePackageClosure.java index fda65177e8..96b61eb744 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/util/CompletePackageClosure.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/util/CompletePackageClosure.java @@ -25,7 +25,6 @@ import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.EParameter; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.ETypeParameter; -import org.eclipse.emf.ecore.EcorePackage; import java.text.MessageFormat; import java.util.HashSet; @@ -39,53 +38,43 @@ public class CompletePackageClosure extends PackageClosure { private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG_MODEL, CompletePackageClosure.class); - private boolean excludeEcore; - public CompletePackageClosure() { } - public CompletePackageClosure(boolean excludeEcore) - { - this.excludeEcore = excludeEcore; - } - @Override protected void handleEPackage(EPackage ePackage, Set<EPackage> visitedPackages) { - if (ePackage != null && visitedPackages.add(ePackage)) + if (ePackage != null) { - if (excludeEcore && // Optimize EPackage comparison - (EcorePackage.eINSTANCE == ePackage || EcorePackage.eNS_URI.equals(ePackage.getNsURI()))) + if (visitedPackages.add(ePackage)) { - return; - } - - Set<Object> visited = new HashSet<Object>(); - for (EClassifier classifier : ePackage.getEClassifiers()) - { - handleEClassifier(classifier, visitedPackages, visited); - } + Set<Object> visited = new HashSet<Object>(); + for (EClassifier classifier : ePackage.getEClassifiers()) + { + handleEClassifier(classifier, visitedPackages, visited); + } - for (Object object : visited) - { - if (object instanceof EClassifier) + for (Object object : visited) { - EClassifier classifier = (EClassifier)object; - final EPackage p = classifier.getEPackage(); - if (p != null) + if (object instanceof EClassifier) { - if (visitedPackages.add(p)) + EClassifier classifier = (EClassifier)object; + final EPackage p = classifier.getEPackage(); + if (p != null) { - if (TRACER.isEnabled()) + if (visitedPackages.add(p)) { - TRACER.trace("Found package " + p.getNsURI()); //$NON-NLS-1$ + if (TRACER.isEnabled()) + { + TRACER.trace("Found package " + p.getNsURI()); //$NON-NLS-1$ + } } } - } - else - { - OM.LOG.warn(MessageFormat.format(Messages.getString("CompletePackageClosure.0"), classifier.getName())); //$NON-NLS-1$ + else + { + OM.LOG.warn(MessageFormat.format(Messages.getString("CompletePackageClosure.0"), classifier.getName())); //$NON-NLS-1$ + } } } } diff --git a/plugins/org.eclipse.net4j.db/META-INF/MANIFEST.MF b/plugins/org.eclipse.net4j.db/META-INF/MANIFEST.MF index 63f0e1c58f..a56d80f2d5 100644 --- a/plugins/org.eclipse.net4j.db/META-INF/MANIFEST.MF +++ b/plugins/org.eclipse.net4j.db/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.net4j.db;singleton:=true -Bundle-Version: 4.6.100.qualifier +Bundle-Version: 4.7.0.qualifier Bundle-Activator: org.eclipse.net4j.internal.db.bundle.OM$Activator Bundle-Vendor: %providerName Bundle-ClassPath: . @@ -11,17 +11,17 @@ Bundle-RequiredExecutionEnvironment: J2SE-1.5 Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.5.0,4.0.0)", org.eclipse.net4j.util;bundle-version="[3.0.0,4.0.0)";visibility:=reexport, org.eclipse.net4j.db.jdbc;bundle-version="[4.0.0,5.0.0)" -Export-Package: org.eclipse.net4j.db;version="4.6.100", - org.eclipse.net4j.db.ddl;version="4.6.100", - org.eclipse.net4j.db.ddl.delta;version="4.6.100", - org.eclipse.net4j.db.dml;version="4.6.100", - org.eclipse.net4j.internal.db;version="4.6.100";x-internal:=true, - org.eclipse.net4j.internal.db.bundle;version="4.6.100";x-internal:=true, - org.eclipse.net4j.internal.db.ddl;version="4.6.100";x-friends:="org.eclipse.emf.cdo.server.db", - org.eclipse.net4j.internal.db.ddl.delta;version="4.6.100";x-internal:=true, - org.eclipse.net4j.internal.db.dml;version="4.6.100";x-internal:=true, - org.eclipse.net4j.spi.db;version="4.6.100", - org.eclipse.net4j.spi.db.ddl;version="4.6.100" +Export-Package: org.eclipse.net4j.db;version="4.7.0", + org.eclipse.net4j.db.ddl;version="4.7.0", + org.eclipse.net4j.db.ddl.delta;version="4.7.0", + org.eclipse.net4j.db.dml;version="4.7.0", + org.eclipse.net4j.internal.db;version="4.7.0";x-internal:=true, + org.eclipse.net4j.internal.db.bundle;version="4.7.0";x-internal:=true, + org.eclipse.net4j.internal.db.ddl;version="4.7.0";x-friends:="org.eclipse.emf.cdo.server.db", + org.eclipse.net4j.internal.db.ddl.delta;version="4.7.0";x-internal:=true, + org.eclipse.net4j.internal.db.dml;version="4.7.0";x-internal:=true, + org.eclipse.net4j.spi.db;version="4.7.0", + org.eclipse.net4j.spi.db.ddl;version="4.7.0" Bundle-ActivationPolicy: lazy Eclipse-BuddyPolicy: registered Automatic-Module-Name: org.eclipse.net4j.db diff --git a/plugins/org.eclipse.net4j.db/pom.xml b/plugins/org.eclipse.net4j.db/pom.xml index fa80a1808a..df0ef3a7e1 100644 --- a/plugins/org.eclipse.net4j.db/pom.xml +++ b/plugins/org.eclipse.net4j.db/pom.xml @@ -25,7 +25,7 @@ <groupId>org.eclipse.emf.cdo</groupId> <artifactId>org.eclipse.net4j.db</artifactId> - <version>4.6.100-SNAPSHOT</version> + <version>4.7.0-SNAPSHOT</version> <packaging>eclipse-plugin</packaging> </project> diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/IDBDatabase.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/IDBDatabase.java index 2eb04118e4..24b9a477c9 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/IDBDatabase.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/IDBDatabase.java @@ -32,6 +32,15 @@ public interface IDBDatabase extends IContainer<IDBConnection>, IDBConnectionPro public IDBSchemaTransaction openSchemaTransaction(); + /** + * @since 4.7 + */ + public IDBSchemaTransaction openSchemaTransaction(IDBConnection connection); + + /** + * @deprecated As of 4.7 no longer supported in favor of support for multiple schema transactions. + */ + @Deprecated public IDBSchemaTransaction getSchemaTransaction(); public void updateSchema(RunnableWithSchema runnable); diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBConnection.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBConnection.java index 45998e809c..13e66b454d 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBConnection.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBConnection.java @@ -84,8 +84,7 @@ public final class DBConnection extends DelegatingConnection implements IDBConne public IDBSchemaTransaction openSchemaTransaction() { - DBSchemaTransaction schemaTransaction = database.openSchemaTransaction(); - schemaTransaction.setConnection(this); + DBSchemaTransaction schemaTransaction = database.openSchemaTransaction(this); return schemaTransaction; } 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 5df41b046f..9247b31957 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 @@ -22,8 +22,11 @@ import org.eclipse.net4j.internal.db.ddl.delta.DBSchemaDelta; import org.eclipse.net4j.spi.db.DBAdapter; import org.eclipse.net4j.spi.db.ddl.InternalDBSchema; import org.eclipse.net4j.util.WrappedException; +import org.eclipse.net4j.util.concurrent.TimeoutRuntimeException; import org.eclipse.net4j.util.container.SetContainer; import org.eclipse.net4j.util.event.Event; +import org.eclipse.net4j.util.io.IOUtil; +import org.eclipse.net4j.util.om.OMPlatform; import org.eclipse.net4j.util.security.IUserAware; import java.sql.Connection; @@ -35,6 +38,11 @@ import java.util.LinkedList; */ public final class DBDatabase extends SetContainer<IDBConnection> implements IDBDatabase { + private static final long TIMEOUT_SCHEMA_ACCESS = Long + .parseLong(OMPlatform.INSTANCE.getProperty("org.eclipse.net4j.internal.db.DBDatabase.TIMEOUT_SCHEMA_ACCESS", "15000")); + + private static final boolean DEBUG_SCHEMA_ACCESS = OMPlatform.INSTANCE.isProperty("org.eclipse.net4j.internal.db.DBDatabase.DEBUG_SCHEMA_ACCESS"); + private DBAdapter adapter; private IDBConnectionProvider connectionProvider; @@ -43,10 +51,10 @@ public final class DBDatabase extends SetContainer<IDBConnection> implements IDB private IDBSchema schema; - private DBSchemaTransaction schemaTransaction; - private final LinkedList<SchemaAccess> schemaAccessQueue = new LinkedList<SchemaAccess>(); + private int schemaWriters; + public DBDatabase(final DBAdapter adapter, IDBConnectionProvider connectionProvider, final String schemaName, final boolean fixNullableIndexColumns) { super(IDBConnection.class); @@ -87,13 +95,23 @@ public final class DBDatabase extends SetContainer<IDBConnection> implements IDB public DBSchemaTransaction openSchemaTransaction() { + return openSchemaTransaction(null); + } + + public DBSchemaTransaction openSchemaTransaction(IDBConnection connection) + { DBSchemaTransaction schemaTransaction = new DBSchemaTransaction(this); - this.schemaTransaction = schemaTransaction; + schemaTransaction.setConnection((DBConnection)connection); return schemaTransaction; } public void closeSchemaTransaction(DBSchemaDelta delta) { + if (delta == null || delta.isEmpty()) + { + return; + } + try { beginSchemaAccess(true); @@ -103,18 +121,18 @@ public final class DBDatabase extends SetContainer<IDBConnection> implements IDB ((DBConnection)transaction).invalidateStatementCache(); } - fireEvent(new SchemaChangedEventImpl(delta)); + fireEvent(new SchemaChangedEventImpl(this, delta)); } finally { - schemaTransaction = null; endSchemaAccess(); } } + @Deprecated public DBSchemaTransaction getSchemaTransaction() { - return schemaTransaction; + throw new UnsupportedOperationException(); } public void updateSchema(RunnableWithSchema runnable) @@ -191,6 +209,18 @@ public final class DBDatabase extends SetContainer<IDBConnection> implements IDB public void beginSchemaAccess(boolean write) { + if (DEBUG_SCHEMA_ACCESS) + { + try + { + throw new Exception("Begin " + (write ? "write" : "read") + " schema access: " + schema.getName()); + } + catch (Exception ex) + { + ex.printStackTrace(IOUtil.OUT()); + } + } + SchemaAccess schemaAccess = null; synchronized (schemaAccessQueue) { @@ -198,10 +228,11 @@ public final class DBDatabase extends SetContainer<IDBConnection> implements IDB { schemaAccess = new WriteSchemaAccess(); schemaAccessQueue.addLast(schemaAccess); + ++schemaWriters; } else { - if (!schemaAccessQueue.isEmpty()) + if (schemaWriters == 0 && !schemaAccessQueue.isEmpty()) { schemaAccess = schemaAccessQueue.getFirst(); if (schemaAccess instanceof ReadSchemaAccess) @@ -223,29 +254,52 @@ public final class DBDatabase extends SetContainer<IDBConnection> implements IDB } } - for (;;) + long end = System.currentTimeMillis() + TIMEOUT_SCHEMA_ACCESS; + + do { synchronized (schemaAccessQueue) { if (schemaAccessQueue.getFirst() == schemaAccess) { + if (write) + { + --schemaWriters; + } + return; } try { - schemaAccessQueue.wait(); + schemaAccessQueue.wait(1000L); } catch (InterruptedException ex) { + Thread.currentThread().interrupt(); throw WrappedException.wrap(ex); } } - } + } while (System.currentTimeMillis() < end); + + throw new TimeoutRuntimeException( + "Schema " + schema.getName() + " could not be locked for " + (write ? "write" : "read") + " access within " + TIMEOUT_SCHEMA_ACCESS + " milliseconds"); } public void endSchemaAccess() { + if (DEBUG_SCHEMA_ACCESS) + { + try + { + throw new Exception("End schema access: " + schema.getName()); + } + catch (Exception ex) + { + ex.printStackTrace(IOUtil.OUT()); + } + } + synchronized (schemaAccessQueue) { SchemaAccess schemaAccess = schemaAccessQueue.getFirst(); @@ -288,7 +342,7 @@ public final class DBDatabase extends SetContainer<IDBConnection> implements IDB /** * @author Eike Stepper */ - private final class ReadSchemaAccess implements SchemaAccess + private static final class ReadSchemaAccess implements SchemaAccess { private int readers = 1; @@ -312,7 +366,7 @@ public final class DBDatabase extends SetContainer<IDBConnection> implements IDB /** * @author Eike Stepper */ - private final class WriteSchemaAccess implements SchemaAccess + private static final class WriteSchemaAccess implements SchemaAccess { @Override public String toString() @@ -324,15 +378,15 @@ public final class DBDatabase extends SetContainer<IDBConnection> implements IDB /** * @author Eike Stepper */ - private final class SchemaChangedEventImpl extends Event implements SchemaChangedEvent + private static final class SchemaChangedEventImpl extends Event implements SchemaChangedEvent { private static final long serialVersionUID = 1L; private final IDBSchemaDelta schemaDelta; - public SchemaChangedEventImpl(IDBSchemaDelta schemaDelta) + public SchemaChangedEventImpl(DBDatabase database, IDBSchemaDelta schemaDelta) { - super(DBDatabase.this); + super(database); this.schemaDelta = schemaDelta; } diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBSchemaTransaction.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBSchemaTransaction.java index 970a166624..525766124e 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBSchemaTransaction.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBSchemaTransaction.java @@ -37,6 +37,8 @@ public final class DBSchemaTransaction implements IDBSchemaTransaction, Runnable private IDBSchema oldSchema; + private IDBSchema oldSchemaCopy; + private IDBSchema workingCopy; public DBSchemaTransaction(DBDatabase database) @@ -44,6 +46,8 @@ public final class DBSchemaTransaction implements IDBSchemaTransaction, Runnable this.database = database; oldSchema = database.getSchema(); + oldSchemaCopy = DBUtil.copySchema(oldSchema); + IDBSchema copy = DBUtil.copySchema(oldSchema); workingCopy = DelegatingDBSchemaElement.wrap(copy); } @@ -89,7 +93,7 @@ public final class DBSchemaTransaction implements IDBSchemaTransaction, Runnable public DBSchemaDelta getSchemaDelta() { - return (DBSchemaDelta)workingCopy.compare(oldSchema); + return (DBSchemaDelta)workingCopy.compare(oldSchemaCopy); } public DBSchemaDelta commit() @@ -99,6 +103,9 @@ public final class DBSchemaTransaction implements IDBSchemaTransaction, Runnable return DBUtil.execute(database, this); } + // Remember connection locally because the instance field will be reset in run/doClose. + DBConnection connection = this.connection; + try { DBSchemaDelta result = run(connection); @@ -116,19 +123,22 @@ public final class DBSchemaTransaction implements IDBSchemaTransaction, Runnable { DBSchemaDelta delta = getSchemaDelta(); - try - { - ((InternalDBSchema)oldSchema).unlock(); - - DBAdapter adapter = database.getAdapter(); - adapter.updateSchema(connection, oldSchema, delta); - - ((DelegatingDBSchema)workingCopy).setDelegate(oldSchema); - } - finally + synchronized (oldSchema) { - ((InternalDBSchema)oldSchema).lock(); - doClose(delta); + try + { + ((InternalDBSchema)oldSchema).unlock(); + + DBAdapter adapter = database.getAdapter(); + adapter.updateSchema(connection, oldSchema, delta); + + ((DelegatingDBSchema)workingCopy).setDelegate(oldSchema); + } + finally + { + ((InternalDBSchema)oldSchema).lock(); + doClose(delta); + } } return delta; @@ -146,6 +156,7 @@ public final class DBSchemaTransaction implements IDBSchemaTransaction, Runnable database.closeSchemaTransaction(delta); connection = null; oldSchema = null; + oldSchemaCopy = null; workingCopy = null; } } |