Package com.arjuna.ats.internal.jts.recovery.contact

Source Code of com.arjuna.ats.internal.jts.recovery.contact.StatusChecker

/*
* JBoss, Home of Professional Open Source
* Copyright 2006, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags.
* See the copyright.txt in the distribution for a full listing
* of individual contributors.
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA  02110-1301, USA.
*
* (C) 2005-2006,
* @author JBoss Inc.
*/
/*
* Copyright (C) 2001,
*
* Arjuna Solutions Limited,
* Newcastle upon Tyne,
* Tyne and Wear,
* UK.
*
* $Id: StatusChecker.java 2342 2006-03-30 13:06:17Z  $
*
*/

package com.arjuna.ats.internal.jts.recovery.contact;

import com.arjuna.ats.jts.logging.jtsLogger;
import com.arjuna.ats.arjuna.logging.FacilityCode;
import com.arjuna.common.util.logging.*;

import java.util.Hashtable;

import com.arjuna.ats.arjuna.common.*;
import com.arjuna.ats.arjuna.coordinator.*;

import com.arjuna.ArjunaOTS.*;

import com.arjuna.orbportability.orb.*;
import com.arjuna.orbportability.*;
import com.arjuna.orbportability.OA;
import com.arjuna.orbportability.ORB;

import com.arjuna.ats.jts.utils.Utility;

import com.arjuna.ats.jts.OTSManager;



import org.omg.CosTransactions.*;
import org.omg.CORBA.NO_IMPLEMENT;
import org.omg.CORBA.OBJECT_NOT_EXIST;
import org.omg.CORBA.COMM_FAILURE;
import org.omg.CORBA.BAD_PARAM;
import org.omg.CORBA.TRANSIENT;
import org.omg.CORBA.SystemException;
import org.omg.CosTransactions.Inactive;

/**
* Checks the status of a transaction as known to the original process that
* created it - assuming the transaction still exists.
*
*
* (relies on the fact (true for 2.1) that any ArjunaFactory can be used to
* find the status of any transaction.
*
* Singleton class
*
*  @message com.arjuna.ats.internal.jts.recovery.contact.StatusChecker_1 [com.arjuna.ats.internal.jts.recovery.contact.StatusChecker_1] - StatusChecker.getStatus( {0} ) - current status = {1}
*  @message com.arjuna.ats.internal.jts.recovery.contact.StatusChecker_2 [com.arjuna.ats.internal.jts.recovery.contact.StatusChecker_2] - StatusChecker.getStatus( {0} ) - stored status = {1}
*  @message com.arjuna.ats.internal.jts.recovery.contact.StatusChecker_3 [com.arjuna.ats.internal.jts.recovery.contact.StatusChecker_3] - StatusChecked.getStatus - found intentions list for apparently unknown transaction: {0}
*  @message com.arjuna.ats.internal.jts.recovery.contact.StatusChecker_4 [com.arjuna.ats.internal.jts.recovery.contact.StatusChecker_4] - StatusChecker.getStatus( {0} ) - Status = {1}
*  @message com.arjuna.ats.internal.jts.recovery.contact.StatusChecker_5 [com.arjuna.ats.internal.jts.recovery.contact.StatusChecker_5] - StatusChecker.getStatus({0}) - NO_IMPLEMENT = dead
*  @message com.arjuna.ats.internal.jts.recovery.contact.StatusChecker_6 [com.arjuna.ats.internal.jts.recovery.contact.StatusChecker_6] - StatusChecker.getStatus({0}) - TRANSIENT = dead
*  @message com.arjuna.ats.internal.jts.recovery.contact.StatusChecker_7 [com.arjuna.ats.internal.jts.recovery.contact.StatusChecker_7] - StatusChecker.getStatus({0}) - COMM_FAILURE = live
*  @message com.arjuna.ats.internal.jts.recovery.contact.StatusChecker_8 [com.arjuna.ats.internal.jts.recovery.contact.StatusChecker_8] - StatusChecker.getStatus({0}) - OBJECT_NOT_EXIST = dead
*  @message com.arjuna.ats.internal.jts.recovery.contact.StatusChecker_9 [com.arjuna.ats.internal.jts.recovery.contact.StatusChecker_9] - BAD_PARAM exception on trying to contact original process
*  @message com.arjuna.ats.internal.jts.recovery.contact.StatusChecker_10 [com.arjuna.ats.internal.jts.recovery.contact.StatusChecker_10] - NoTransaction exception on trying to contact original process
*  @message com.arjuna.ats.internal.jts.recovery.contact.StatusChecker_11 [com.arjuna.ats.internal.jts.recovery.contact.StatusChecker_11] - CORBA exception on trying to contact original process "
*  @message com.arjuna.ats.internal.jts.recovery.contact.StatusChecker_12 [com.arjuna.ats.internal.jts.recovery.contact.StatusChecker_12] - Exception on trying to contact original process
*  @message com.arjuna.ats.internal.jts.recovery.contact.StatusChecker_13 [com.arjuna.ats.internal.jts.recovery.contact.StatusChecker_13] - StatusChecker.getStatus({0}) -  no factory, process previously dead
*  @message com.arjuna.ats.internal.jts.recovery.contact.StatusChecker_14 [com.arjuna.ats.internal.jts.recovery.contact.StatusChecker_14] - no known contactitem for {0}
*  @message com.arjuna.ats.internal.jts.recovery.contact.StatusChecker_15 [com.arjuna.ats.internal.jts.recovery.contact.StatusChecker_15] - surprise item in StatusChecker list for {0}, {1}
*/

