[federate-commits] Federate SVN: r36 - in trunk/federate-txn-jbossts/src/main/java/com/arjuna/ats/internal: arjuna and 1 other directories.
federate-commits at lists.jboss.org
federate-commits at lists.jboss.org
Mon Nov 24 17:05:39 EST 2008
Author: rareddy
Date: 2008-11-24 17:05:39 -0500 (Mon, 24 Nov 2008)
New Revision: 36
Added:
trunk/federate-txn-jbossts/src/main/java/com/arjuna/ats/internal/arjuna/
trunk/federate-txn-jbossts/src/main/java/com/arjuna/ats/internal/arjuna/recovery/
trunk/federate-txn-jbossts/src/main/java/com/arjuna/ats/internal/arjuna/recovery/PeriodicRecovery.java
Log:
FEDERATE-14: Overiding the JBossTM code to set the thread as daemon. Needs to be retracted once the "Jbosstm" project is upgraded to fixed version.
Added: trunk/federate-txn-jbossts/src/main/java/com/arjuna/ats/internal/arjuna/recovery/PeriodicRecovery.java
===================================================================
--- trunk/federate-txn-jbossts/src/main/java/com/arjuna/ats/internal/arjuna/recovery/PeriodicRecovery.java (rev 0)
+++ trunk/federate-txn-jbossts/src/main/java/com/arjuna/ats/internal/arjuna/recovery/PeriodicRecovery.java 2008-11-24 22:05:39 UTC (rev 36)
@@ -0,0 +1,647 @@
+/*
+ * 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) 1999-2001 by HP Bluestone Software, Inc. All rights Reserved.
+ *
+ * HP Arjuna Labs,
+ * Newcastle upon Tyne,
+ * Tyne and Wear,
+ * UK.
+ *
+ * $Id: PeriodicRecovery.java 2342 2006-03-30 13:06:17Z $
+ */
+
+package com.arjuna.ats.internal.arjuna.recovery;
+
+import java.lang.InterruptedException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Properties;
+import java.util.Vector;
+import java.net.*;
+import java.io.*;
+
+import com.arjuna.ats.arjuna.recovery.RecoveryModule;
+import com.arjuna.ats.arjuna.recovery.RecoveryEnvironment;
+import com.arjuna.ats.arjuna.common.arjPropertyManager;
+
+import com.arjuna.ats.arjuna.logging.FacilityCode;
+import com.arjuna.ats.arjuna.logging.tsLogger;
+
+import com.arjuna.common.util.logging.*;
+
+/**
+ * Threaded object to perform the periodic recovery. Instantiated in
+ * the RecoveryManager. The work is actually completed by the recovery
+ * modules. These modules are dynamically loaded. The modules to load
+ * are specified by properties beginning with "RecoveryExtension"
+ * <P>
+ * @author
+ * @version $Id: PeriodicRecovery.java 2342 2006-03-30 13:06:17Z $
+ *
+ * @message com.arjuna.ats.internal.arjuna.recovery.PeriodicRecovery_1 [com.arjuna.ats.internal.arjuna.recovery.PeriodicRecovery_1] - Attempt to load recovery module with null class name!
+ * @message com.arjuna.ats.internal.arjuna.recovery.PeriodicRecovery_2 [com.arjuna.ats.internal.arjuna.recovery.PeriodicRecovery_2] - Recovery module {0} does not conform to RecoveryModule interface
+ * @message com.arjuna.ats.internal.arjuna.recovery.PeriodicRecovery_3 [com.arjuna.ats.internal.arjuna.recovery.PeriodicRecovery_3] - Loading recovery module: {0}
+ * @message com.arjuna.ats.internal.arjuna.recovery.PeriodicRecovery_4 [com.arjuna.ats.internal.arjuna.recovery.PeriodicRecovery_4] - Loading recovery module: {0}
+ * @message com.arjuna.ats.internal.arjuna.recovery.PeriodicRecovery_5 [com.arjuna.ats.internal.arjuna.recovery.PeriodicRecovery_5] - Loading recovery module: could not find class {0}
+ * @message com.arjuna.ats.internal.arjuna.recovery.PeriodicRecovery_6 [com.arjuna.ats.internal.arjuna.recovery.PeriodicRecovery_6] - {0} has inappropriate value ( {1} )
+ * @message com.arjuna.ats.internal.arjuna.recovery.PeriodicRecovery_7 [com.arjuna.ats.internal.arjuna.recovery.PeriodicRecovery_7] - {0} has inappropriate value ( {1} )
+ * @message com.arjuna.ats.internal.arjuna.recovery.PeriodicRecovery_8 [com.arjuna.ats.internal.arjuna.recovery.PeriodicRecovery_8] - Invalid port specified {0}
+ * @message com.arjuna.ats.internal.arjuna.recovery.PeriodicRecovery_9 [com.arjuna.ats.internal.arjuna.recovery.PeriodicRecovery_9] - Could not create recovery listener {0}
+ * @message com.arjuna.ats.internal.arjuna.recovery.PeriodicRecovery_10 [com.arjuna.ats.internal.arjuna.recovery.PeriodicRecovery_10] - Ignoring request to scan because RecoveryManager state is: {0}
+ */
+
+public class PeriodicRecovery extends Thread
+{
+
+/*
+ * TODO uncomment for JDK 1.5.
+ *
+ public static enum State
+ {
+ created, active, terminated, suspended, scanning
+ }
+*/
+ public class State
+ {
+ public static final int created = 0;
+ public static final int active = 1;
+ public static final int terminated = 2;
+ public static final int suspended = 3;
+ public static final int scanning = 4;
+
+ private State () {}
+ }
+
+ public PeriodicRecovery (boolean threaded)
+ {
+ setDaemon(true);
+ initialise();
+
+ // Load the recovery modules that actually do the work.
+
+ loadModules();
+
+ try
+ {
+ _workerService = new WorkerService(this);
+
+ _listener = new Listener(getServerSocket(), _workerService);
+ _listener.setDaemon(true);
+ }
+ catch (Exception ex)
+ {
+ if (tsLogger.arjLoggerI18N.isWarnEnabled())
+ {
+ tsLogger.arjLoggerI18N.warn("com.arjuna.ats.internal.arjuna.recovery.PeriodicRecovery_9", new Object[]{ex});
+ }
+ }
+
+ if (threaded)
+ {
+ start();
+ }
+
+ _listener.start();
+ }
+
+ public int getStatus ()
+ {
+ synchronized (_stateLock)
+ {
+ return _currentState;
+ }
+ }
+
+ public void setStatus (int s)
+ {
+ synchronized (_stateLock)
+ {
+ _currentState = s;
+ }
+ }
+
+ public void shutdown ()
+ {
+ setStatus(State.terminated);
+
+ this.interrupt();
+ }
+
+ public void suspendScan (boolean async)
+ {
+ synchronized (_signal)
+ {
+ setStatus(State.suspended);
+
+ this.interrupt();
+
+ if (!async)
+ {
+ try
+ {
+ _signal.wait();
+ }
+ catch (InterruptedException ex)
+ {
+ }
+ }
+ }
+ }
+
+ public void resumeScan ()
+ {
+ /*
+ * If it's suspended, then it has to be blocked
+ * on the lock.
+ */
+
+ if (getStatus() == State.suspended)
+ {
+ setStatus(State.active);
+
+ synchronized (_suspendLock)
+ {
+ _suspendLock.notify();
+ }
+ }
+ }
+
+ /**
+ * Return the port specified by the property
+ * com.arjuna.ats.internal.arjuna.recovery.recoveryPort,
+ * otherwise return a default port.
+ */
+
+ public static final ServerSocket getServerSocket () throws IOException
+ {
+ if (_socket == null)
+ {
+ // TODO these properties should be documented!!
+
+ String tsmPortStr = arjPropertyManager.propertyManager.getProperty(com.arjuna.ats.arjuna.common.Environment.RECOVERY_MANAGER_PORT);
+ int port = 0;
+
+ if (tsmPortStr != null)
+ {
+ try
+ {
+ port = Integer.parseInt( tsmPortStr );
+ }
+ catch (Exception ex)
+ {
+ if (tsLogger.arjLoggerI18N.isWarnEnabled())
+ {
+ tsLogger.arjLoggerI18N.warn("com.arjuna.ats.internal.arjuna.recovery.PeriodicRecovery_8", new Object[]{ex});
+ }
+ }
+ }
+
+ _socket = new ServerSocket(port);
+ }
+
+ return _socket;
+ }
+
+ /**
+ * Start the background thread to perform the periodic recovery
+ */
+
+ public void run ()
+ {
+ boolean finished = false;
+
+ do
+ {
+ checkSuspended();
+
+ finished = doWork(true);
+
+ } while (!finished);
+ }
+
+ /**
+ * Perform the recovery scans on all registered modules.
+ *
+ * @param boolean periodic If <code>true</code> then this is being called
+ * as part of the normal periodic running of the manager and we'll sleep
+ * after phase 2 work. Otherwise, we're being called directly and there should
+ * be no sleep after phase 2.
+ *
+ * @return <code>true</code> if the manager has been instructed to finish,
+ * <code>false</code> otherwise.
+ */
+
+ public final synchronized boolean doWork (boolean periodic)
+ {
+ boolean interrupted = false;
+
+ /*
+ * If we're suspended or already scanning, then ignore.
+ */
+
+ synchronized (_stateLock)
+ {
+ if (getStatus() != State.active)
+ {
+ if (tsLogger.arjLoggerI18N.isInfoEnabled())
+ {
+ tsLogger.arjLoggerI18N.info("com.arjuna.ats.internal.arjuna.recovery.PeriodicRecovery_10", new Object[]{new Integer(getStatus())});
+ }
+
+ return false;
+ }
+
+ setStatus(State.scanning);
+ }
+
+ tsLogger.arjLogger.info("Periodic recovery - first pass <" +
+ _theTimestamper.format(new Date()) + ">" );
+
+ Enumeration modules = _recoveryModules.elements();
+
+ while (modules.hasMoreElements())
+ {
+ RecoveryModule m = (RecoveryModule) modules.nextElement();
+
+ m.periodicWorkFirstPass();
+
+ if (tsLogger.arjLogger.isDebugEnabled())
+ {
+ tsLogger.arjLogger.debug( DebugLevel.FUNCTIONS,
+ VisibilityLevel.VIS_PUBLIC,
+ FacilityCode.FAC_CRASH_RECOVERY,
+ " " );
+ }
+ }
+
+ if (interrupted)
+ {
+ interrupted = false;
+
+ _workerService.signalDone();
+ }
+
+ // wait for a bit to avoid catching (too many) transactions etc. that
+ // are really progressing quite happily
+
+ try
+ {
+ Thread.sleep( _backoffPeriod * 1000 );
+ }
+ catch ( InterruptedException ie )
+ {
+ interrupted = true;
+ }
+
+ if (getStatus() == State.terminated)
+ {
+ return true;
+ }
+ else
+ {
+ checkSuspended();
+
+ setStatus(State.scanning);
+ }
+
+ tsLogger.arjLogger.info("Periodic recovery - second pass <"+
+ _theTimestamper.format(new Date()) + ">" );
+
+ modules = _recoveryModules.elements();
+
+ while (modules.hasMoreElements())
+ {
+ RecoveryModule m = (RecoveryModule) modules.nextElement();
+
+ m.periodicWorkSecondPass();
+
+ if (tsLogger.arjLogger.isDebugEnabled())
+ {
+ tsLogger.arjLogger.debug ( DebugLevel.FUNCTIONS, VisibilityLevel.VIS_PUBLIC, FacilityCode.FAC_CRASH_RECOVERY, " " );
+ }
+ }
+
+ try
+ {
+ if (!interrupted && periodic)
+ Thread.sleep( _recoveryPeriod * 1000 );
+ }
+ catch ( InterruptedException ie )
+ {
+ interrupted = true;
+ }
+
+ if (getStatus() == State.terminated)
+ {
+ return true;
+ }
+ else
+ {
+ checkSuspended();
+
+ // make sure we're scanning again.
+
+ setStatus(State.active);
+ }
+
+ return false; // keep going
+ }
+
+ /**
+ * Add the specified module to the end of the recovery module list.
+ * There is no way to specify relative ordering of recovery modules
+ * with respect to modules loaded via the property file.
+ *
+ * @param RecoveryModule module The module to append.
+ */
+
+ public final void addModule (RecoveryModule module)
+ {
+ _recoveryModules.add(module);
+ }
+
+ /**
+ * @return the recovery modules.
+ */
+
+ public final Vector getModules ()
+ {
+ return _recoveryModules;
+ }
+
+ /**
+ * Load recovery modules prior to starting to recovery. The property
+ * name of each module is used to indicate relative ordering.
+ */
+
+ private final static void loadModules ()
+ {
+ // scan the relevant properties so as to get them into sort order
+ Properties properties = arjPropertyManager.propertyManager.getProperties();
+
+ if (properties != null)
+ {
+ Vector moduleNames = new Vector();
+ Enumeration names = properties.propertyNames();
+
+ while (names.hasMoreElements())
+ {
+ String attrName = (String) names.nextElement();
+
+ if (attrName.startsWith(RecoveryEnvironment.MODULE_PROPERTY_PREFIX))
+ {
+ // this is one of ours - put it in the right place
+ int position = 0;
+
+ while ( position < moduleNames.size() &&
+ attrName.compareTo( (String)moduleNames.elementAt(position)) > 0 )
+ {
+ position++;
+ }
+ moduleNames.add(position,attrName);
+ }
+ }
+ // now go through again and load them
+ names = moduleNames.elements();
+
+ while (names.hasMoreElements())
+ {
+ String attrName = (String) names.nextElement();
+
+ loadModule(properties.getProperty(attrName));
+ }
+ }
+ }
+
+ private final static void loadModule (String className)
+ {
+ if (tsLogger.arjLogger.isDebugEnabled())
+ {
+ tsLogger.arjLogger.debug( DebugLevel.FUNCTIONS,
+ VisibilityLevel.VIS_PRIVATE,
+ FacilityCode.FAC_CRASH_RECOVERY,
+ "Loading recovery module "+
+ className );
+ }
+
+ if (className == null)
+ {
+ if (tsLogger.arjLoggerI18N.isWarnEnabled())
+ tsLogger.arjLoggerI18N.warn("com.arjuna.ats.internal.arjuna.recovery.PeriodicRecovery_1");
+
+ return;
+ }
+ else
+ {
+ try
+ {
+ Class c = Thread.currentThread().getContextClassLoader().loadClass( className );
+
+ try
+ {
+ RecoveryModule m = (RecoveryModule) c.newInstance();
+ _recoveryModules.add(m);
+ }
+ catch (ClassCastException e)
+ {
+ if (tsLogger.arjLoggerI18N.isWarnEnabled())
+ {
+ tsLogger.arjLoggerI18N.warn("com.arjuna.ats.internal.arjuna.recovery.PeriodicRecovery_2",
+ new Object[]{className});
+ }
+ }
+ catch (IllegalAccessException iae)
+ {
+ if (tsLogger.arjLoggerI18N.isWarnEnabled())
+ {
+ tsLogger.arjLoggerI18N.warn("com.arjuna.ats.internal.arjuna.recovery.PeriodicRecovery_3",
+ new Object[]{iae});
+ }
+ }
+ catch (InstantiationException ie)
+ {
+ if (tsLogger.arjLoggerI18N.isWarnEnabled())
+ {
+ tsLogger.arjLoggerI18N.warn("com.arjuna.ats.internal.arjuna.recovery.PeriodicRecovery_4",
+ new Object[]{ie});
+ }
+ }
+
+ c = null;
+ }
+ catch ( ClassNotFoundException cnfe )
+ {
+ if (tsLogger.arjLoggerI18N.isWarnEnabled())
+ {
+ tsLogger.arjLoggerI18N.warn("com.arjuna.ats.internal.arjuna.recovery.PeriodicRecovery_5",
+ new Object[]{className});
+ }
+ }
+ }
+ }
+
+ private void checkSuspended ()
+ {
+ synchronized (_signal)
+ {
+ _signal.notify();
+ }
+
+ if (getStatus() == State.suspended)
+ {
+ while (getStatus() == State.suspended)
+ {
+ try
+ {
+ synchronized (_suspendLock)
+ {
+ _suspendLock.wait();
+ }
+ }
+ catch (InterruptedException ex)
+ {
+ }
+ }
+
+ setStatus(State.active);
+ }
+ }
+
+ private final void initialise ()
+ {
+ _recoveryModules = new Vector();
+ setStatus(State.active);
+ }
+
+ // this refers to the modules specified in the recovery manager
+ // property file which are dynamically loaded.
+ private static Vector _recoveryModules = null;
+
+ // back off period is the time between the first and second pass.
+ // recovery period is the time between the second pass and the start
+ // of the first pass.
+ private static int _backoffPeriod = 0;
+ private static int _recoveryPeriod = 0;
+
+ // default values for the above
+ private static final int _defaultBackoffPeriod = 10;
+ private static final int _defaultRecoveryPeriod = 120;
+
+ // exit thread flag
+ private static int _currentState = State.created;
+ private static Object _stateLock = new Object();
+
+ private static SimpleDateFormat _theTimestamper = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss");
+
+ private static ServerSocket _socket = null;
+
+ private static Listener _listener = null;
+ private static WorkerService _workerService = null;
+
+ private Object _suspendLock = new Object();
+ private Object _signal = new Object();
+
+ /*
+ * Read the system properties to set the configurable options
+ *
+ * Note: if we start and stop the service then changes to the timeouts
+ * won't be reflected. We will need to modify this eventually.
+ */
+
+ static
+ {
+ _recoveryPeriod = _defaultRecoveryPeriod;
+
+ String recoveryPeriodString =
+ arjPropertyManager.propertyManager.getProperty(com.arjuna.ats.arjuna.common.Environment.PERIODIC_RECOVERY_PERIOD );
+
+ if ( recoveryPeriodString != null )
+ {
+ try
+ {
+ Integer recoveryPeriodInteger = new Integer( recoveryPeriodString );
+ _recoveryPeriod = recoveryPeriodInteger.intValue();
+
+ if (tsLogger.arjLogger.isDebugEnabled())
+ {
+ tsLogger.arjLogger.debug
+ ( DebugLevel.FUNCTIONS,
+ VisibilityLevel.VIS_PRIVATE,
+ FacilityCode.FAC_CRASH_RECOVERY,
+ "com.arjuna.ats.arjuna.recovery.PeriodicRecovery" +
+ ": Recovery period set to " + _recoveryPeriod + " seconds" );
+ }
+ }
+ catch (NumberFormatException e)
+ {
+ if (tsLogger.arjLoggerI18N.isWarnEnabled())
+ {
+ tsLogger.arjLoggerI18N.warn("com.arjuna.ats.internal.arjuna.recovery.PeriodicRecovery_6",
+ new Object[]{com.arjuna.ats.arjuna.common.Environment.PERIODIC_RECOVERY_PERIOD, recoveryPeriodString});
+ }
+ }
+ }
+
+ _backoffPeriod = _defaultBackoffPeriod;
+
+ String backoffPeriodString=
+ arjPropertyManager.propertyManager.getProperty(com.arjuna.ats.arjuna.common.Environment.RECOVERY_BACKOFF_PERIOD);
+
+
+ if (backoffPeriodString != null)
+ {
+ try
+ {
+ Integer backoffPeriodInteger = new Integer(backoffPeriodString);
+ _backoffPeriod = backoffPeriodInteger.intValue();
+
+ if (tsLogger.arjLogger.isDebugEnabled())
+ {
+ tsLogger.arjLogger.debug
+ ( DebugLevel.FUNCTIONS,
+ VisibilityLevel.VIS_PRIVATE,
+ FacilityCode.FAC_CRASH_RECOVERY,
+ "PeriodicRecovery" +
+ ": Backoff period set to " + _backoffPeriod + " seconds" );
+ }
+ }
+ catch (NumberFormatException e)
+ {
+ if (tsLogger.arjLoggerI18N.isWarnEnabled())
+ {
+ tsLogger.arjLoggerI18N.warn("com.arjuna.ats.internal.arjuna.recovery.PeriodicRecovery_7",
+ new Object[]{com.arjuna.ats.arjuna.common.Environment.RECOVERY_BACKOFF_PERIOD, backoffPeriodString});
+ }
+ }
+ }
+ }
+
+}
+
+
+
+
+
+
+
+
Property changes on: trunk/federate-txn-jbossts/src/main/java/com/arjuna/ats/internal/arjuna/recovery/PeriodicRecovery.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
More information about the federate-commits
mailing list