use of org.apache.geode.cache.TransactionWriter in project geode by apache.
the class TXState method beforeCompletion.
//////////////////////////////////////////////////////////////////
// JTA Synchronization implementation //
//////////////////////////////////////////////////////////////////
/*
* (non-Javadoc)
*
* @see org.apache.geode.internal.cache.TXStateInterface#beforeCompletion()
*/
public void beforeCompletion() throws SynchronizationCommitConflictException {
if (this.closed) {
throw new TXManagerCancelledException();
}
this.proxy.getTxMgr().setTXState(null);
final long opStart = CachePerfStats.getStatTime();
this.jtaLifeTime = opStart - getBeginTime();
try {
reserveAndCheck();
/*
* If there is a TransactionWriter plugged in, we need to to give it an opportunity to abort
* the transaction.
*/
TransactionWriter writer = this.proxy.getTxMgr().getWriter();
if (writer != null) {
try {
// need to mark this so we don't fire again in commit
firedWriter = true;
TXEvent event = getEvent();
if (!event.hasOnlyInternalEvents()) {
writer.beforeCommit(event);
}
} catch (TransactionWriterException twe) {
cleanup();
throw new CommitConflictException(twe);
} catch (VirtualMachineError err) {
// cleanup(); this allocates objects so I don't think we can do it - that leaves the TX
// open, but we are poison pilling so we should be ok??
SystemFailure.initiateFailure(err);
// now, so don't let this thread continue.
throw err;
} catch (Throwable t) {
// rollback the transaction!
cleanup();
// Whenever you catch Error or Throwable, you must also
// catch VirtualMachineError (see above). However, there is
// _still_ a possibility that you are dealing with a cascading
// error condition, so you also need to check to see if the JVM
// is still usable:
SystemFailure.checkFailure();
throw new CommitConflictException(t);
}
}
} catch (CommitConflictException commitConflict) {
this.proxy.getTxMgr().noteCommitFailure(opStart, this.jtaLifeTime, this);
throw new SynchronizationCommitConflictException(LocalizedStrings.TXState_CONFLICT_DETECTED_IN_GEMFIRE_TRANSACTION_0.toLocalizedString(getTransactionId()), commitConflict);
}
}
use of org.apache.geode.cache.TransactionWriter in project geode by apache.
the class TXState method commit.
/*
* (non-Javadoc)
*
* @see org.apache.geode.internal.cache.TXStateInterface#commit()
*/
public void commit() throws CommitConflictException {
if (this.closed) {
return;
}
if (logger.isDebugEnabled()) {
logger.debug("committing transaction {}", getTransactionId());
}
synchronized (this.completionGuard) {
this.completionStarted = true;
}
if (onBehalfOfRemoteStub && !proxy.isCommitOnBehalfOfRemoteStub()) {
throw new UnsupportedOperationInTransactionException(LocalizedStrings.TXState_CANNOT_COMMIT_REMOTED_TRANSACTION.toLocalizedString());
}
cleanupNonDirtyRegions();
try {
/*
* Lock buckets so they can't be rebalanced then perform the conflict check to fix #43489
*/
try {
lockBucketRegions();
} catch (PrimaryBucketException pbe) {
// not sure what to do here yet
RuntimeException re = new TransactionDataRebalancedException(LocalizedStrings.PartitionedRegion_TRANSACTIONAL_DATA_MOVED_DUE_TO_REBALANCING.toLocalizedString());
re.initCause(pbe);
throw re;
}
if (this.locks == null) {
reserveAndCheck();
}
// For internal testing
if (this.internalAfterConflictCheck != null) {
this.internalAfterConflictCheck.run();
}
/*
* If there is a TransactionWriter plugged in, we need to to give it an opportunity to abort
* the transaction.
*/
TransactionWriter writer = this.proxy.getTxMgr().getWriter();
if (!firedWriter && writer != null) {
try {
firedWriter = true;
TXEvent event = getEvent();
if (!event.hasOnlyInternalEvents()) {
writer.beforeCommit(event);
}
} catch (TransactionWriterException twe) {
cleanup();
throw new CommitConflictException(twe);
} catch (VirtualMachineError err) {
// cleanup(); this allocates objects so I don't think we can do it - that leaves the TX
// open, but we are poison pilling so we should be ok??
SystemFailure.initiateFailure(err);
// now, so don't let this thread continue.
throw err;
} catch (Throwable t) {
// rollback the transaction!
cleanup();
// Whenever you catch Error or Throwable, you must also
// catch VirtualMachineError (see above). However, there is
// _still_ a possibility that you are dealing with a cascading
// error condition, so you also need to check to see if the JVM
// is still usable:
SystemFailure.checkFailure();
throw new CommitConflictException(t);
}
}
List /* <TXEntryStateWithRegionAndKey> */
entries = generateEventOffsets();
TXCommitMessage msg = null;
try {
/*
* In order to preserve data consistency, we need to: 1. Modify the cache first
* (applyChanges) 2. Ask for advice on who to send to (buildMessage) 3. Send out to other
* members.
*
* If this is done out of order, we will have problems with GII, split brain, and HA. See
* bug #41187
*
* @gregp
*/
attachFilterProfileInformation(entries);
lockTXRegions(regions);
try {
// apply changes to the cache
applyChanges(entries);
// For internal testing
if (this.internalAfterApplyChanges != null) {
this.internalAfterApplyChanges.run();
}
// build and send the message
msg = buildMessage();
this.commitMessage = msg;
if (this.internalBeforeSend != null) {
this.internalBeforeSend.run();
}
msg.send(this.locks.getDistributedLockId());
// For internal testing
if (this.internalAfterSend != null) {
this.internalAfterSend.run();
}
firePendingCallbacks();
/*
* This is to prepare the commit message for the caller, make sure all events are in
* there.
*/
this.commitMessage = buildCompleteMessage();
} finally {
unlockTXRegions(regions);
}
} finally {
if (msg != null) {
msg.releaseViewVersions();
}
this.locks.releaseLocal();
// For internal testing
if (this.internalAfterReleaseLocalLocks != null) {
this.internalAfterReleaseLocalLocks.run();
}
}
} finally {
cleanup();
}
}
Aggregations