/* * 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: FactoryContactItem.java 2342 2006-03-30 13:06:17Z $ */ package com.arjuna.ats.internal.jts.recovery.contact; import java.util.Date; import com.arjuna.ArjunaOTS.ArjunaFactory; import com.arjuna.ArjunaOTS.ArjunaFactoryHelper; import com.arjuna.ats.arjuna.common.Uid; import com.arjuna.ats.arjuna.exceptions.ObjectStoreException; import com.arjuna.ats.arjuna.objectstore.RecoveryStore; import com.arjuna.ats.arjuna.objectstore.StoreManager; import com.arjuna.ats.arjuna.state.InputObjectState; import com.arjuna.ats.arjuna.state.OutputObjectState; import com.arjuna.ats.internal.jts.ORBManager; import com.arjuna.ats.jts.logging.jtsLogger; /** * Create a persistent entry in the ActionStore to allow the RecoveryManager to * know which ArjunaFactory is in which JVM. * * (relies on the fact (true for 2.1) that any ArjunaFactory can be used to * find the status of any transaction. * * Identifying uid is the processUid */ public class FactoryContactItem { private static final String _pseudoTypeName = "/Recovery/FactoryContact"; private static final int version = 1; private static FactoryContactItem _theSingularItem = null; private Date _creationTime = null; private Date _aliveTime = null; private Date _deadTime = null; // if this is null, the parent process is known to be deceased private ArjunaFactory _factory = null; private Uid _uid = null; /** * create the contact item for the factory in this address space * and persist it * * Used in the original transaction-initiating process */ static boolean createAndSave(ArjunaFactory factory) { if (_theSingularItem == null) { _theSingularItem = new FactoryContactItem(factory); return _theSingularItem.saveMe(); } else { // do it only once return true; } } /** * construct the item known by this uid from the ObjectStore (assuming * it is there - otherwise return null) * * Used in the RecoveryManager */ static FactoryContactItem recreate (Uid uid) { FactoryContactItem theItem = new FactoryContactItem(uid); if (theItem.restoreMe()) { return theItem; } else { return null; } } /* provide information for other classes (and ourselves) in this package */ static RecoveryStore getStore() { return StoreManager.getRecoveryStore(); } static String getTypeName() { return _pseudoTypeName; } /** * accessor */ ArjunaFactory getFactory() { return _factory; } /** * accessor */ Date getCreationTime() { return _creationTime; } /** * accessor - returns null if contact has not be successfully used * this run of RecoveryManager */ Date getAliveTime() { return _aliveTime; } /** * accessor - returns null if contact has not failed at some time in the * past (persists) */ Date getDeadTime() { return _deadTime; } /** * accessor */ Uid getUid() { return _uid; } /** * the address space this contact item points to has gone away */ void markAsDead() { // ignore if done previously if (_factory != null) { // the ior won't work any more, so forget it _factory = null; _deadTime = new Date(); saveMe(); } } /** * the address space this contact item points to has just been contacted * this information is NOT persisted */ void markAsAlive() { _aliveTime = new Date(); } /** * Constructor used in normal JBoss Transaction service application to * identify the (or an) ArjunaFactory in this process */ private FactoryContactItem(ArjunaFactory factory) { if (jtsLogger.logger.isDebugEnabled()) { jtsLogger.logger.debug("FactoryContactItem(factory)"); } // the Uid of this object is the Uid of the process that creates it by // this constructor. // full class name needed to disambiguate from java.text.Utility _uid = com.arjuna.ats.arjuna.utils.Utility.getProcessUid(); _factory = factory; _creationTime = new Date(); } /** * Constructor used in RecoveryManager to restore a contact item from the * the object store */ private FactoryContactItem(Uid uid) { _uid = new Uid(uid); } /** * Although FactoryContactItem is not derived from StateManager, this * method has the equivalent signature and purpose (but different access) */ private boolean save_state (OutputObjectState objstate) { // convert the information try { objstate.packInt(version); objstate.packLong(_creationTime.getTime()); if (_factory != null) { String iorAsString = ORBManager.getORB().orb().object_to_string(_factory); objstate.packString(iorAsString); } else { objstate.packString(""); objstate.packLong(_deadTime.getTime()); } return true; } catch (java.io.IOException ex) { jtsLogger.i18NLogger.warn_recovery_contact_FactoryContactItem_1(ex); } catch (Exception exp) { jtsLogger.i18NLogger.warn_recovery_contact_FactoryContactItem_1(exp); } return false; } /** * Although FactoryContactItem is not derived from StateManager, this * method has the equivalent signature and purpose (but different access) */ private boolean restore_state (InputObjectState objstate) { // convert the information try { int oldversion = objstate.unpackInt(); if (oldversion != version) { jtsLogger.i18NLogger.warn_recovery_contact_FactoryContactItem_2(); } long oldtime = objstate.unpackLong(); _creationTime = new Date(oldtime); String iorAsString = objstate.unpackString(); if (iorAsString.length() > 1) { org.omg.CORBA.Object corbject = ORBManager.getORB().orb().string_to_object(iorAsString); /**** org.omg.CORBA.Object corbject; if ( ORBManager.isInitialised() ) corbject = ORBManager.getORB().orb().string_to_object(iorAsString); else corbject = RecoveryORBManager.getORB().orb().string_to_object(iorAsString); ***/ _factory = ArjunaFactoryHelper.narrow(corbject); if (_factory == null) { jtsLogger.i18NLogger.warn_recovery_contact_FactoryContactItem_3(); } _deadTime = null; } else { _factory = null; oldtime = objstate.unpackLong(); _deadTime = new Date(oldtime); } _aliveTime = null; return true; } catch (java.io.IOException ex) { jtsLogger.i18NLogger.warn_recovery_contact_FactoryContactItem_4(ex); } catch (Exception exp) { jtsLogger.i18NLogger.warn_recovery_contact_FactoryContactItem_4(exp); } return false; } private boolean saveMe () { try { OutputObjectState objstate = new OutputObjectState(); if (save_state(objstate)) { getStore().write_committed(_uid, _pseudoTypeName, objstate); return true; } } catch (ObjectStoreException exo) { jtsLogger.i18NLogger.warn_recovery_contact_FactoryContactItem_1(exo); } return false; } private boolean restoreMe() { try { InputObjectState objstate = getStore().read_committed(_uid, _pseudoTypeName); if (objstate == null) // not in object store any more return false; if (restore_state(objstate)) { return true; } jtsLogger.i18NLogger.warn_recovery_contact_FactoryContactItem_5(); } catch (ObjectStoreException exo) { // this shouldn't happen, because we shouldn't be looking for a factory // that was never recorded jtsLogger.i18NLogger.warn_recovery_contact_FactoryContactItem_6(); } return false; } /* * Not used by recovery currently. */ private static boolean removeMe(Uid uid) { try { return getStore().remove_committed(uid, _pseudoTypeName); } catch (ObjectStoreException exo) { // this shouldn't happen, because we shouldn't be looking for a factory // that was never recorded jtsLogger.i18NLogger.warn_recovery_contact_FactoryContactItem_7(exo); } return false; } }