From 7a5a8945e19a6d05f9c64beae5b7e6f55a295d87 Mon Sep 17 00:00:00 2001 From: Eike Stepper Date: Sat, 15 Sep 2007 06:37:55 +0000 Subject: [203511] Provide vetoable transaction hooks https://bugs.eclipse.org/bugs/show_bug.cgi?id=203511 --- .../src/org/eclipse/emf/cdo/CDOTransaction.java | 19 +++++ .../org/eclipse/emf/cdo/CDOTransactionHandler.java | 38 +++++++++ .../emf/internal/cdo/CDOTransactionImpl.java | 90 ++++++++++++++++------ .../cdo/protocol/CommitTransactionRequest.java | 30 ++++---- .../net4j/internal/util/event/Notifier.java | 3 + 5 files changed, 143 insertions(+), 37 deletions(-) create mode 100644 plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOTransactionHandler.java diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOTransaction.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOTransaction.java index ad068b0ea0..ac74b4d6a4 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOTransaction.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOTransaction.java @@ -11,12 +11,17 @@ package org.eclipse.emf.cdo; import org.eclipse.emf.cdo.eresource.CDOResource; +import org.eclipse.emf.cdo.protocol.CDOID; import org.eclipse.emf.cdo.protocol.model.CDOClass; +import org.eclipse.emf.cdo.protocol.model.CDOPackage; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.resource.ResourceSet; +import java.util.List; +import java.util.Map; + /** * @author Eike Stepper */ @@ -40,4 +45,18 @@ public interface CDOTransaction extends CDOView * @see CDOTransaction#rollback() */ public void rollback(); + + public void addHandler(CDOTransactionHandler handler); + + public void removeHandler(CDOTransactionHandler handler); + + public CDOTransactionHandler[] getHandlers(); + + public List getNewPackages(); + + public Map getNewResources(); + + public Map getNewObjects(); + + public Map getDirtyObjects(); } diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOTransactionHandler.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOTransactionHandler.java new file mode 100644 index 0000000000..8769fa518e --- /dev/null +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOTransactionHandler.java @@ -0,0 +1,38 @@ +/*************************************************************************** + * Copyright (c) 2004 - 2007 Eike Stepper, Germany. + * 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; + +/** + * @author Eike Stepper + */ +public interface CDOTransactionHandler +{ + /** + * Called by a CDOTransaction before an object is added. The implementor of this method is + * allowed to throw an unchecked exception that will propagate up to the operation that is about to add the object. + */ + public void addingObject(CDOTransaction transaction, CDOObject object); + + /** + * Called by a CDOTransaction before an object is modified. The implementor of this method is + * allowed to throw an unchecked exception that will propagate up to the operation that is about to modify the object. + *

