diff options
Diffstat (limited to 'org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/XATransactionCommitContext.java')
-rw-r--r-- | org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/XATransactionCommitContext.java | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/XATransactionCommitContext.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/XATransactionCommitContext.java new file mode 100644 index 0000000000..a3c23c0f8b --- /dev/null +++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/XATransactionCommitContext.java @@ -0,0 +1,185 @@ +/** + * Copyright (c) 2004 - 2011 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: + * Simon McDuff - initial API and implementation + * Eike Stepper - maintenance + */ +package org.eclipse.emf.cdo.internal.server; + +import org.eclipse.emf.cdo.internal.server.bundle.OM; +import org.eclipse.emf.cdo.server.StoreThreadLocal; +import org.eclipse.emf.cdo.spi.server.InternalRepository; +import org.eclipse.emf.cdo.spi.server.InternalTransaction; + +import org.eclipse.net4j.util.WrappedException; +import org.eclipse.net4j.util.concurrent.ConcurrentValue; +import org.eclipse.net4j.util.om.monitor.OMMonitor; +import org.eclipse.net4j.util.om.trace.ContextTracer; + +/** + * @author Simon McDuff + * @since 2.0 + */ +public class XATransactionCommitContext extends TransactionCommitContext +{ + private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG_TRANSACTION, XATransactionCommitContext.class); + + private ConcurrentValue<CommitState> state = new ConcurrentValue<CommitState>(CommitState.STARTING); + + public XATransactionCommitContext(InternalTransaction transaction) + { + super(transaction); + } + + public ConcurrentValue<CommitState> getState() + { + return state; + } + + @Override + public void preWrite() + { + super.preWrite(); + StoreThreadLocal.setAccessor(null); + } + + @Override + public void commit(OMMonitor monitor) + { + StoreThreadLocal.setAccessor(getAccessor()); + try + { + super.commit(monitor); + } + finally + { + StoreThreadLocal.setAccessor(null); + } + } + + @Override + public void write(OMMonitor monitor) + { + StoreThreadLocal.setAccessor(getAccessor()); + try + { + super.write(monitor); + } + finally + { + StoreThreadLocal.setAccessor(null); + } + } + + @Override + public void postCommit(boolean success) + { + StoreThreadLocal.setAccessor(getAccessor()); + InternalRepository repository = getTransaction().getRepository(); + repository.getCommitManager().remove(this); + super.postCommit(success); + } + + @Override + public synchronized void rollback(String message) + { + super.rollback(message); + + // Change the state to unblock call. + state.set(CommitState.ROLLED_BACK); + } + + /** + * Wait until another thread fills ID mapping for external objects. + */ + @Override + public void applyIDMappings(OMMonitor monitor) + { + if (TRACER.isEnabled()) + { + TRACER.format("Notify phase2 to fill ID mapping."); //$NON-NLS-1$ + } + + state.set(CommitState.APPLY_ID_MAPPING); + if (TRACER.isEnabled()) + { + TRACER.format("Waiting for phase2 to be completed before continueing."); //$NON-NLS-1$ + } + + try + { + state.acquire(PHASEAPPLYMAPPING_DONE); + } + catch (InterruptedException ex) + { + throw WrappedException.wrap(ex); + } + + if (TRACER.isEnabled()) + { + TRACER.format("Received signal to continue."); //$NON-NLS-1$ + } + + super.applyIDMappings(monitor); + } + + /** + * Object to test if the process is at ApplyIDMapping + */ + final public static Object PHASEAPPLYMAPPING = new Object() + { + @Override + public int hashCode() + { + return CommitState.APPLY_ID_MAPPING.hashCode(); + } + + @Override + public boolean equals(Object object) + { + if (object == CommitState.ROLLED_BACK) + { + throw new RuntimeException("RolledBack"); //$NON-NLS-1$ + } + + return CommitState.APPLY_ID_MAPPING == object; + } + }; + + /** + * Object to test if the process did applyIDMapping + */ + final public static Object PHASEAPPLYMAPPING_DONE = new Object() + { + @Override + public int hashCode() + { + return CommitState.APPLY_ID_MAPPING_DONE.hashCode(); + } + + @Override + public boolean equals(Object object) + { + if (object == CommitState.ROLLED_BACK) + { + throw new RuntimeException("RolledBack"); //$NON-NLS-1$ + } + + return CommitState.APPLY_ID_MAPPING_DONE == object; + } + }; + + /** + * @author Simon McDuff + * @since 2.0 + */ + public enum CommitState + { + STARTING, APPLY_ID_MAPPING, APPLY_ID_MAPPING_DONE, ROLLED_BACK + } +} |