public class StatusChecker
{
  /* the interface of this class is intended to allow for possible
   * future extension to do statuschecking by other (non-corba) means
   *
   * On the other hand, there is some nasty interlinking between bits of this
   * class - some redesign into separate classes would make things easier to
   * follow.
   */
  
// lookup the relevant factory according to the uid of the FactoryContactItem
private Hashtable _itemFromUid;

private static StatusChecker _checker;

/**
* create a static singleton to do the work for the static methods
*/
static
{
    _checker = new StatusChecker();
}


/**
* get the status in the original process, given the uid of the contact
* item (which is the uid of the process)
*/
public static Status get_status(Uid transactionUid, Uid itemUid) throws Inactive
{
    if (jtsLogger.logger.isDebugEnabled())
    {
  jtsLogger.logger.debug(DebugLevel.FUNCTIONS, VisibilityLevel.VIS_PUBLIC,
             FacilityCode.FAC_CRASH_RECOVERY,
             "StatusChecker.get_status("+transactionUid+", "+itemUid+")");
    }

    return _checker.checkOriginalStatus(transactionUid, itemUid, true);
}

/**
* get the current status in the original process, given the uid of the contact
* item (which is the uid of the process). Note that this method is used by the
* GenericRecoveryCoordinator code only.
*/

public static Status get_current_status(Uid transactionUid, Uid itemUid) throws Inactive
{
    if (jtsLogger.logger.isDebugEnabled())
    {
  jtsLogger.logger.debug(DebugLevel.FUNCTIONS, VisibilityLevel.VIS_PUBLIC,
             FacilityCode.FAC_CRASH_RECOVERY,
             "StatusChecker.get_current_status("+transactionUid+", "+itemUid+")");
    }

    return _checker.checkOriginalStatus(transactionUid, itemUid, false);
}

/**
* why isn't this private
*/
public StatusChecker()
{
    _itemFromUid = new Hashtable();
}


/**
* Check the status of a transaction when the contact item uid is known.
* This method *must* only be called from replay_completion, since it
* relies upon this fact to differentiate between a committed or rolled back
* transaction in the event of finding no intentions list in the object
* store.
*
* @return the status of the transaction as known in the original process.
* @throws Inactive if the original process is no longer active.
*/

public Status checkOriginalStatus (Uid transactionUid, Uid itemUid, boolean checkTheObjectStore)
    throws Inactive
{
    if (jtsLogger.logger.isDebugEnabled())
    {
  jtsLogger.logger.debug(DebugLevel.FUNCTIONS, VisibilityLevel.VIS_PUBLIC,
             FacilityCode.FAC_CRASH_RECOVERY,
             "StatusChecker.checkOriginalStatus("+transactionUid+", "+itemUid+", "+checkTheObjectStore+")");
    }
   
    FactoryContactItem item = getItem(itemUid);

    if (item != null)
    {
  return getStatus(transactionUid, item, checkTheObjectStore);
    }
    else
    {
  // null item implies long-dead process
  throw new Inactive();
    }
}

/**
*  try to get the status from a factory and convert to our way.
*  factory must not be null
*  itemUid is the store id as in _itemFromUid
*/

private Status getStatus (Uid transactionUid, FactoryContactItem item, boolean checkTheObjectStore) throws Inactive
{
    if (jtsLogger.logger.isDebugEnabled())
    {
  jtsLogger.logger.debug(DebugLevel.FUNCTIONS, VisibilityLevel.VIS_PUBLIC,
             FacilityCode.FAC_CRASH_RECOVERY,
             "StatusChecker.getStatus("+transactionUid+", "+item+", "+checkTheObjectStore+")");
    }
   
    ArjunaFactory factory = item.getFactory();

    if (factory != null)
    {
  Status otsStatus = Status.StatusUnknown;
  boolean originalDead = false;

  try
  {
      otid_t otid = Utility.uidToOtid(transactionUid);

      otsStatus = factory.getCurrentStatus(otid);

      if (jtsLogger.loggerI18N.isDebugEnabled())
      {
    jtsLogger.loggerI18N.debug(DebugLevel.FUNCTIONS, VisibilityLevel.VIS_PUBLIC,
             FacilityCode.FAC_CRASH_RECOVERY,
             "com.arjuna.ats.internal.jts.recovery.contact.StatusChecker_1",
             new Object[]{transactionUid, Utility.stringStatus(otsStatus)});
      }

      /*
       * If the factory doesn't know about the transaction, then
       * check the object store for the intentions list. If not
       * present, then the transaction must have rolled back.
       * If present, then we don't know what's going on, since the
       * factory should still have a reference to the transaction!
       */

      if (otsStatus == Status.StatusNoTransaction)
      {
    otsStatus = factory.getStatus(otid);

    if (jtsLogger.loggerI18N.isDebugEnabled())
    {
        jtsLogger.loggerI18N.debug(DebugLevel.FUNCTIONS, VisibilityLevel.VIS_PUBLIC,
                 FacilityCode.FAC_CRASH_RECOVERY,
                 "com.arjuna.ats.internal.jts.recovery.contact.StatusChecker_2",
                 new Object[]{transactionUid, Utility.stringStatus(otsStatus)});
    }

    switch (otsStatus.value())
    {
    case Status._StatusNoTransaction:
        /*
         * A definitive NoTransaction means rolled back because of
         * presumed abort protocol.
         */

        //        return Status.StatusRolledBack;
        return otsStatus;
    case Status._StatusUnknown:
        return otsStatus;
    default:
        {
      /*
       * We got an answer! This probably means that the
       * factory has just finished with the transaction, but
       * the state hasn't been removed by the file system yet
       * - we don't sync the removal to improve performance.
       */

      jtsLogger.loggerI18N.warn("com.arjuna.ats.internal.jts.recovery.contact.StatusChecker_3", new Object[] {transactionUid});
       
      otsStatus = Status.StatusUnknown;
        }
        break;
    }
      }
    
      if (jtsLogger.loggerI18N.isDebugEnabled())
      {
    jtsLogger.loggerI18N.debug(DebugLevel.FUNCTIONS, VisibilityLevel.VIS_PUBLIC,
             FacilityCode.FAC_CRASH_RECOVERY,
             "com.arjuna.ats.internal.jts.recovery.contact.StatusChecker_4",
             new Object[]{transactionUid, Utility.stringStatus(otsStatus)});
      }
 
      item.markAsAlive();
  } catch ( NO_IMPLEMENT ex_noimp) {
      // the original application has died

      if (jtsLogger.loggerI18N.isDebugEnabled())
      {
    jtsLogger.loggerI18N.debug(DebugLevel.FUNCTIONS, VisibilityLevel.VIS_PUBLIC,
             FacilityCode.FAC_CRASH_RECOVERY,
             "com.arjuna.ats.internal.jts.recovery.contact.StatusChecker_5",
             new Object[]{transactionUid});
      }

      originalDead = true;

  // orbix seems to count unreachable as transient. Over infinite time, all
  // addresses are valid
  } catch ( TRANSIENT ex_trans) {

      if (ORBInfo.getOrbEnumValue() == ORBType.ORBIX2000 ||
    ORBInfo.getOrbEnumValue() == ORBType.JACORB)
      {
        // the original application has (probably) died
        if (jtsLogger.loggerI18N.isDebugEnabled())
      {
          jtsLogger.loggerI18N.debug(DebugLevel.FUNCTIONS, VisibilityLevel.VIS_PUBLIC,
                   FacilityCode.FAC_CRASH_RECOVERY,
                   "com.arjuna.ats.internal.jts.recovery.contact.StatusChecker_6",
                   new Object[]{transactionUid});
      }
        originalDead = true;
      }
     
  } catch ( COMM_FAILURE ex_comm) {
      /*
       * Probably the original application has died, but only just - do
       * not mark either way.
       */
      if (jtsLogger.loggerI18N.isDebugEnabled())
    {
        jtsLogger.loggerI18N.debug(DebugLevel.FUNCTIONS, VisibilityLevel.VIS_PUBLIC,
                 FacilityCode.FAC_CRASH_RECOVERY,
                 "com.arjuna.ats.internal.jts.recovery.contact.StatusChecker_7",
                 new Object[]{transactionUid});
    }
     
  } catch ( OBJECT_NOT_EXIST ex_noobj) {
      // the original process must have gone away, and another one
      // come up in the same place
      // (or, just possibly, the original closed the ots)
      originalDead = true;
      if (jtsLogger.loggerI18N.isDebugEnabled())
    {
        jtsLogger.loggerI18N.debug(DebugLevel.FUNCTIONS, VisibilityLevel.VIS_PUBLIC,
                 FacilityCode.FAC_CRASH_RECOVERY,
                 "com.arjuna.ats.internal.jts.recovery.contact.StatusChecker_8",
                 new Object[]{transactionUid});
    }
     
  } catch ( BAD_PARAM ex_badparam) {
      jtsLogger.loggerI18N.warn(" com.arjuna.ats.internal.jts.recovery.contact.StatusChecker_9");
      // the transactionUid is invalid !
  } catch ( NoTransaction ex_notran) {
      jtsLogger.loggerI18N.warn(" com.arjuna.ats.internal.jts.recovery.contact.StatusChecker_10");
      // the transactionUid is invalid !
      // no transaction
  } catch ( SystemException ex_corba ) {
      // why did this happen ?
      jtsLogger.loggerI18N.warn(" com.arjuna.ats.internal.jts.recovery.contact.StatusChecker_11", ex_corba);
  } catch ( Exception ex_other) {
      // this really shouldn't happen
      jtsLogger.loggerI18N.warn(" com.arjuna.ats.internal.jts.recovery.contact.StatusChecker_12", ex_other);
  }
   
  if (originalDead)
  {
      item.markAsDead();

      // use Inactive as an indication that the parent process
      // has gone
     
      throw new Inactive();
  }
  else
  {
      return otsStatus;
  }
    }
    else
    {
  // factory in item is null - process already dead
  if (jtsLogger.loggerI18N.isDebugEnabled())
  {
      jtsLogger.loggerI18N.debug(DebugLevel.FUNCTIONS, VisibilityLevel.VIS_PUBLIC,
               FacilityCode.FAC_CRASH_RECOVERY,
               "com.arjuna.ats.internal.jts.recovery.contact.StatusChecker_13",
               new Object[]{transactionUid});
  }

  /*
   * In which case we can use the current, in process local factory, to
   * look at the object store and get the status from that. At present
   * all factories can look at the entire object store on a machine, so
   * this will work. If a factory is limited to only a portion of the object
   * store then we may need to create an explicit factory that has "global"
   * knowledge.
   */

        if ( checkTheObjectStore )
        {
            try
            {
    Status s = OTSManager.factory().getStatus(transactionUid);

    /*
     * If the status is committing or rolling back from a dead
     * (local) process then we can direct recovery now.
     */

    if (s == Status.StatusCommitting)
        return Status.StatusCommitted;
    else
    {
        if (s == Status.StatusRollingBack)
      return Status.StatusRolledBack;
    }

    return s;
            }
            catch (NoTransaction e1)
            {
                return Status.StatusNoTransaction;
            }
            catch (SystemException e2)
            {
                return Status.StatusUnknown;
            }
        }
        else
        {
            throw new Inactive();
        }
    }
}


/**
* find the IOR for the ArjunaFactory whose FactoryContactItem was saved with
* this uid. It is possible this Uid was created after the last scan, so if
* it isn't in the hashtable, look for real directly.
*/
private FactoryContactItem getItem (Uid uid)
{
    FactoryContactItem theItem = null;
    theItem = getKnownItem(uid);
    if (theItem == null) {
  // not previously known - see if it exists now
  theItem = getNewItem(uid);

  if (theItem == null) {
     
      // if it's still null, either something has gone wrong
      // - how did it get in the recoverycoordkey when the
      //   factory was unknown
      // or it's very old and been fully deleted

      jtsLogger.loggerI18N.warn("com.arjuna.ats.internal.jts.recovery.contact.StatusChecker_14", new Object[]{uid});
      // treat as long-dead process - return null
  }
    }

    return theItem;
}

private FactoryContactItem getKnownItem(Uid uid)
{
    FactoryContactItem theItem = null;

    try {
  theItem = (FactoryContactItem) _itemFromUid.get(uid);
  return theItem;
    } catch (ClassCastException ex) {
  jtsLogger.loggerI18N.warn("com.arjuna.ats.internal.jts.recovery.contact.StatusChecker_15", new Object[]{uid, ex});
  return null;
    }
}

private FactoryContactItem getNewItem (Uid uid)
{
    FactoryContactItem item = FactoryContactItem.recreate(uid);
    if (item != null) {
  // enter in the uid hashtable
  _itemFromUid.put(uid,item);
    }
    return item;     
}


}
TOP

Related Classes of com.arjuna.ats.internal.jts.recovery.contact.StatusChecker

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.