+ * Note: This method will be called at most once per object until the associated transaction is committed. + */ + public void modifyingObject(CDOTransaction transaction, CDOObject object); + + /** + * Called by a CDOTransaction before it is being committed. The implementor of this method is + * allowed to throw an unchecked exception that will propagate up to the operation that is about to commit the + * transaction. + */ + public void committingTransaction(CDOTransaction transaction); +} diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOTransactionImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOTransactionImpl.java index ef26efc19b..03fb795b15 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOTransactionImpl.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOTransactionImpl.java @@ -10,13 +10,17 @@ **************************************************************************/ package org.eclipse.emf.internal.cdo; +import org.eclipse.emf.cdo.CDOObject; import org.eclipse.emf.cdo.CDOTransaction; import org.eclipse.emf.cdo.CDOTransactionCommittedEvent; import org.eclipse.emf.cdo.CDOTransactionDirtyEvent; +import org.eclipse.emf.cdo.CDOTransactionHandler; +import org.eclipse.emf.cdo.eresource.CDOResource; import org.eclipse.emf.cdo.eresource.impl.CDOResourceImpl; import org.eclipse.emf.cdo.internal.protocol.CDOIDImpl; import org.eclipse.emf.cdo.internal.protocol.model.CDOPackageImpl; import org.eclipse.emf.cdo.protocol.CDOID; +import org.eclipse.emf.cdo.protocol.model.CDOPackage; import org.eclipse.emf.cdo.protocol.util.TransportException; import org.eclipse.emf.ecore.EPackage; @@ -27,6 +31,7 @@ import org.eclipse.emf.internal.cdo.util.EMFPackageClosure; import org.eclipse.emf.internal.cdo.util.ModelUtil; import org.eclipse.net4j.IChannel; +import org.eclipse.net4j.internal.util.event.Notifier; import org.eclipse.net4j.internal.util.om.trace.ContextTracer; import org.eclipse.net4j.signal.IFailOverStrategy; import org.eclipse.net4j.util.ImplementationError; @@ -50,13 +55,18 @@ public class CDOTransactionImpl extends CDOViewImpl implements CDOTransaction private transient long nextTemporaryID = INITIAL_TEMPORARY_ID; - private List newPackages; + /** + * TODO Optimize by storing an array. See {@link Notifier}. + */ + private List handlers = new ArrayList(0); + + private List newPackages; - private Map newResources = new HashMap(); + private Map newResources = new HashMap(); - private Map newObjects = new HashMap(); + private Map newObjects = new HashMap(); - private Map dirtyObjects = new HashMap(); + private Map dirtyObjects = new HashMap(); private boolean dirty; @@ -71,28 +81,52 @@ public class CDOTransactionImpl extends CDOViewImpl implements CDOTransaction return Type.TRANSACTION; } + public void addHandler(CDOTransactionHandler handler) + { + synchronized (handlers) + { + handlers.add(handler); + } + } + + public void removeHandler(CDOTransactionHandler handler) + { + synchronized (handlers) + { + handlers.remove(handler); + } + } + + public CDOTransactionHandler[] getHandlers() + { + synchronized (handlers) + { + return handlers.toArray(new CDOTransactionHandler[handlers.size()]); + } + } + @Override public boolean isDirty() { return dirty; } - public List getNewPackages() + public List getNewPackages() { return newPackages; } - public Map getNewResources() + public Map getNewResources() { return newResources; } - public Map getNewObjects() + public Map getNewObjects() { return newObjects; } - public Map getDirtyObjects() + public Map getDirtyObjects() { return dirtyObjects; } @@ -115,6 +149,11 @@ public class CDOTransactionImpl extends CDOViewImpl implements CDOTransaction TRACER.trace("commit()"); } + for (CDOTransactionHandler handler : getHandlers()) + { + handler.committingTransaction(this); + } + try { CDOSessionImpl session = getSession(); @@ -138,9 +177,9 @@ public class CDOTransactionImpl extends CDOViewImpl implements CDOTransaction session.notifyInvalidation(result.getTimeStamp(), dirtyObjects.keySet(), this); } - for (CDOPackageImpl newPackage : newPackages) + for (CDOPackage newPackage : newPackages) { - newPackage.setPersistent(true); + ((CDOPackageImpl)newPackage).setPersistent(true); } newPackages = null; @@ -191,22 +230,22 @@ public class CDOTransactionImpl extends CDOViewImpl implements CDOTransaction public void registerNew(InternalCDOObject object) { - if (object instanceof CDOResourceImpl) + if (TRACER.isEnabled()) { - if (TRACER.isEnabled()) - { - TRACER.format("Registering new resource {0}", object); - } + TRACER.format("Registering new object {0}", object); + } + + for (CDOTransactionHandler handler : getHandlers()) + { + handler.addingObject(this, object); + } + if (object instanceof CDOResourceImpl) + { register(newResources, object); } else { - if (TRACER.isEnabled()) - { - TRACER.format("Registering new object {0}", object); - } - register(newObjects, object); } } @@ -218,6 +257,11 @@ public class CDOTransactionImpl extends CDOViewImpl implements CDOTransaction TRACER.format("Registering dirty object {0}", object); } + for (CDOTransactionHandler handler : getHandlers()) + { + handler.modifyingObject(this, object); + } + register(dirtyObjects, object); } @@ -237,10 +281,10 @@ public class CDOTransactionImpl extends CDOViewImpl implements CDOTransaction } } - private List analyzeNewPackages(CDOSessionImpl session) + private List analyzeNewPackages(CDOSessionImpl session) { Set ePackages = new HashSet(); - for (InternalCDOObject object : newObjects.values()) + for (CDOObject object : newObjects.values()) { ePackages.add(object.eClass().getEPackage()); } @@ -249,7 +293,7 @@ public class CDOTransactionImpl extends CDOViewImpl implements CDOTransaction ePackages = new EMFPackageClosure().calculate(ePackages); CDOSessionPackageManager packageManager = session.getPackageManager(); - List cdoPackages = new ArrayList(); + List cdoPackages = new ArrayList(); for (EPackage ePackage : ePackages) { CDOPackageImpl cdoPackage = ModelUtil.getCDOPackage(ePackage, packageManager); diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/protocol/CommitTransactionRequest.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/protocol/CommitTransactionRequest.java index 0e140d9fb0..3ce55f051c 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/protocol/CommitTransactionRequest.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/protocol/CommitTransactionRequest.java @@ -10,7 +10,8 @@ **************************************************************************/ package org.eclipse.emf.internal.cdo.protocol; -import org.eclipse.emf.cdo.eresource.impl.CDOResourceImpl; +import org.eclipse.emf.cdo.CDOObject; +import org.eclipse.emf.cdo.eresource.CDOResource; import org.eclipse.emf.cdo.internal.protocol.CDOIDImpl; import org.eclipse.emf.cdo.internal.protocol.CDOIDRangeImpl; import org.eclipse.emf.cdo.internal.protocol.model.CDOPackageImpl; @@ -18,17 +19,18 @@ import org.eclipse.emf.cdo.internal.protocol.revision.CDORevisionImpl; import org.eclipse.emf.cdo.protocol.CDOID; import org.eclipse.emf.cdo.protocol.CDOIDRange; import org.eclipse.emf.cdo.protocol.CDOProtocolConstants; +import org.eclipse.emf.cdo.protocol.model.CDOPackage; import org.eclipse.emf.cdo.protocol.revision.CDORevision; +import org.eclipse.emf.internal.cdo.CDOTransactionImpl; +import org.eclipse.emf.internal.cdo.InternalCDOObject; +import org.eclipse.emf.internal.cdo.bundle.OM; + import org.eclipse.net4j.IChannel; import org.eclipse.net4j.internal.util.om.trace.ContextTracer; import org.eclipse.net4j.util.io.ExtendedDataInputStream; import org.eclipse.net4j.util.io.ExtendedDataOutputStream; -import org.eclipse.emf.internal.cdo.CDOTransactionImpl; -import org.eclipse.emf.internal.cdo.InternalCDOObject; -import org.eclipse.emf.internal.cdo.bundle.OM; - import java.io.IOException; import java.util.Collection; import java.util.Iterator; @@ -67,22 +69,22 @@ public class CommitTransactionRequest extends CDOClientRequest newPackages = transaction.getNewPackages(); + List newPackages = transaction.getNewPackages(); if (PROTOCOL.isEnabled()) { PROTOCOL.format("Writing {0} new packages", newPackages.size()); } out.writeInt(newPackages.size()); - for (CDOPackageImpl newPackage : newPackages) + for (CDOPackage newPackage : newPackages) { - newPackage.write(out); + ((CDOPackageImpl)newPackage).write(out); } } private void writeNewResources(ExtendedDataOutputStream out) throws IOException { - Collection newResources = transaction.getNewResources().values(); + Collection newResources = transaction.getNewResources().values(); if (PROTOCOL.isEnabled()) { PROTOCOL.format("Writing {0} new resources", newResources.size()); @@ -93,7 +95,7 @@ public class CommitTransactionRequest extends CDOClientRequest newObjects = transaction.getNewObjects().values(); + Collection newObjects = transaction.getNewObjects().values(); if (PROTOCOL.isEnabled()) { PROTOCOL.format("Writing {0} new objects", newObjects.size()); @@ -104,7 +106,7 @@ public class CommitTransactionRequest extends CDOClientRequest dirtyObjects = transaction.getDirtyObjects().values(); + Collection dirtyObjects = transaction.getDirtyObjects().values(); if (PROTOCOL.isEnabled()) { PROTOCOL.format("Writing {0} dirty objects", dirtyObjects.size()); @@ -130,12 +132,12 @@ public class CommitTransactionRequest extends CDOClientRequest newPackages = transaction.getNewPackages(); - for (CDOPackageImpl newPackage : newPackages) + List newPackages = transaction.getNewPackages(); + for (CDOPackage newPackage : newPackages) { CDOIDRange oldRange = newPackage.getMetaIDRange(); CDOIDRange newRange = CDOIDRangeImpl.read(in); - newPackage.setMetaIDRange(newRange); + ((CDOPackageImpl)newPackage).setMetaIDRange(newRange); for (long i = 0; i < oldRange.getCount(); i++) { CDOID oldID = oldRange.get(i); diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/internal/util/event/Notifier.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/internal/util/event/Notifier.java index c6bb4fa188..1f43034c39 100644 --- a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/internal/util/event/Notifier.java +++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/internal/util/event/Notifier.java @@ -23,6 +23,9 @@ import java.util.List; */ public class Notifier implements INotifier.Introspection { + /** + * TODO Optimize by storing an array + */ private List listeners = new ArrayList(0); public Notifier() -- cgit v1.2.3