diff options
author | Eike Stepper | 2013-05-28 13:07:11 +0000 |
---|---|---|
committer | Eike Stepper | 2013-05-28 13:07:11 +0000 |
commit | 66de2a0d6677e4c9fb25c19728bc9aac0bf74d0a (patch) | |
tree | f8ff9f178cbe6f533675a7aa618b53dd1fd8c522 | |
parent | 20dce792a76718b199400de10e7df4ebd4f8b370 (diff) | |
download | cdo-bugs/396743.tar.gz cdo-bugs/396743.tar.xz cdo-bugs/396743.zip |
[396743] [DB] List size column mismatching the row entries bugs/396743
https://bugs.eclipse.org/bugs/show_bug.cgi?id=396743
21 files changed, 656 insertions, 465 deletions
diff --git a/plugins/org.eclipse.emf.cdo.common.db/.settings/.api_filters b/plugins/org.eclipse.emf.cdo.common.db/.settings/.api_filters index 751c8a17f5..e46b9e3036 100644 --- a/plugins/org.eclipse.emf.cdo.common.db/.settings/.api_filters +++ b/plugins/org.eclipse.emf.cdo.common.db/.settings/.api_filters @@ -33,6 +33,12 @@ </filter> </resource> <resource path="src/org/eclipse/emf/cdo/common/internal/db/cache/DBRevisionCache.java" type="org.eclipse.emf.cdo.common.internal.db.cache.DBRevisionCache"> + <filter id="574619656"> + <message_arguments> + <message_argument value="InternalCDORevisionCache"/> + <message_argument value="DBRevisionCache"/> + </message_arguments> + </filter> <filter id="574660632"> <message_arguments> <message_argument value="InternalCDORevisionCache"/> diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/util/CDOCommonUtil.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/util/CDOCommonUtil.java index 09e73e603f..58d224b428 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/util/CDOCommonUtil.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/util/CDOCommonUtil.java @@ -57,8 +57,14 @@ public final class CDOCommonUtil */ public static final String SYSTEM_USER_ID = "CDO_SYSTEM"; //$NON-NLS-1$ + /** + * @since 4.2 + */ + public static boolean STOP_CLIENTS; + private CDOCommonUtil() { + int StopClients; } /** diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/AbstractCDORevisionCache.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/AbstractCDORevisionCache.java index 91ef96c422..316af6f722 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/AbstractCDORevisionCache.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/AbstractCDORevisionCache.java @@ -16,10 +16,12 @@ import org.eclipse.emf.cdo.common.branch.CDOBranch; import org.eclipse.emf.cdo.common.id.CDOID; import org.eclipse.emf.cdo.common.revision.CDORevision; import org.eclipse.emf.cdo.common.revision.CDORevisionKey; +import org.eclipse.emf.cdo.internal.common.bundle.OM; import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionCache; import org.eclipse.net4j.util.event.IListener; +import org.eclipse.net4j.util.om.trace.ContextTracer; import org.eclipse.net4j.util.ref.ReferenceQueueWorker; import java.lang.ref.Reference; @@ -33,13 +35,39 @@ import java.text.MessageFormat; public abstract class AbstractCDORevisionCache extends ReferenceQueueWorker<InternalCDORevision> implements InternalCDORevisionCache { + private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG_REVISION, AbstractCDORevisionCache.class); + private static boolean disableGC; + private String name; + public AbstractCDORevisionCache() { setDaemon(true); } + public void setName(String name) + { + this.name = name; + } + + @Override + public String toString() + { + return formatName("CDORevisionCache"); + } + + @Override + protected String getThreadName() + { + return formatName("CDORevisionCacheCleaner"); + } + + private String formatName(String prefix) + { + return prefix + (name == null ? "" : "-" + name); + } + @Override protected void work(Reference<? extends InternalCDORevision> reference) { @@ -61,22 +89,36 @@ public abstract class AbstractCDORevisionCache extends ReferenceQueueWorker<Inte { fireEvent(new EvictionEventImpl(this, key), listeners); } + + if (TRACER.isEnabled()) + { + TRACER.format("Evicted {0} from {1}", key, this); //$NON-NLS-1$ + } } protected Reference<InternalCDORevision> createReference(CDORevision revision) { if (disableGC) { - return new CacheStrongReference((InternalCDORevision)revision); + return createStrongReference(revision); + } + + if (TRACER.isEnabled()) + { + TRACER.format("Adding revision {0} to {1}", revision, this); //$NON-NLS-1$ } return new CacheSoftReference((InternalCDORevision)revision, getQueue()); } - @Override - protected String getThreadName() + private Reference<InternalCDORevision> createStrongReference(CDORevision revision) { - return "CDORevisionCacheCleaner"; + if (TRACER.isEnabled()) + { + TRACER.format("Adding revision {0} to {1} (STRONGLY REFERENCED)", revision, this); //$NON-NLS-1$ + } + + return new CacheStrongReference((InternalCDORevision)revision); } /** diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/CDORevisionManagerImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/CDORevisionManagerImpl.java index 38e480e140..2c7fc8a4d3 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/CDORevisionManagerImpl.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/CDORevisionManagerImpl.java @@ -480,6 +480,12 @@ public class CDORevisionManagerImpl extends Lifecycle implements InternalCDORevi { cache = (InternalCDORevisionCache)CDORevisionUtil.createRevisionCache(supportingAudits, supportingBranches); } + + if (cache instanceof AbstractCDORevisionCache) + { + String name = revisionLoader.toString(); + ((AbstractCDORevisionCache)cache).setName(name); + } } @Override diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/InternalCDORevisionCache.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/InternalCDORevisionCache.java index a2dcaaddf7..a6d8991603 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/InternalCDORevisionCache.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/InternalCDORevisionCache.java @@ -26,6 +26,8 @@ import java.util.List; * * @author Eike Stepper * @since 3.0 + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. */ public interface InternalCDORevisionCache extends CDORevisionCache, CDOAllRevisionsProvider, ILifecycle { diff --git a/plugins/org.eclipse.emf.cdo.server.db/.settings/.api_filters b/plugins/org.eclipse.emf.cdo.server.db/.settings/.api_filters index 16058e23d1..53141a771c 100644 --- a/plugins/org.eclipse.emf.cdo.server.db/.settings/.api_filters +++ b/plugins/org.eclipse.emf.cdo.server.db/.settings/.api_filters @@ -1,5 +1,13 @@ <?xml version="1.0" encoding="UTF-8" standalone="no"?> <component id="org.eclipse.emf.cdo.server.db" version="2"> + <resource path="src/org/eclipse/emf/cdo/server/db/mapping/IListMappingDeltaSupport.java" type="org.eclipse.emf.cdo.server.db.mapping.IListMappingDeltaSupport"> + <filter id="403767336"> + <message_arguments> + <message_argument value="org.eclipse.emf.cdo.server.db.mapping.IListMappingDeltaSupport"/> + <message_argument value="NEW_LIST_SIZE"/> + </message_arguments> + </filter> + </resource> <resource path="src/org/eclipse/emf/cdo/server/db/mapping/IMappingStrategy.java" type="org.eclipse.emf.cdo.server.db.mapping.IMappingStrategy"> <filter id="403767336"> <message_arguments> @@ -23,4 +31,12 @@ </message_arguments> </filter> </resource> + <resource path="src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalNonAuditClassMapping.java" type="org.eclipse.emf.cdo.server.internal.db.mapping.horizontal.HorizontalNonAuditClassMapping$ViewForImplicitReadLocks"> + <filter id="574619656"> + <message_arguments> + <message_argument value="IView"/> + <message_argument value="ViewForImplicitReadLocks"/> + </message_arguments> + </filter> + </resource> </component> 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 9dc67a301a..a1c87a559f 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 @@ -243,13 +243,13 @@ public class DBStoreAccessor extends StoreAccessor implements IDBStoreAccessor, if (eClass != null) { InternalCDORevision revision = getStore().createRevision(eClass, id); - revision.setBranchPoint(branchPoint); + revision.setBranchPoint(branchPoint); // This is part of the search criterion, being replaced later IClassMapping mapping = mappingStrategy.getClassMapping(eClass); if (mapping.readRevision(this, revision, listChunk)) { int version = revision.getVersion(); - if (version < CDOBranchVersion.FIRST_VERSION - 1) + if (version < CDOBranchVersion.UNSPECIFIED_VERSION) { return new DetachedCDORevision(eClass, id, revision.getBranch(), -version, revision.getTimeStamp(), revision.getRevised()); 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 6107b21062..426b72bb4d 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 @@ -16,6 +16,7 @@ package org.eclipse.emf.cdo.server.internal.db.mapping.horizontal; import org.eclipse.emf.cdo.common.id.CDOID; import org.eclipse.emf.cdo.common.revision.CDOList; import org.eclipse.emf.cdo.common.revision.CDORevision; +import org.eclipse.emf.cdo.common.util.CDOCommonUtil; import org.eclipse.emf.cdo.server.IStoreAccessor.QueryXRefsContext; import org.eclipse.emf.cdo.server.IStoreChunkReader.Chunk; import org.eclipse.emf.cdo.server.db.IDBStore; @@ -216,10 +217,9 @@ public abstract class AbstractListTableMapping extends AbstractBasicListTableMap public void readValues(IDBStoreAccessor accessor, InternalCDORevision revision, int listChunk) { MoveableList<Object> list = revision.getList(getFeature()); - if (listChunk == 0 || list.size() == 0) { - // nothing to read take shortcut + // Nothing to read. Take shortcut. return; } @@ -274,6 +274,11 @@ public abstract class AbstractListTableMapping extends AbstractBasicListTableMap } catch (IndexOutOfBoundsException ex) { + CDOCommonUtil.STOP_CLIENTS = true; + int size = list.size(); + int badIndex = currentIndex - 1; + System.out.println("Size = " + size); + System.out.println("Bad index = " + badIndex); ex.printStackTrace(); } } 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 b6fe2c9d1c..2c8660d96c 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 @@ -13,10 +13,10 @@ */ package org.eclipse.emf.cdo.server.internal.db.mapping.horizontal; +import org.eclipse.emf.cdo.common.CDOCommonView; import org.eclipse.emf.cdo.common.branch.CDOBranch; import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; import org.eclipse.emf.cdo.common.id.CDOID; -import org.eclipse.emf.cdo.common.id.CDOIDUtil; import org.eclipse.emf.cdo.common.revision.CDOList; import org.eclipse.emf.cdo.common.revision.CDORevision; import org.eclipse.emf.cdo.common.revision.delta.CDOAddFeatureDelta; @@ -30,15 +30,22 @@ import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta; import org.eclipse.emf.cdo.common.revision.delta.CDOSetFeatureDelta; import org.eclipse.emf.cdo.common.revision.delta.CDOUnsetFeatureDelta; import org.eclipse.emf.cdo.eresource.EresourcePackage; +import org.eclipse.emf.cdo.server.IRepository; +import org.eclipse.emf.cdo.server.ISession; import org.eclipse.emf.cdo.server.IStoreAccessor.QueryXRefsContext; +import org.eclipse.emf.cdo.server.IView; import org.eclipse.emf.cdo.server.db.IDBStoreAccessor; import org.eclipse.emf.cdo.server.db.IIDHandler; import org.eclipse.emf.cdo.server.db.mapping.IClassMappingDeltaSupport; import org.eclipse.emf.cdo.server.db.mapping.IListMappingDeltaSupport; import org.eclipse.emf.cdo.server.db.mapping.ITypeMapping; +import org.eclipse.emf.cdo.server.internal.db.DBStore; import org.eclipse.emf.cdo.server.internal.db.bundle.OM; +import org.eclipse.emf.cdo.server.internal.db.mapping.horizontal.NonAuditListTableMapping.NewListSizeResult; import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionDelta; +import org.eclipse.emf.cdo.spi.server.InternalCommitContext; +import org.eclipse.emf.cdo.spi.server.InternalLockManager; import org.eclipse.net4j.db.DBException; import org.eclipse.net4j.db.DBUtil; @@ -46,7 +53,9 @@ import org.eclipse.net4j.db.IDBPreparedStatement; import org.eclipse.net4j.db.IDBPreparedStatement.ReuseProbability; import org.eclipse.net4j.db.ddl.IDBField; import org.eclipse.net4j.util.ImplementationError; +import org.eclipse.net4j.util.WrappedException; import org.eclipse.net4j.util.collection.Pair; +import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType; import org.eclipse.net4j.util.om.monitor.OMMonitor; import org.eclipse.net4j.util.om.monitor.OMMonitor.Async; import org.eclipse.net4j.util.om.trace.ContextTracer; @@ -54,11 +63,10 @@ import org.eclipse.net4j.util.om.trace.ContextTracer; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EStructuralFeature; -import java.sql.Connection; -import java.sql.ResultSet; import java.sql.SQLException; -import java.sql.Statement; import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Map; @@ -70,6 +78,8 @@ public class HorizontalNonAuditClassMapping extends AbstractHorizontalClassMappi { private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG, HorizontalNonAuditClassMapping.class); + private static final IView VIEW_FOR_IMPLICIT_READ_LOCKS = new ViewForImplicitReadLocks(); + private String sqlSelectAllObjectIDs; private String sqlSelectCurrentAttributes; @@ -84,6 +94,8 @@ public class HorizontalNonAuditClassMapping extends AbstractHorizontalClassMappi private String sqlDelete; + private boolean hasLists; + private ThreadLocal<FeatureDeltaWriter> deltaWriter = new ThreadLocal<FeatureDeltaWriter>() { @Override @@ -97,6 +109,7 @@ public class HorizontalNonAuditClassMapping extends AbstractHorizontalClassMappi { super(mappingStrategy, eClass); initSQLStrings(); + hasLists = !getListMappings().isEmpty(); } private void initSQLStrings() @@ -340,13 +353,30 @@ public class HorizontalNonAuditClassMapping extends AbstractHorizontalClassMappi throw new UnsupportedOperationException("Mapping strategy does not support audits"); //$NON-NLS-1$ } - IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler(); + DBStore store = (DBStore)getMappingStrategy().getStore(); + IIDHandler idHandler = store.getIDHandler(); IDBPreparedStatement stmt = accessor.getDBConnection().prepareStatement(sqlSelectCurrentAttributes, ReuseProbability.HIGH); + CDOID id = revision.getID(); + + InternalLockManager lockingManager = null; + Collection<CDOID> ids = null; + + if (hasLists && !isComputingDirtyObjects()) + { + lockingManager = store.getRepository().getLockingManager(); + ids = Collections.singleton(id); + } + try { - idHandler.setCDOID(stmt, 1, revision.getID()); + idHandler.setCDOID(stmt, 1, id); + + if (lockingManager != null) + { + lockingManager.lock2(LockType.READ, VIEW_FOR_IMPLICIT_READ_LOCKS, ids, 10000); + } // Read singleval-attribute table always (even without modeled attributes!) boolean success = readValuesFromStatement(stmt, revision, accessor); @@ -363,12 +393,31 @@ public class HorizontalNonAuditClassMapping extends AbstractHorizontalClassMappi { throw new DBException(ex); } + catch (InterruptedException ex) + { + throw WrappedException.wrap(ex); + } finally { - DBUtil.close(stmt); + try + { + if (lockingManager != null) + { + lockingManager.unlock2(LockType.READ, VIEW_FOR_IMPLICIT_READ_LOCKS, ids); + } + } + finally + { + DBUtil.close(stmt); + } } } + private boolean isComputingDirtyObjects() + { + return InternalCommitContext.COMPUTING_DIRTY_OBJECTS.get() == Boolean.TRUE; + } + @Override protected void detachAttributes(IDBStoreAccessor accessor, CDOID id, int version, CDOBranch branch, long timeStamp, OMMonitor monitor) @@ -429,6 +478,28 @@ public class HorizontalNonAuditClassMapping extends AbstractHorizontalClassMappi } } + @Override + protected void reviseOldRevision(IDBStoreAccessor accessor, CDOID id, CDOBranch branch, long timeStamp) + { + // do nothing + } + + @Override + protected String getListXRefsWhere(QueryXRefsContext context) + { + if (CDORevision.UNSPECIFIED_DATE != context.getTimeStamp()) + { + throw new IllegalArgumentException("Non-audit mode does not support timestamp specification"); + } + + if (!context.getBranch().isMainBranch()) + { + throw new IllegalArgumentException("Non-audit mode does not support branch specification"); + } + + return ATTRIBUTES_REVISED + "=0"; + } + /** * @author Eike Stepper */ @@ -458,11 +529,6 @@ public class HorizontalNonAuditClassMapping extends AbstractHorizontalClassMappi private int newVersion; - /* - * this is a temporary copy of the revision to track list size changes... - */ - private InternalCDORevision tempRevision; - public FeatureDeltaWriter() { attributeChanges = new ArrayList<Pair<ITypeMapping, Object>>(); @@ -476,25 +542,29 @@ public class HorizontalNonAuditClassMapping extends AbstractHorizontalClassMappi updateContainer = false; } - public void process(IDBStoreAccessor a, CDORevisionDelta d, long c) + public void process(IDBStoreAccessor accessor, CDORevisionDelta delta, long created) { - // set context - id = d.getID(); - - branchId = d.getBranch().getID(); - oldVersion = d.getVersion(); - newVersion = oldVersion + 1; - created = c; - accessor = a; + try + { + // Set context + id = delta.getID(); - tempRevision = (InternalCDORevision)accessor.getTransaction().getRevision(id).copy(); + branchId = delta.getBranch().getID(); + oldVersion = delta.getVersion(); + newVersion = oldVersion + 1; + this.created = created; + this.accessor = accessor; - // process revision delta tree - d.accept(this); + // Process revision delta tree + delta.accept(this); - updateAttributes(); - // clean up - reset(); + updateAttributes(); + } + finally + { + // Clean up + reset(); + } } public void visit(CDOMoveFeatureDelta delta) @@ -529,39 +599,17 @@ public class HorizontalNonAuditClassMapping extends AbstractHorizontalClassMappi public void visit(CDOListFeatureDelta delta) { EStructuralFeature feature = delta.getFeature(); - - IListMappingDeltaSupport listMapping = (IListMappingDeltaSupport)getListMapping(feature); - listMapping.processDelta(accessor, id, branchId, oldVersion, oldVersion + 1, created, delta); - - CDOList list = tempRevision.getList(feature); - int oldSize = list.size(); - delta.apply(tempRevision); - int newSize = list.size(); - - Statement stmt = null; - ResultSet rset = null; + int oldSize = delta.getOriginSize(); + int newSize = -1; try { - Connection conn = accessor.getConnection(); - stmt = conn.createStatement(); - rset = stmt.executeQuery("SELECT COUNT(*) FROM " + getListMapping(feature).getDBTables().iterator().next() - + " WHERE " + IMappingConstants.LIST_REVISION_ID + "=" + CDOIDUtil.getLong(id)); - rset.next(); - int wantedSize = rset.getInt(1); - if (wantedSize != newSize) - { - throw new IllegalStateException(); - } - } - catch (SQLException ex) - { - ex.printStackTrace(); + IListMappingDeltaSupport listMapping = (IListMappingDeltaSupport)getListMapping(feature); + listMapping.processDelta(accessor, id, branchId, oldVersion, oldVersion + 1, created, delta); } - finally + catch (NewListSizeResult result) { - DBUtil.close(rset); - DBUtil.close(stmt); + newSize = result.getNewListSize(); } if (oldSize != newSize) @@ -707,25 +755,79 @@ public class HorizontalNonAuditClassMapping extends AbstractHorizontalClassMappi } } - @Override - protected void reviseOldRevision(IDBStoreAccessor accessor, CDOID id, CDOBranch branch, long timeStamp) + /** + * @author Eike Stepper + */ + private static final class ViewForImplicitReadLocks implements IView { - // do nothing - } + public boolean isClosed() + { + return false; + } - @Override - protected String getListXRefsWhere(QueryXRefsContext context) - { - if (CDORevision.UNSPECIFIED_DATE != context.getTimeStamp()) + public void close() { - throw new IllegalArgumentException("Non-audit mode does not support timestamp specification"); } - if (!context.getBranch().isMainBranch()) + @SuppressWarnings("rawtypes") + public Object getAdapter(Class adapter) { - throw new IllegalArgumentException("Non-audit mode does not support branch specification"); + return null; } - return ATTRIBUTES_REVISED + "=0"; + public CDORevision getRevision(CDOID id) + { + return null; + } + + public long getTimeStamp() + { + return CDOBranchPoint.UNSPECIFIED_DATE; + } + + public CDOBranch getBranch() + { + return null; + } + + public boolean isDurableView() + { + return false; + } + + public int getSessionID() + { + return -1; + } + + public CDOCommonView.Options options() + { + return null; + } + + public boolean isReadOnly() + { + return true; + } + + public int getViewID() + { + return -1; + } + + public String getDurableLockingID() + { + return null; + } + + public ISession getSession() + { + return null; + } + + public IRepository getRepository() + { + return null; + } } } 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 9724f53eee..24bc772240 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 @@ -13,7 +13,6 @@ package org.eclipse.emf.cdo.server.internal.db.mapping.horizontal; import org.eclipse.emf.cdo.common.branch.CDOBranch; -import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; import org.eclipse.emf.cdo.common.id.CDOID; import org.eclipse.emf.cdo.common.revision.CDORevision; import org.eclipse.emf.cdo.common.revision.delta.CDOAddFeatureDelta; @@ -31,7 +30,6 @@ import org.eclipse.emf.cdo.server.db.IIDHandler; import org.eclipse.emf.cdo.server.db.mapping.IListMappingDeltaSupport; import org.eclipse.emf.cdo.server.db.mapping.IMappingStrategy; import org.eclipse.emf.cdo.server.internal.db.bundle.OM; -import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; import org.eclipse.net4j.db.DBException; import org.eclipse.net4j.db.DBUtil; @@ -282,27 +280,16 @@ public class NonAuditListTableMapping extends AbstractListTableMapping implement public void processDelta(final IDBStoreAccessor accessor, final CDOID id, int branchId, int oldVersion, final int newVersion, long created, CDOListFeatureDelta delta) { - CDOBranchPoint main = accessor.getStore().getRepository().getBranchManager().getMainBranch().getHead(); - - int xxx; - InternalCDORevision originalRevision = (InternalCDORevision)accessor.getStore().getRepository() - .getRevisionManager().getRevision(id, main, CDORevision.UNCHUNKED, CDORevision.DEPTH_NONE, true); - int oldListSize = originalRevision.getList(getFeature()).size(); + int oldListSize = delta.getOriginSize(); if (TRACER.isEnabled()) { - TRACER.format("ListTableMapping.processDelta for revision {0} - previous list size: {1}", originalRevision, //$NON-NLS-1$ + TRACER.format("ListTableMapping.processDelta for object {0} - original list size: {1}", id, //$NON-NLS-1$ oldListSize); } // let the visitor collect the changes ListDeltaVisitor visitor = new ListDeltaVisitor(oldListSize); - - if (TRACER.isEnabled()) - { - TRACER.trace("Processing deltas..."); //$NON-NLS-1$ - } - for (CDOFeatureDelta listDelta : delta.getListChanges()) { listDelta.accept(visitor); @@ -312,6 +299,8 @@ public class NonAuditListTableMapping extends AbstractListTableMapping implement // finally, write results to the database visitor.writeResultToDatabase(accessor, id); + + throw new NewListSizeResult(visitor.getNewListSize()); } private void close(PreparedStatement... stmts) @@ -360,6 +349,26 @@ public class NonAuditListTableMapping extends AbstractListTableMapping implement /** * @author Eike Stepper */ + static final class NewListSizeResult extends RuntimeException + { + private static final long serialVersionUID = 1L; + + private final int newListSize; + + public NewListSizeResult(int newListSize) + { + this.newListSize = newListSize; + } + + public int getNewListSize() + { + return newListSize; + } + } + + /** + * @author Eike Stepper + */ private final class ListDeltaVisitor implements CDOFeatureDeltaVisitor { private boolean clearFirst; @@ -372,6 +381,8 @@ public class NonAuditListTableMapping extends AbstractListTableMapping implement */ private int tempIndex = -1; + private int newListSize; + public ListDeltaVisitor(int oldListSize) { // reset the clear-flag @@ -383,6 +394,13 @@ public class NonAuditListTableMapping extends AbstractListTableMapping implement { manipulations.add(ManipulationElement.createOriginalElement(i)); } + + newListSize = oldListSize; + } + + public int getNewListSize() + { + return newListSize; } public void visit(CDOAddFeatureDelta delta) @@ -397,6 +415,7 @@ public class NonAuditListTableMapping extends AbstractListTableMapping implement // create the item manipulations.add(ManipulationElement.createInsertedElement(delta.getIndex(), delta.getValue())); + ++newListSize; } public void visit(CDORemoveFeatureDelta delta) @@ -411,6 +430,7 @@ public class NonAuditListTableMapping extends AbstractListTableMapping implement // fill the gap by shifting all subsequent items down shiftIndexes(delta.getIndex() + 1, UNBOUNDED_SHIFT, -1); + --newListSize; } public void visit(CDOSetFeatureDelta delta) @@ -451,6 +471,7 @@ public class NonAuditListTableMapping extends AbstractListTableMapping implement // and also clear all manipulation items manipulations.clear(); + newListSize = 0; } public void visit(CDOClearFeatureDelta delta) @@ -465,6 +486,7 @@ public class NonAuditListTableMapping extends AbstractListTableMapping implement // and also clear all manipulation items manipulations.clear(); + newListSize = 0; } public void visit(CDOMoveFeatureDelta delta) @@ -601,7 +623,6 @@ public class NonAuditListTableMapping extends AbstractListTableMapping implement applyOffsetToSourceIndexes(offsetBefore); int offsetAfter; - if ((long)Math.abs(offsetBefore) + (long)manipulations.size() > Integer.MAX_VALUE) { // security belt for really huge collections or for collections that have been manipulated lots of times diff --git a/plugins/org.eclipse.emf.cdo.server/.settings/.api_filters b/plugins/org.eclipse.emf.cdo.server/.settings/.api_filters index edf8cf60cc..439da2b9ef 100644 --- a/plugins/org.eclipse.emf.cdo.server/.settings/.api_filters +++ b/plugins/org.eclipse.emf.cdo.server/.settings/.api_filters @@ -42,6 +42,13 @@ </filter> <filter id="574660632"> <message_arguments> + <message_argument value="IView"/> + <message_argument value="CDOCommonView"/> + <message_argument value="Repository"/> + </message_arguments> + </filter> + <filter id="574660632"> + <message_arguments> <message_argument value="InternalRepository"/> <message_argument value="CDOCommonRepository"/> <message_argument value="Repository"/> @@ -88,30 +95,6 @@ </message_arguments> </filter> </resource> - <resource path="src/org/eclipse/emf/cdo/internal/server/TransactionCommitContext.java" type="org.eclipse.emf.cdo.internal.server.TransactionCommitContext$DeltaLockWrapper"> - <filter id="571473929"> - <message_arguments> - <message_argument value="AbstractCDOID"/> - <message_argument value="DeltaLockWrapper"/> - </message_arguments> - </filter> - </resource> - <resource path="src/org/eclipse/emf/cdo/internal/server/TransactionCommitContext.java" type="org.eclipse.emf.cdo.internal.server.TransactionCommitContext$DeltaLockWrapper$ForID"> - <filter id="574619656"> - <message_arguments> - <message_argument value="CDOID"/> - <message_argument value="ForID"/> - </message_arguments> - </filter> - </resource> - <resource path="src/org/eclipse/emf/cdo/internal/server/TransactionCommitContext.java" type="org.eclipse.emf.cdo.internal.server.TransactionCommitContext$DeltaLockWrapper$ForIDAndBranch"> - <filter id="574619656"> - <message_arguments> - <message_argument value="CDOIDAndBranch"/> - <message_argument value="ForIDAndBranch"/> - </message_arguments> - </filter> - </resource> <resource path="src/org/eclipse/emf/cdo/internal/server/TransactionCommitContext.java" type="org.eclipse.emf.cdo.internal.server.TransactionCommitContext$XRefContext"> <filter id="572522506"> <message_arguments> 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 7589ec06ef..e7c65f817a 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 @@ -42,6 +42,8 @@ import org.eclipse.emf.cdo.common.revision.CDORevisionFactory; import org.eclipse.emf.cdo.common.revision.CDORevisionHandler; import org.eclipse.emf.cdo.common.revision.CDORevisionKey; import org.eclipse.emf.cdo.common.revision.CDORevisionUtil; +import org.eclipse.emf.cdo.common.revision.delta.CDOContainerFeatureDelta; +import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta; import org.eclipse.emf.cdo.common.util.CDOCommonUtil; import org.eclipse.emf.cdo.common.util.CDOQueryInfo; import org.eclipse.emf.cdo.common.util.RepositoryStateChangedEvent; @@ -74,6 +76,7 @@ import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageUnit; import org.eclipse.emf.cdo.spi.common.revision.DetachedCDORevision; import org.eclipse.emf.cdo.spi.common.revision.InternalCDOList; import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; +import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionDelta; import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager; import org.eclipse.emf.cdo.spi.common.revision.PointerCDORevision; import org.eclipse.emf.cdo.spi.common.revision.RevisionInfo; @@ -482,7 +485,7 @@ public class Repository extends Container<Object> implements InternalRepository } IStoreAccessor accessor = StoreThreadLocal.getAccessor(); - InternalCDORevision revision = accessor.readRevision(id, branchPoint, referenceChunk, revisionManager); + InternalCDORevision revision = loadRevision(id, branchPoint, referenceChunk, accessor); if (revision == null) { if (isSupportingAudits()) @@ -539,7 +542,7 @@ public class Repository extends Container<Object> implements InternalRepository branchPoint = branch.getBase(); branch = branchPoint.getBranch(); - InternalCDORevision revision = accessor.readRevision(id, branchPoint, referenceChunk, revisionManager); + InternalCDORevision revision = loadRevision(id, branchPoint, referenceChunk, accessor); if (revision != null) { revision.freeze(); @@ -550,6 +553,12 @@ public class Repository extends Container<Object> implements InternalRepository return null; } + private InternalCDORevision loadRevision(CDOID id, CDOBranchPoint branchPoint, int referenceChunk, + IStoreAccessor accessor) + { + return accessor.readRevision(id, branchPoint, referenceChunk, revisionManager); + } + private long loadRevisionRevised(CDOID id, CDOBranch branch) { InternalCDORevision revision = loadRevisionByVersion(id, branch.getVersion(CDORevision.FIRST_VERSION), @@ -564,6 +573,11 @@ public class Repository extends Container<Object> implements InternalRepository public InternalCDORevision loadRevisionByVersion(CDOID id, CDOBranchVersion branchVersion, int referenceChunk) { + if (!supportingAudits) + { + throw new IllegalStateException("Auditing is not supported"); + } + IStoreAccessor accessor = StoreThreadLocal.getAccessor(); return accessor.readRevisionByVersion(id, branchVersion, referenceChunk, revisionManager); } @@ -891,7 +905,7 @@ public class Repository extends Container<Object> implements InternalRepository public void commit(InternalCommitContext commitContext, OMMonitor monitor) { - if (serializingCommits) + if (serializingCommits || includesMovesToOtherObjects(commitContext)) { synchronized (commitTransactionLock) { @@ -904,6 +918,23 @@ public class Repository extends Container<Object> implements InternalRepository } } + private boolean includesMovesToOtherObjects(InternalCommitContext commitContext) + { + for (InternalCDORevisionDelta delta : commitContext.getDirtyObjectDeltas()) + { + for (CDOFeatureDelta featureDelta : delta.getFeatureDeltas()) + { + EStructuralFeature feature = featureDelta.getFeature(); + if (feature == CDOContainerFeatureDelta.CONTAINER_FEATURE) + { + return true; + } + } + } + + return false; + } + protected void commitUnsynced(InternalCommitContext commitContext, OMMonitor monitor) { ProgressDistributor distributor = store.getIndicatingCommitDistributor(); diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/TransactionCommitContext.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/TransactionCommitContext.java index eaa346d28b..4387ccde51 100644 --- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/TransactionCommitContext.java +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/TransactionCommitContext.java @@ -28,15 +28,12 @@ import org.eclipse.emf.cdo.common.lock.CDOLockOwner; import org.eclipse.emf.cdo.common.lock.CDOLockState; import org.eclipse.emf.cdo.common.lock.CDOLockUtil; import org.eclipse.emf.cdo.common.model.CDOPackageUnit; -import org.eclipse.emf.cdo.common.protocol.CDODataOutput; import org.eclipse.emf.cdo.common.revision.CDOIDAndBranch; import org.eclipse.emf.cdo.common.revision.CDOIDAndVersion; import org.eclipse.emf.cdo.common.revision.CDORevision; import org.eclipse.emf.cdo.common.revision.CDORevisionKey; -import org.eclipse.emf.cdo.common.revision.CDORevisionUtil; import org.eclipse.emf.cdo.common.revision.delta.CDOAddFeatureDelta; import org.eclipse.emf.cdo.common.revision.delta.CDOContainerFeatureDelta; -import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta; import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDeltaVisitor; import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta; import org.eclipse.emf.cdo.common.revision.delta.CDOSetFeatureDelta; @@ -47,13 +44,11 @@ import org.eclipse.emf.cdo.internal.common.commit.CDOCommitDataImpl; import org.eclipse.emf.cdo.internal.common.commit.FailureCommitInfo; import org.eclipse.emf.cdo.internal.common.model.CDOPackageRegistryImpl; import org.eclipse.emf.cdo.internal.server.bundle.OM; -import org.eclipse.emf.cdo.server.ContainmentCycleDetectedException; import org.eclipse.emf.cdo.server.IStoreAccessor; import org.eclipse.emf.cdo.server.IStoreAccessor.QueryXRefsContext; import org.eclipse.emf.cdo.server.IView; import org.eclipse.emf.cdo.server.StoreThreadLocal; import org.eclipse.emf.cdo.spi.common.commit.InternalCDOCommitInfoManager; -import org.eclipse.emf.cdo.spi.common.id.AbstractCDOID; import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageInfo; import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry; import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageUnit; @@ -86,7 +81,6 @@ import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.EStructuralFeature; -import java.io.IOException; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; @@ -109,11 +103,17 @@ public class TransactionCommitContext implements InternalCommitContext private final InternalTransaction transaction; - private InternalRepository repository; + private final CDOBranch branch; - private InternalCDORevisionManager revisionManager; + private final InternalRepository repository; - private InternalLockManager lockManager; + private final InternalCDORevisionManager revisionManager; + + private final InternalLockManager lockManager; + + private final boolean serializingCommits; + + private final boolean ensuringReferentialIntegrity; private InternalCDOPackageRegistry repositoryPackageRegistry; @@ -171,10 +171,6 @@ public class TransactionCommitContext implements InternalCommitContext private boolean hasChanges; - private boolean serializingCommits; - - private boolean ensuringReferentialIntegrity; - private boolean autoReleaseLocksEnabled; private ExtendedDataInputStream lobs; @@ -183,6 +179,7 @@ public class TransactionCommitContext implements InternalCommitContext { this.transaction = transaction; + branch = transaction.getBranch(); repository = transaction.getRepository(); revisionManager = repository.getRevisionManager(); lockManager = repository.getLockingManager(); @@ -199,7 +196,7 @@ public class TransactionCommitContext implements InternalCommitContext public CDOBranchPoint getBranchPoint() { - return transaction.getBranch().getPoint(timeStamp); + return branch.getPoint(timeStamp); } public String getUserID() @@ -652,9 +649,9 @@ public class TransactionCommitContext implements InternalCommitContext } } - private void setTimeStamp(OMMonitor mmonitor) + private void setTimeStamp(OMMonitor monitor) { - long[] times = createTimeStamp(mmonitor); // Could throw an exception + long[] times = createTimeStamp(monitor); // Could throw an exception timeStamp = times[0]; previousTimeStamp = times[1]; CheckUtil.checkState(timeStamp != CDOBranchPoint.UNSPECIFIED_DATE, "Commit timestamp must not be 0"); @@ -715,7 +712,6 @@ public class TransactionCommitContext implements InternalCommitContext public CDOCommitInfo createCommitInfo() { - CDOBranch branch = transaction.getBranch(); String userID = transaction.getSession().getUserID(); CDOCommitData commitData = createCommitData(); @@ -788,7 +784,6 @@ public class TransactionCommitContext implements InternalCommitContext newPackageUnit.setTimeStamp(timeStamp); } - CDOBranch branch = transaction.getBranch(); for (InternalCDORevision newObject : newObjects) { newObject.adjustForCommit(branch, timeStamp); @@ -853,24 +848,8 @@ public class TransactionCommitContext implements InternalCommitContext { InternalCDORevisionDelta delta = dirtyObjectDeltas[i]; CDOID id = delta.getID(); - Object key = lockManager.getLockKey(id, transaction.getBranch()); - if (serializingCommits) - { - lockedObjects.add(key); - } - else - { - lockedObjects.add(createDeltaLockWrapper(key, delta)); - - if (hasContainmentChanges(delta)) - { - if (isContainerLocked(delta)) - { - throw new ContainmentCycleDetectedException("Parent (" + key - + ") is already locked for containment changes"); - } - } - } + Object key = lockManager.getLockKey(id, branch); + lockedObjects.add(key); } if (deltaTargetLocker != null) @@ -885,7 +864,7 @@ public class TransactionCommitContext implements InternalCommitContext for (int i = 0; i < detachedObjects.length; i++) { CDOID id = detachedObjects[i]; - Object key = lockManager.getLockKey(id, transaction.getBranch()); + Object key = lockManager.getLockKey(id, branch); lockedObjects.add(key); } @@ -893,7 +872,7 @@ public class TransactionCommitContext implements InternalCommitContext { // First lock all objects (incl. possible ref targets). // This is a transient operation, it does not check for existance! - lockManager.lock2(LockType.WRITE, transaction, lockedObjects, 1000); + lockManager.lock2(LockType.WRITE, transaction, lockedObjects, 10000); // If all locks could be acquired, check if locked targets do still exist if (lockedTargets != null) @@ -920,92 +899,6 @@ public class TransactionCommitContext implements InternalCommitContext } } - private DeltaLockWrapper createDeltaLockWrapper(Object key, InternalCDORevisionDelta delta) - { - if (key instanceof CDOID) - { - return new DeltaLockWrapper.ForID((CDOID)key, delta); - } - - if (key instanceof CDOIDAndBranch) - { - return new DeltaLockWrapper.ForIDAndBranch((CDOIDAndBranch)key, delta); - } - - throw new IllegalArgumentException("Invalid key: " + key); - } - - /** - * Iterates up the eContainers of an object and returns <code>true</code> on the first parent locked by another view. - * - * @return <code>true</code> if any parent is locked, <code>false</code> otherwise. - */ - private boolean isContainerLocked(InternalCDORevisionDelta delta) - { - CDOID id = delta.getID(); - InternalCDORevision revision = revisionManager.getRevisionByVersion(id, delta, CDORevision.UNCHUNKED, true); - if (revision == null) - { - // Can happen with non-auditing cache - throw new ConcurrentModificationException("Attempt by " + transaction + " to modify historical revision: " - + CDORevisionUtil.copyRevisionKey(delta)); - } - - return isContainerLocked(revision); - } - - private boolean isContainerLocked(InternalCDORevision revision) - { - CDOID id = (CDOID)revision.getContainerID(); - if (CDOIDUtil.isNull(id)) - { - return false; - } - - Object key = lockManager.getLockKey(id, transaction.getBranch()); - DeltaLockWrapper lockWrapper = createDeltaLockWrapper(key, null); - - if (lockManager.hasLockByOthers(LockType.WRITE, transaction, lockWrapper)) - { - Object object = lockManager.getLockEntryObject(lockWrapper); - if (object instanceof DeltaLockWrapper) - { - InternalCDORevisionDelta delta = ((DeltaLockWrapper)object).getDelta(); - if (delta != null && hasContainmentChanges(delta)) - { - return true; - } - } - } - - InternalCDORevision parent = revisionManager.getRevision(id, transaction, CDORevision.UNCHUNKED, - CDORevision.DEPTH_NONE, true); - - if (parent != null) - { - return isContainerLocked(parent); - } - - return false; - } - - private boolean hasContainmentChanges(InternalCDORevisionDelta delta) - { - for (CDOFeatureDelta featureDelta : delta.getFeatureDeltas()) - { - EStructuralFeature feature = featureDelta.getFeature(); - if (feature instanceof EReference) - { - if (((EReference)feature).isContainment()) - { - return true; - } - } - } - - return false; - } - private void lockTarget(Object value, Set<CDOID> newIDs, boolean supportingBranches) { if (value instanceof CDOIDObject) @@ -1028,7 +921,7 @@ public class TransactionCommitContext implements InternalCommitContext } // Let this object be locked - Object key = lockManager.getLockKey(id, transaction.getBranch()); + Object key = lockManager.getLockKey(id, branch); lockedObjects.add(key); // Let this object be checked for existance after it has been locked @@ -1071,7 +964,7 @@ public class TransactionCommitContext implements InternalCommitContext List<CDOIDAndBranch> keys = new ArrayList<CDOIDAndBranch>(detachedObjects.length); for (CDOID id : detachedObjects) { - CDOIDAndBranch idAndBranch = CDOIDUtil.createIDAndBranch(id, transaction.getBranch()); + CDOIDAndBranch idAndBranch = CDOIDUtil.createIDAndBranch(id, branch); keys.add(idAndBranch); } @@ -1088,6 +981,8 @@ public class TransactionCommitContext implements InternalCommitContext private void computeDirtyObjects(OMMonitor monitor) { + COMPUTING_DIRTY_OBJECTS.set(Boolean.TRUE); + try { monitor.begin(dirtyObjectDeltas.length); @@ -1109,29 +1004,28 @@ public class TransactionCommitContext implements InternalCommitContext } finally { + COMPUTING_DIRTY_OBJECTS.remove(); monitor.done(); } } private InternalCDORevision computeDirtyObject(InternalCDORevisionDelta delta) { - CDOBranch branch = transaction.getBranch(); - CDOID id = delta.getID(); - InternalCDORevision oldRevision = null; try { - oldRevision = revisionManager.getRevisionByVersion(id, delta, CDORevision.UNCHUNKED, true); + CDOID id = delta.getID(); + oldRevision = revisionManager.getRevision(id, transaction, CDORevision.UNCHUNKED, CDORevision.DEPTH_NONE, true); if (oldRevision != null) { - if (oldRevision.getBranch() == branch && oldRevision.isHistorical()) + if (oldRevision.getBranch() != delta.getBranch() || oldRevision.getVersion() != delta.getVersion()) { oldRevision = null; } } } - catch (Exception ex) + catch (RuntimeException ex) { OM.LOG.error(ex); oldRevision = null; @@ -1187,8 +1081,8 @@ public class TransactionCommitContext implements InternalCommitContext { rollbackMessage = message; + int CheckRollback; removePackageAdapters(); - unlockObjects(); if (accessor != null) { @@ -1205,6 +1099,8 @@ public class TransactionCommitContext implements InternalCommitContext repository.failCommit(timeStamp); } } + + unlockObjects(); } } @@ -1302,12 +1198,10 @@ public class TransactionCommitContext implements InternalCommitContext CDOLockState[] newStates = Repository.toCDOLockStates(newLockStates); long timeStamp = getTimeStamp(); - InternalTransaction tx = getTransaction(); - CDOBranch branch = tx.getBranch(); Operation unlock = Operation.UNLOCK; - CDOLockChangeInfo info = CDOLockUtil.createLockChangeInfo(timeStamp, tx, branch, unlock, null, newStates); - repository.getSessionManager().sendLockNotification(tx.getSession(), info); + CDOLockChangeInfo info = CDOLockUtil.createLockChangeInfo(timeStamp, transaction, branch, unlock, null, newStates); + repository.getSessionManager().sendLockNotification(transaction.getSession(), info); } private void addNewPackageUnits(OMMonitor monitor) @@ -1456,157 +1350,6 @@ public class TransactionCommitContext implements InternalCommitContext } /** - * @author Martin Fluegge - */ - private static abstract class DeltaLockWrapper extends AbstractCDOID - { - private static final long serialVersionUID = 1L; - - private Object key; - - private InternalCDORevisionDelta delta; - - public DeltaLockWrapper(Object key, InternalCDORevisionDelta delta) - { - this.key = key; - this.delta = delta; - } - - public Object getKey() - { - return key; - } - - public InternalCDORevisionDelta getDelta() - { - return delta; - } - - public abstract CDOID getID(); - - @Override - public void write(CDODataOutput out) throws IOException - { - ((AbstractCDOID)getID()).write(out); - } - - public String toURIFragment() - { - return getID().toURIFragment(); - } - - public Type getType() - { - return getID().getType(); - } - - public boolean isObject() - { - return getID().isObject(); - } - - public boolean isTemporary() - { - return getID().isTemporary(); - } - - public boolean isExternal() - { - return getID().isExternal(); - } - - @Override - protected int doCompareTo(CDOID o) throws ClassCastException - { - return getID().compareTo(o); - } - - @Override - public boolean equals(Object obj) - { - if (obj instanceof DeltaLockWrapper) - { - DeltaLockWrapper wrapper = (DeltaLockWrapper)obj; - obj = wrapper.getKey(); - } - - if (key instanceof CDOID) - { - return key == obj; - } - - return key.equals(obj); - } - - @Override - public int hashCode() - { - return key.hashCode(); - } - - @Override - public String toString() - { - return key.toString(); - } - - /** - * @author Eike Stepper - */ - private static final class ForID extends DeltaLockWrapper - { - private static final long serialVersionUID = 1L; - - public ForID(CDOID key, InternalCDORevisionDelta delta) - { - super(key, delta); - } - - @Override - public CDOID getKey() - { - return (CDOID)super.getKey(); - } - - @Override - public CDOID getID() - { - return getKey(); - } - } - - /** - * @author Martin Fluegge - */ - private static final class ForIDAndBranch extends DeltaLockWrapper implements CDOIDAndBranch - { - private static final long serialVersionUID = 1L; - - public ForIDAndBranch(CDOIDAndBranch key, InternalCDORevisionDelta delta) - { - super(key, delta); - } - - @Override - public CDOIDAndBranch getKey() - { - return (CDOIDAndBranch)super.getKey(); - } - - @Override - public CDOID getID() - { - return getKey().getID(); - } - - public CDOBranch getBranch() - { - return getKey().getBranch(); - } - } - } - - /** * @author Eike Stepper */ private final class XRefContext implements QueryXRefsContext @@ -1675,7 +1418,7 @@ public class TransactionCommitContext implements InternalCommitContext public CDOBranch getBranch() { - return transaction.getBranch(); + return branch; } public Map<CDOID, EClass> getTargetObjects() diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalCommitContext.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalCommitContext.java index bff8a6220c..21e1bd4793 100644 --- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalCommitContext.java +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalCommitContext.java @@ -37,6 +37,11 @@ import java.util.Map; */ public interface InternalCommitContext extends IStoreAccessor.CommitContext { + /** + * @since 4.2 + */ + public static final ThreadLocal<Boolean> COMPUTING_DIRTY_OBJECTS = new ThreadLocal<Boolean>(); + @SuppressWarnings("unchecked") public static final ProgressDistributable<InternalCommitContext>[] OPS = ProgressDistributor.array( // new ProgressDistributable.Default<InternalCommitContext>() diff --git a/plugins/org.eclipse.emf.cdo.tests.db/src/org/eclipse/emf/cdo/tests/db/H2Config.java b/plugins/org.eclipse.emf.cdo.tests.db/src/org/eclipse/emf/cdo/tests/db/H2Config.java index 5f1948905d..d1d036460a 100644 --- a/plugins/org.eclipse.emf.cdo.tests.db/src/org/eclipse/emf/cdo/tests/db/H2Config.java +++ b/plugins/org.eclipse.emf.cdo.tests.db/src/org/eclipse/emf/cdo/tests/db/H2Config.java @@ -71,7 +71,9 @@ public class H2Config extends DBConfig H2Adapter.createSchema(defaultDataSource, repoName, !isRestarting()); JdbcDataSource dataSource = new JdbcDataSource(); - dataSource.setURL("jdbc:h2:" + reusableFolder.getAbsolutePath() + "/h2test;LOCK_MODE=1;SCHEMA=" + repoName); + // dataSource.setURL("jdbc:h2:" + reusableFolder.getAbsolutePath() + + // "/h2test;LOCK_TIMEOUT=10000;LOCK_MODE=1;SCHEMA=" + repoName); + dataSource.setURL("jdbc:h2:" + reusableFolder.getAbsolutePath() + "/h2test;LOCK_TIMEOUT=10000;SCHEMA=" + repoName); return dataSource; } diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/TransactionTest.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/TransactionTest.java index c0c6f0a968..16645b8825 100644 --- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/TransactionTest.java +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/TransactionTest.java @@ -62,55 +62,6 @@ public class TransactionTest extends AbstractCDOTest OMPlatform.INSTANCE.setDebugging(false); } - public void testWrongListSize() throws Exception - { - { - CDOSession session = openSession(); - CDOTransaction transaction = session.openTransaction(); - CDOResource resource = transaction.createResource(getResourcePath("/test1")); - resource.getContents().add(getModel1Factory().createCompany()); - transaction.commit(); - session.close(); - } - - for (int i = 0; i < 2; i++) - { - new Thread() - { - @Override - public void run() - { - CDOSession session = openSession(); - for (;;) - { - CDOTransaction transaction = session.openTransaction(); - - try - { - ((org.eclipse.emf.cdo.net4j.CDONet4jSession)session).options().setCommitTimeout(100000000); - CDOResource resource = transaction.getResource(getResourcePath("/test1")); - Company company = (Company)resource.getContents().get(0); - - Category category = getModel1Factory().createCategory(); - company.getCategories().add(category); - transaction.commit(); - } - catch (CommitException ex) - { - ex.printStackTrace(); - } - finally - { - transaction.close(); - } - } - } - }.start(); - } - - sleep(1000000000L); - } - public void testCommitAfterClose() throws Exception { CDOSession session = openSession(); diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_396743_Test.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_396743_Test.java new file mode 100644 index 0000000000..91994e052b --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_396743_Test.java @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2013 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.emf.cdo.tests.bugzilla; + +import org.eclipse.emf.cdo.common.revision.CDORevisionCache; +import org.eclipse.emf.cdo.common.revision.CDORevisionUtil; +import org.eclipse.emf.cdo.common.util.CDOCommonUtil; +import org.eclipse.emf.cdo.eresource.CDOResource; +import org.eclipse.emf.cdo.session.CDOSession; +import org.eclipse.emf.cdo.tests.AbstractCDOTest; +import org.eclipse.emf.cdo.tests.config.IConfig; +import org.eclipse.emf.cdo.tests.config.impl.ConfigTest.Skips; +import org.eclipse.emf.cdo.tests.config.impl.RepositoryConfig; +import org.eclipse.emf.cdo.tests.model1.Category; +import org.eclipse.emf.cdo.tests.model1.Company; +import org.eclipse.emf.cdo.transaction.CDOTransaction; + +import org.eclipse.net4j.util.lifecycle.LifecycleUtil; +import org.eclipse.net4j.util.om.OMPlatform; + +import org.eclipse.emf.common.util.EList; + +/** + * Bug 396743: [DB] List size column mismatching the row entries. + * + * @author Eike Stepper + */ +// This test tries to produce the problem until it occurs. Runs forever if the problem is fixed. +@Skips(IConfig.CAPABILITY_ALL) +public class Bugzilla_396743_Test extends AbstractCDOTest +{ + private static final boolean REUSE_TRANSACTIONS = true; + + /** + * @author Eike Stepper + */ + private abstract class ClientThread extends Thread + { + private String indent; + + public ClientThread(int id) + { + super("TestClient-" + id); + indent = " " + .substring(0, id * 40); + } + + @Override + public void run() + { + try + { + CDOSession session = openSession(); + ((org.eclipse.emf.cdo.net4j.CDONet4jSession)session).options().setCommitTimeout(100000000); + + CDOTransaction transaction = null; + Company company = null; + + if (REUSE_TRANSACTIONS) + { + transaction = session.openTransaction(); + company = getCompany(transaction); + } + + while (!CDOCommonUtil.STOP_CLIENTS) + { + if (!REUSE_TRANSACTIONS) + { + transaction = session.openTransaction(); + company = getCompany(transaction); + } + + try + { + int count; + synchronized (transaction) + { + modifyModel(company); + transaction.commit(); + + count = company.getCategories().size(); + } + + println("Committed " + count); + sleep(3); // Give other threads a chance + } + catch (Exception ex) + { + String message = ex.getMessage(); + if (message.indexOf("Attempt by Transaction") != -1 + || message.indexOf("This transaction has conflicts") != -1) + { + println("FAILED"); + } + else + { + println(message); + ex.printStackTrace(); + } + + if (REUSE_TRANSACTIONS) + { + transaction.rollback(); + } + } + finally + { + if (!REUSE_TRANSACTIONS) + { + LifecycleUtil.deactivate(transaction); + transaction = null; + company = null; + } + } + } + + println("ENDE"); + } + catch (Throwable t) + { + t.printStackTrace(); + } + } + + private void println(String string) + { + // if (string.length() > 100) + // { + // string = string.substring(0, 99); + // } + + System.out.println(indent + string); + } + + private Company getCompany(CDOTransaction transaction) + { + CDOResource resource = transaction.getResource(getResourcePath("/test1")); + return (Company)resource.getContents().get(0); + } + + protected abstract void modifyModel(Company company); + } + + /** + * @author Eike Stepper + */ + private final class Adder extends ClientThread + { + public Adder(int id) + { + super(id); + } + + @Override + protected void modifyModel(Company company) + { + Category category = getModel1Factory().createCategory(); + company.getCategories().add(category); + } + } + + /** + * @author Eike Stepper + */ + private final class Deleter extends ClientThread + { + public Deleter(int id) + { + super(id); + } + + @Override + protected void modifyModel(Company company) + { + EList<Category> categories = company.getCategories(); + categories.remove(Math.random() * categories.size()); + } + } + + @Override + protected void doSetUp() throws Exception + { + super.doSetUp(); + OMPlatform.INSTANCE.setDebugging(false); + + getRepositoryConfig().getTestProperties().put(RepositoryConfig.PROP_TEST_REVISION_MANAGER, + CDORevisionUtil.createRevisionManager(CDORevisionCache.NOOP)); + + // new Thread("CC-Trigger") + // { + // @Override + // public void run() + // { + // ConcurrencyUtil.sleep(3000); + // + // for (;;) + // { + // ConcurrencyUtil.sleep(1000); + // + // try + // { + // clearCache(getRepository().getRevisionManager()); + // System.out.println("CACHE CLEARED"); + // } + // catch (Exception ex) + // { + // ex.printStackTrace(); + // } + // } + // } + // }.start(); + } + + public void testWrongListSizeAdditions() throws Exception + { + { + CDOSession session = openSession(); + CDOTransaction transaction = session.openTransaction(); + CDOResource resource = transaction.createResource(getResourcePath("/test1")); + resource.getContents().add(getModel1Factory().createCompany()); + transaction.commit(); + session.close(); + } + + Adder thread1 = new Adder(1); + Adder thread2 = new Adder(2); + + thread1.start(); + thread2.start(); + + thread1.join(); + thread2.join(); + } + + public void _testWrongListSizeAdditionsAndDeletions() throws Exception + { + { + CDOSession session = openSession(); + CDOTransaction transaction = session.openTransaction(); + CDOResource resource = transaction.createResource(getResourcePath("/test1")); + resource.getContents().add(getModel1Factory().createCompany()); + transaction.commit(); + session.close(); + } + + Adder thread1 = new Adder(1); + Adder thread2 = new Adder(2); + Deleter thread3 = new Deleter(3); + + thread1.start(); + thread2.start(); + thread3.start(); + + thread1.join(); + thread2.join(); + } +} diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/util/TestRevisionManager.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/util/TestRevisionManager.java index 0e0d6fa057..9290eeaaf4 100644 --- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/util/TestRevisionManager.java +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/util/TestRevisionManager.java @@ -19,7 +19,6 @@ import org.eclipse.emf.cdo.spi.common.revision.RevisionInfo; import org.eclipse.emf.cdo.spi.common.revision.SyntheticCDORevision; import org.eclipse.net4j.util.concurrent.ConcurrencyUtil; -import org.eclipse.net4j.util.event.IListener; import java.util.List; @@ -71,12 +70,6 @@ public class TestRevisionManager extends CDORevisionManagerImpl return super.getRevisions(ids, branchPoint, referenceChunk, prefetchDepth, loadOnDemand, synthetics); } - @Override - public void addListener(IListener listener) - { - super.addListener(listener); - } - public void resetLoadCounter() { synchronized (lock) diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOSessionImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOSessionImpl.java index 9e62b06751..b783e08b74 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOSessionImpl.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOSessionImpl.java @@ -1126,6 +1126,12 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl impleme context.terminate(); } } + + @Override + protected String getThreadName() + { + return "CDOSessionInvalidationRunner-" + CDOSessionImpl.this; + } }; invalidationRunner.activate(); diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOViewImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOViewImpl.java index 87be6c076f..0c47637346 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOViewImpl.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOViewImpl.java @@ -927,7 +927,7 @@ public class CDOViewImpl extends AbstractCDOView @Override protected String getThreadName() { - return "CDOInvalidationRunner-" + CDOViewImpl.this; //$NON-NLS-1$ + return "CDOViewInvalidationRunner-" + CDOViewImpl.this; //$NON-NLS-1$ } @Override diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/signal/SignalProtocol.java b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/signal/SignalProtocol.java index 285018e34b..967b7e54f4 100644 --- a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/signal/SignalProtocol.java +++ b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/signal/SignalProtocol.java @@ -252,6 +252,12 @@ public class SignalProtocol<INFRA_STRUCTURE> extends Protocol<INFRA_STRUCTURE> i @Override public String toString() { + IChannel channel = getChannel(); + if (channel != null) + { + return MessageFormat.format("SignalProtocol[{0}, {1}, {2}]", channel.getID(), channel.getLocation(), getType()); //$NON-NLS-1$ + } + return MessageFormat.format("SignalProtocol[{0}]", getType()); //$NON-NLS-1$ } |