Package com.arjuna.mwlabs.wsas.activity

Source Code of com.arjuna.mwlabs.wsas.activity.ActivityReaper

/*
* 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) 2002,
*
* Arjuna Technologies Limited,
* Newcastle upon Tyne,
* Tyne and Wear,
* UK.
*
* $Id: ActivityReaper.java,v 1.6 2005/05/19 12:13:18 nmcl Exp $
*/

package com.arjuna.mwlabs.wsas.activity;

import com.arjuna.mw.wsas.logging.wsasLogger;

import com.arjuna.mw.wsas.UserActivityFactory;
import com.arjuna.mw.wsas.status.*;

import com.arjuna.mw.wsas.completionstatus.*;

import com.arjuna.mw.wsas.common.Environment;

import com.arjuna.ats.internal.arjuna.template.OrderedList;
import com.arjuna.ats.internal.arjuna.template.OrderedListIterator;

/**
* Class to record activities with non-zero timeout values, and
* class to implement a activity reaper thread which terminates
* these activities once their timeout elapses.
*
* @author Mark Little (mark@arjuna.com)
* @version $Id: ActivityReaper.java,v 1.6 2005/05/19 12:13:18 nmcl Exp $
* @since 1.0.
*/

public class ActivityReaper
{

    public static final String NORMAL = "NORMAL";
    public static final String DYNAMIC = "DYNAMIC";

    public final long checkingPeriod ()
    {
  return _checkPeriod;
    }

    /*
     * Should be no need to protect with a mutex since only one thread
     * is ever doing the work.
     */

    /**
     * Only check for one at a time to prevent starvation.
     *
     * Timeout is given in milliseconds.
     *
     * @message com.arjuna.mwlabs.wsas.activity.ActivityReaper_1 [com.arjuna.mwlabs.wsas.activity.ActivityReaper_1] - ActivityReaper: could not terminate.
     */
   
    public final boolean check (long timeout)
    {
  if (_list == null)
      return true;
 
  OrderedListIterator iter = new OrderedListIterator(_list);
  ReaperElement e = null;

  while ((e = (ReaperElement) iter.iterate()) != null)
  {
      if (timeout >= e._absoluteTimeout)
    break;
      else
      {
    iter = null;
    return true;
      }
  }

  iter = null;
 
  if (e != null)
  {
      /*
       * Only force rollback if the activity is still running.
       */

      Status status = com.arjuna.mw.wsas.status.Unknown.instance();
     
      try
      {
    status = e._activity.status();
      }
      catch (Exception ex)
      {
      }
     
      if (status instanceof Active)
      {
    /*
     * If this is a local activity, then we can roll it
     * back completely. Otherwise, just mark it as rollback only.
     */

    boolean problem = false;
   
    try
    {
        try
        {
      /*
       * TODO
       *
       * Everything works on thread-to-activity association
       * so we can't just tell an activity to end: we have
       * to resume it and then tell it to end. The reason
       * is that all HLS-es assume that the invoking thread
       * has the current context on it.
       */

      //      e._activity.end(Failure.instance());

      UserActivityFactory.userActivity().resume(new ActivityHierarchyImple(e._activity));
      UserActivityFactory.userActivity().end(Failure.instance());
      UserActivityFactory.userActivity().suspend();
        }
        catch (Exception ex)
        {
      problem = true;
        }
    }
    catch (Exception ex2)
    {
        problem = true;
    }
   
    if (problem)
    {
        boolean error = false;
        
        try
        {
      e._activity.setCompletionStatus(FailureOnly.instance());
        }
        catch (Exception ex3)
        {
      error = true;
        }
        
        if (error)
        {
      wsasLogger.arjLoggerI18N.warn("com.arjuna.mwlabs.wsas.activity.ActivityReaper_1");
        }
    }
      }
     
      _list.remove(e);
  }
 
  System.gc()// do some garbage collection while we're at it!
 
  return true;
    }
   
    /**
     * @return the number of items in the reaper's list.
     */

    public final synchronized long numberOfActivities ()
    {
  return ((_list == null) ? 0 : _list.size());
    }
   
