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

org.objectweb.dream.pump.AbstractPumpSynchronized Maven / Gradle / Ivy

/**
 * Dream
 * Copyright (C) 2003-2004 INRIA Rhone-Alpes.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY 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 along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Contact : [email protected]
 *
 * Initial developer(s): Vivien Quema
 * Contributor(s): Romain Lenglet
 */

package org.objectweb.dream.pump;

import org.objectweb.dream.Pull;
import org.objectweb.dream.PullException;
import org.objectweb.dream.Push;
import org.objectweb.dream.PushException;
import org.objectweb.dream.control.activity.manager.TaskManager;
import org.objectweb.dream.control.activity.task.AbstractTask;
import org.objectweb.dream.control.activity.task.Task;
import org.objectweb.dream.message.Message;
import org.objectweb.dream.message.MessageManagerType;
import org.objectweb.dream.synchro.MutexItf;
import org.objectweb.dream.util.LoggerUtil;
import org.objectweb.fractal.api.Component;
import org.objectweb.fractal.api.control.IllegalLifeCycleException;
import org.objectweb.fractal.fraclet.annotation.annotations.Attribute;
import org.objectweb.fractal.fraclet.annotation.annotations.Service;
import org.objectweb.dream.dreamannotation.DreamComponent;
import org.objectweb.dream.dreamannotation.DreamLifeCycle;
import org.objectweb.dream.dreamannotation.DreamMonolog;
import org.objectweb.dream.dreamannotation.util.DreamLifeCycleType;
import org.objectweb.fractal.fraclet.annotation.annotations.Requires;
import org.objectweb.fractal.fraclet.annotation.annotations.type.Contingency;
import org.objectweb.util.monolog.api.BasicLevel;
import org.objectweb.util.monolog.api.Logger;

/**
 * Abstract implementation of a synchronized Pull/Push pump. This component has
 * an optional {@link org.objectweb.dream.synchro.MutexItf} client interface
 * that it uses to synchronize the execution of its run method with other
 * components.
 */
@DreamComponent(controllerDesc = "activeDreamPrimitive")
public abstract class AbstractPumpSynchronized
{

  // ---------------------------------------------------------------------------
  // Client interfaces
  // ---------------------------------------------------------------------------

  @Requires(name = "out-push")
  protected Push               outPushItf;
  @Requires(name = "in-pull")
  protected Pull               inPullItf;
  @Requires(name = MutexItf.ITF_NAME, contingency = Contingency.OPTIONAL)
  protected MutexItf           mutexItf;
  @Requires(name = "message-manager")
  protected MessageManagerType messageManagerItf;
  @Requires(name = "task-manager")
  protected TaskManager        taskManagerItf;

  // --------------------------------------------------------------------------
  // Services interfaces
  // --------------------------------------------------------------------------

  /**
   * Component reference
   */
  @Service
  Component                    weaveableC;

  /**
   * Logger of the component
   */
  @DreamMonolog()
  protected Logger             logger;

  // ---------------------------------------------------------------------------
  // Attributes
  // ---------------------------------------------------------------------------
  /**
   * the PushNullPolicy indicates whether "null" messages that
   * are pulled must be pushed or not. Its default value is false.
   */
  @Attribute(argument = "pushNullPolicy")
  protected boolean            pushNullPolicy            = false;
  /**
   * the StopOnPushExceptionPolicy indicates whether the task
   * must be stopped when a {@link org.objectweb.dream.PushException} occurs.
   * Its default value is true.
   */
  @Attribute(argument = "stopOnPushExceptionPolicy")
  protected boolean            stopOnPushExceptionPolicy = true;
  /**
   * the StopOnPullExceptionPolicy indicates whether the task
   * must be stopped when a {@link org.objectweb.dream.PullException} occurs.
   * Its default value is true.
   */
  @Attribute(argument = "stopOnPullExceptionPolicy")
  protected boolean            stopOnPullExceptionPolicy = true;

  // ---------------------------------------------------------------------------
  // Fields
  // ---------------------------------------------------------------------------

  protected AbstractTask       pumpTask                  = new PumpTask();

  /**
   * True when the stopFc() method has been called on the component interface.
   */
  protected boolean            isComponentStopping       = false;

  // ---------------------------------------------------------------------------
  // Implementation of PumpTask class
  // ---------------------------------------------------------------------------

  class PumpTask extends AbstractTask
  {

    /**
     * Default constructor
     */
    public PumpTask()
    {
      super("PumpTask");
    }

    /**
     * @see org.objectweb.dream.control.activity.task.Task#execute(Object)
     */
    public Object execute(Object hints) throws InterruptedException
    {
      LoggerUtil.start(logger);
      if (mutexItf != null)
      {
        mutexItf.lock();
      }
      Message msg = null;
      try
      {
        msg = inPullItf.pull();
        if (msg != null || pushNullPolicy)
        {
          outPushItf.push(msg);
        }
      }
      catch (PullException e)
      {
        return handlePullException(e);
      }
      catch (PushException e)
      {
        return handlePushException(msg, e);
      }
      finally
      {
        if (mutexItf != null)
        {
          mutexItf.unlock();
        }
      }
      return EXECUTE_AGAIN;
    }
  }

  // ---------------------------------------------------------------------------
  // Utility methods.
  // ---------------------------------------------------------------------------

  /**
   * Handles a {@link PushException} occurring when the activity tries to push a
   * message. This implementation simply deletes the message using message
   * manger.
   * 
   * @param message the pushed message
   * @param exception the exception thrown during the push call.
   */
  protected Object handlePushException(Message message, PushException exception)
  {
    messageManagerItf.deleteMessage(message);
    if (stopOnPushExceptionPolicy)
    {
      if (logger.isLoggable(BasicLevel.WARN))
      {
        logger.log(BasicLevel.WARN,
            "Push exception occurred, stop executing the task", exception);
      }
      return Task.STOP_EXECUTING;
    }
    if (logger.isLoggable(BasicLevel.WARN))
    {
      logger.log(BasicLevel.WARN,
          "Push exception occurred, continue executing the task", exception);
    }
    return Task.EXECUTE_AGAIN;
  }

  /**
   * Handles a {@link PullException} occurring when the activity tries to pull a
   * message.
   * 
   * @param exception the exception thrown during the pull call.
   */
  protected Object handlePullException(PullException exception)
  {
    LoggerUtil.start(logger);
    // test if the component is stopping
    if (isComponentStopping)
    {
      // The exception has been generated by the activity manager
      // So this exception is not logged.
      // The task is simply stopped
      return AbstractTask.STOP_EXECUTING;
    }
    if (stopOnPullExceptionPolicy)
    {
      if (logger.isLoggable(BasicLevel.WARN))
      {
        logger.log(BasicLevel.WARN,
            "Pull exception occurred, stop executing the task", exception);
      }
      LoggerUtil.returnAfter(logger);
      return AbstractTask.STOP_EXECUTING;
    }
    if (logger.isLoggable(BasicLevel.WARN))
    {
      logger.log(BasicLevel.WARN,
          "Pull exception occurred, continue executing the task", exception);
    }
    LoggerUtil.returnAfter(logger);
    return AbstractTask.EXECUTE_AGAIN;
  }
  
  /**
   * @see org.objectweb.dream.AbstractComponent#beforeFirstStart(Component)
   */
  @DreamLifeCycle(on = DreamLifeCycleType.PREPARE_TO_STOP)
  protected void prepareStopFcHandler() throws IllegalLifeCycleException
  {
    LoggerUtil.start(logger);
    isComponentStopping = true;
    LoggerUtil.end(logger);
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy