/** * This method invoked rollback on the Resource that is passed as a parameter. * * <p>This procedure may be called as the main procedure of a new thread, which must be done for * remote Resource objects during resync to avoid the possibility of deadlock during resync. * * <p>It is called directly when the Resource is not a proxy. * * @param res The Resource to be rolled back. * @return * @see */ void rollbackOrphan(Resource res) { try { res.rollback(); } catch (Throwable exc) { // If the rollback raised a heuristic exception, it can // only be reported in a message as it will never reach // the Coordinator. if (exc instanceof HeuristicCommit || exc instanceof HeuristicMixed || exc instanceof HeuristicHazard) { _logger.log(Level.WARNING, "jts.heuristic_exception", exc.toString()); } else { } } // We must release the proxy now. res._release(); }
// same as replay_completion(res) : added for delegated recovery support public Status replay_completion(Resource res, String logPath) throws NotPrepared { if (_logger.isLoggable(Level.FINE)) { _logger.logp( Level.FINE, "RecoveryCoordinatorImpl", "replay_completion()", "replay_completion on Resource:" + res); } Status result = Status.StatusRolledBack; CoordinatorImpl coord = DelegatedRecoveryManager.getCoordinator(globalTID, logPath); if (coord != null) { try { result = coord.get_status(); } catch (SystemException exc) { } } switch (result.value()) { /* * If the transaction is still active, raise the NotPrepared * exception. The Coordinator must be marked rollback-only at * this point because we cannot allow the transaction to * complete if a participant has failed. */ case Status._StatusActive: case Status._StatusMarkedRollback: try { coord.rollback_only(); } catch (Throwable exc) { } throw new NotPrepared(); /* * If the transaction is prepared, the caller must wait for the * Coordinator to tell it what to do, so return an unknown status, and * do nothing. Note that if this Coordinator is sitting waiting for * its superior, this could take a int time. */ case Status._StatusPrepared: result = Status.StatusUnknown; break; /* * If the transaction has been committed, the caller will receive * a commit. * * GDH If the transaction is commiting then we pass this on * to the caller. This state (added in OTS 1.1 means that * TopCoordinator.recover must now accept the COMMITTING state. */ case Status._StatusCommitting: // MODIFICATION (Ram Jeyaraman) commented out the code below, // since a StatusCommitting will be upgraded to Committed in // the subordinate. /* // (Ram Jeyaraman) let the subordinate wait, and allow the root // finish driving the commit. result = Status.StatusUnknown; */ break; case Status._StatusCommitted: break; case Status._StatusRolledBack: // If the transaction has been rolled back, and there is // no Coordinator for the transaction, we must invoke rollback // directly, as it will not be done otherwise. However for // proxies, this rollback cannot be done from this thread as // it would cause deadlock in the server requesting resync. if (coord == null) { if (!Configuration.getProxyChecker().isProxy(res)) { rollbackOrphan(res); } else { // We must pass a duplicate of the proxy to the // rollback thread because this proxy will be destroyed // when the replay_completion request returns // to the remote server. try { OrphanRollbackThread rollbackThread = new OrphanRollbackThread(this, (Resource) res._duplicate()); rollbackThread.start(); } catch (SystemException exc) { } } } break; /* * In any other situation, assume that the transaction has been rolled * back. As there is a Coordinator, it will direct the Resource to roll * back. */ default: result = Status.StatusRolledBack; } return result; }