    /**
     * timeout is given in seconds, but we work in milliseconds.
     */
    public final synchronized boolean insert (ActivityImple activity, int timeout)
    {
  /*
   * Ignore if the timeout is zero, since this means the activity
   * should never timeout.
   */

  if (timeout == 0)
      return true;
   
  ActivityReaper._lifetime += timeout;
 
  /*
   * If the timeout for this activity is less than the
   * current timeout for the reaper thread (or one is not set for
   * the reaper thread) then use that timeout and interrupt the thread
   * to get it to recheck.
   */

  if ((timeout < _checkPeriod) || (_checkPeriod == Long.MAX_VALUE))
  {
      _checkPeriod = timeout*1000// convert to milliseconds!
      ActivityReaper._reaperThread.interrupt();
  }
 
  ReaperElement e = new ReaperElement(activity, timeout);

  if ((_list != null) && _list.insert(e))
      return true;
  else
  {
      e = null;
      return false;
  }
    }

    public final synchronized boolean remove (ActivityImple act)
    {
  if ((_list == null) || (act == null))
      return false;
   
  ReaperElement e = null;
  OrderedListIterator iter = new OrderedListIterator(_list);
  boolean result = false;
  boolean found = false;
 
  while (((e = (ReaperElement) iter.iterate()) != null) && !found)
  {
      try
      {
    found = e._activity.equals(act);
      }
      catch (Exception e2)
      {
    break;
      }
  }

  iter = null;

  if (found)
  {
      result = _list.remove(e);

      e = null;
  }

  return result;
    }

    /**
     * Currently we let the reaper thread run at same priority as other
     * threads. Could get priority from environment.
     */

    public static synchronized ActivityReaper create (long checkPeriod)
    {
  if (ActivityReaper._theReaper == null)
  {
      String mode = System.getProperty(Environment.REAPER_MODE);
     
      if (mode != null)
      {
    if (mode.compareTo(ActivityReaper.DYNAMIC) == 0)
        ActivityReaper._dynamic = true;
      }
     
      if (!ActivityReaper._dynamic)
      {
    String timeoutEnv = System.getProperty(Environment.REAPER_TIMEOUT);

    if (timeoutEnv != null)
    {
        Long l = null;
   
        try
        {
      l = new Long(timeoutEnv);
      checkPeriod = l.longValue();
     
      l = null;
        }
        catch (NumberFormatException e)
        {
      e.printStackTrace();
        }
    }
      }
      else
    checkPeriod = Long.MAX_VALUE;
   
      ActivityReaper._theReaper = new ActivityReaper(checkPeriod);
     
      _reaperThread = new ReaperThread(ActivityReaper._theReaper);
      //      _reaperThread.setPriority(Thread.MIN_PRIORITY);

      _reaperThread.setDaemon(true);
     
      _reaperThread.start();
  }

  return ActivityReaper._theReaper;
    }

    public static synchronized ActivityReaper create ()
    {
  return create(ActivityReaper.defaultCheckPeriod);
    }
   
    public static synchronized ActivityReaper activityReaper ()
    {
  return activityReaper(false);
    }

    /*
     * If parameter is true then do a create.
     */

    public static synchronized ActivityReaper activityReaper (boolean createReaper)
    {
  if (createReaper)
      return create();
  else
      return _theReaper;
    }
   
    /*
     * Don't bother synchronizing as this is only an estimate anyway.
     */

    public static final long activityLifetime ()
    {
  return ActivityReaper._lifetime;
    }

    public static final long defaultCheckPeriod = 120000// in milliseconds

    ActivityReaper (long checkPeriod)
    {
  _list = new OrderedList();
  _checkPeriod = checkPeriod;

  if (_list == null)
  {
      throw new OutOfMemoryError();
  }
    }

    static final void reset ()
    {
  _theReaper = null;
    }
   
    private OrderedList _list;
    private long        _checkPeriod;
   
    private static ActivityReaper _theReaper = null;
    private static ReaperThread   _reaperThread = null;
    private static boolean        _dynamic = false;
    private static long           _lifetime = 0;
}


TOP

Related Classes of com.arjuna.mwlabs.wsas.activity.ActivityReaper

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.