All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.jts.CosTransactions.RecoveryCoordinatorImpl Maven / Gradle / Ivy

There is a newer version: 7.2024.1.Alpha1
Show newest version
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-2011 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */
// Portions Copyright [2018] [Payara Foundation]

//----------------------------------------------------------------------------
//
// Module:      RecoveryCoordinatorImpl.java
//
// Description: Transaction RecoveryCoordinator object implementation.
//
// Product:     com.sun.jts.CosTransactions
//
// Author:      Simon Holdsworth
//
// Date:        March, 1997
//
// Copyright (c):   1995-1997 IBM Corp.
//
//   The source code for this program is not published or otherwise divested
//   of its trade secrets, irrespective of what has been deposited with the
//   U.S. Copyright Office.
//
//   This software contains confidential and proprietary information of
//   IBM Corp.
//----------------------------------------------------------------------------

package com.sun.jts.CosTransactions;

import org.omg.CORBA.*;
import org.omg.PortableServer.*;
import org.omg.CosTransactions.*;
import com.sun.jts.trace.*;
import java.util.logging.Logger;
import java.util.logging.Level;
import com.sun.logging.LogDomains;
import com.sun.jts.utils.LogFormatter;

/**
 * The RecoveryCoordinatorImpl interface is our implementation of the standard
 * RecoveryCoordinator interface. It allows recoverable objects to drive the
 * recovery process in certain situations. Each instance of this class is
 * implicitly associated with a single resource registration, and may only be
 * used by that resource in that particular transaction for which it is
 * registered. An instance of this class should be accessed from only one
 * thread within a process.
 *
 * @version 0.02
 *
 * @author Simon Holdsworth, IBM Corporation
 *
 * @see
 */

//----------------------------------------------------------------------------
// CHANGE HISTORY
//
// Version By     Change Description
//   0.01  SAJH   Initial implementation.
//   0.02  GDH    Gordon Hutchison April 1998
//                Added in COMMITTING to replay_completion
//-----------------------------------------------------------------------------

class RecoveryCoordinatorImpl extends RecoveryCoordinatorPOA {

    private static boolean recoverable = false;
    private static POA poa = null;
    private RecoveryCoordinator thisRef = null;
    private int internalSeq = 0;
	/*
		Logger to log transaction messages
	*/
    static Logger _logger = LogDomains.getLogger(RecoveryCoordinatorImpl.class, LogDomains.TRANSACTION_LOGGER);
    GlobalTID globalTID = null;

	RecoveryCoordinatorImpl() {}

    /**
     * Sets up the RecoveryCoordinator with the global identifier.
     * 

* This is so that it can always find the Coordinator to inform it of the * requirement for recovery of the given Resource. *

* An internal sequence number is used to differentiate RecoveryCoordinator * objects used for the same Coordinator object within a process. This is * so that they each get a unique object identifier. * * @param globalTID The global transaction identifier. * @param sequence An internal sequence number to differentiate objects. * * @return * * @see */ RecoveryCoordinatorImpl(GlobalTID globalTID, int sequence) { this.globalTID = globalTID; internalSeq = sequence; // MODIFICATION (Ram Jeyaraman) comment out the code // below, as it does nothing. /* byte[] tidBytes = globalTID.toBytes(); byte[] id = new byte[tidBytes.length + 4]; System.arraycopy(tidBytes, 0, id, 4, tidBytes.length); id[0] = (byte) internalSeq; id[1] = (byte)(internalSeq >> 8); id[2] = (byte)(internalSeq >> 16); id[3] = (byte)(internalSeq >> 24); */ } /** * Informs the Transaction Service that the given Resource object has been * prepared but has not received a commit or rollback operation. *

* If the transaction outcome is unknown, the Resource object passed * on this operation will be called at some later time for * commit or rollback. * * @param res The Resource to be recovered. * * @return The state of the transaction. * * @exception NotPrepared The transaction for which the * RecoveryCoordinator was created has not prepared. * * @see */ public Status replay_completion(Resource res) 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 = RecoveryManager.getCoordinator(globalTID); 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 : if( coord != null) { 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; } // 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 : if ( coord != null ) { 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; } /** * This method invoked rollback on the Resource that is passed as a * parameter. *

* 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. * *

* 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(); } /** * Creates the RecoveryCoordinatorImpl with the given key. *

* This is done when the RecoveryCoordinator object is recreated after the * server has been restarted. *

* The first four bytes of the key are an internal sequence number used to * differentiate RecoveryCoordinator objects created in the * same process for the same transaction. *

* The rest of the key is the global transaction identifier. * * @param key The key for the object. * * @return * * @see */ RecoveryCoordinatorImpl(byte[] key) { // Get the global transaction identifier from the key. byte[] tidBytes = new byte[key.length - 4]; // BUGFIX (Ram Jeyaraman) changed the order of array copy. // previously, an source and destination array was wrong. //System.arraycopy(tidBytes, 0, key, 4, tidBytes.length); System.arraycopy(key, 4, tidBytes, 0, tidBytes.length); globalTID = new GlobalTID(tidBytes); // Ensure that recovery has completed so that // we can get the Coordinator. RecoveryManager.waitForRecovery(); // Leave other members at the default values. } /** * Returns the CORBA Object which represents this object. * * @param * * @return The CORBA object. * * @see */ synchronized final RecoveryCoordinator object() { if (thisRef == null) { if (poa == null) { poa = Configuration.getPOA("RecoveryCoordinator"/*#Frozen*/); recoverable = Configuration.isRecoverable(); } try { if (recoverable && globalTID != null) { // Create the object id from the global transaction // identifier and the internal sequence number. byte[] tidBytes = globalTID.toBytes(); byte[] id = new byte[tidBytes.length + 4]; System.arraycopy(tidBytes, 0, id, 4, tidBytes.length); id[0] = (byte) internalSeq; id[1] = (byte)(internalSeq >> 8); id[2] = (byte)(internalSeq >> 16); id[3] = (byte)(internalSeq >> 24); // Activate the object and create the reference. poa.activate_object_with_id(id, this); org.omg.CORBA.Object obj = poa.create_reference_with_id( id, RecoveryCoordinatorHelper.id()); thisRef = RecoveryCoordinatorHelper.narrow(obj); //thisRef = (RecoveryCoordinator) this; } else { poa.activate_object(this); org.omg.CORBA.Object obj = poa.servant_to_reference(this); thisRef = RecoveryCoordinatorHelper.narrow(obj); //thisRef = (RecoveryCoordinator)this; } } catch(Exception exc) { _logger.log(Level.SEVERE,"jts.create_recoverycoordinator_error"); String msg = LogFormatter.getLocalizedMessage(_logger, "jts.create_recoverycoordinator_error"); throw new org.omg.CORBA.INTERNAL(msg); } } return thisRef; } /** * Destroys the RecoveryCoordinatorImpl object. * * @param * * @return * * @see */ synchronized final void destroy() { try { if (poa != null && thisRef != null) { poa.deactivate_object(poa.reference_to_id(thisRef)); thisRef = null; } else { // BUGFIX(Ram J) It is possible that the // RecoveryCoordinator object was activated via the activation // daemon. In that case, there is no guarantee // that poa and thisRef are set to a meaningful value. // So, try to deactivate the RecoveryCoordinator object anyway. POA rcPoa = null; if (poa == null) { rcPoa = Configuration.getPOA("RecoveryCoordinator"/*#Frozen*/); } else { rcPoa = poa; } if (thisRef == null) { rcPoa.deactivate_object(rcPoa.servant_to_id(this)); } else { rcPoa.deactivate_object(rcPoa.reference_to_id(thisRef)); thisRef = null; } } } catch( Exception exc ) { _logger.log(Level.WARNING,"jts.object_destroy_error","RecoveryCoordinator"); } globalTID = null; internalSeq = 0; } } /** * This class is provided to allow a Resource to be rolled back by the * RecoveryCoordinator on a new thread. This is required for * Resource objects which are proxies because deadlock would occur * if the rollback was called from the same thread as the one on * which the replay_completion was executing. * * @version 0.01 * * @author Simon Holdsworth, IBM Corporation * * @see */ class OrphanRollbackThread extends Thread { Resource resource = null; RecoveryCoordinatorImpl recovery = null; /** * OrphanRollbackThread constructor. * * @param recovery * @param resource * * @return * * @see */ OrphanRollbackThread(RecoveryCoordinatorImpl recovery, Resource resource) { this.resource = resource; this.recovery = recovery; setName("JTS Orphan Rollback Thread"/*#Frozen*/); } /** * Calls the RecoveryCoordinator to rollback the Resource. * * @param * * @return * * @see */ public void run() { recovery.rollbackOrphan(resource); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy