cz.cuni.amis.pogamut.base.agent.impl
Class AbstractAgent

Package class diagram package AbstractAgent
java.lang.Object
  extended by cz.cuni.amis.pogamut.base.agent.impl.AbstractAgent
All Implemented Interfaces:
IAgent, IComponent, IComponentAware, IControllable
Direct Known Subclasses:
AbstractObservingAgent, TestAgents.NetworkLoggingAgent

public abstract class AbstractAgent
extends Object
implements IAgent

Abstract agent class, provides basic interface for the agent implementing its lifecycle methods + introducing JMX.

Agent has fully implemented lifecycle methods such as start(), startPaused() or stop(). It also listens for IFatalErrorEvent on its bus in order to terminate itself in case of any errors. Also, if all components of the agent stops themselves, the agent is stopped as well. If you do not like this behavior, email me to jakub.gemrot@gmail.com and I will make this optional.

Note that the Pogamut agent is designed to be a multicomponent beast. And by component we're meaning objects that implements IComponent registers itself into getEventBus() owned by the agent and adhering to the lifecycle provided either by ComponentController or ILifecycleBus#addLifecycleManagement(IToken, cz.cuni.amis.pogamut.base.component.controller.IComponentControlHelper, cz.cuni.amis.pogamut.base.component.controller.ComponentDependencies).

These components (if correctly configured, which all native components are) starts together with the call of start() or startPaused(), as well as stopping themselves in the case of stop().

This model seems to defy the OOP, in fact it is its very incarnation applying principles or "separation of concerns", "modular design", whatever you would like to call it. Many native components are designed the way they interact with each other only via interfaces, they do not depend on each other directly thus greatly enabling anybody to hack inside any internal component of any Pogamut agent.

JMX

We're purposely using neither inheritance here nor decorator (or such wrappers) because we need JMX to be usable by every descendant of the class (so we don't want to have another JMX class branch, nor wrapper that denies the inheritance by its nature).

To keep the JMX-specific methods at minimum in the agent class we're grouping them into the private inner class object JMXComponents that can be accessed via getJMX() method. This object maintain also a list of IJMXEnabled components that should be enabled when the whole JMX feature is being enabled.

Usage:

To start JMX on the agent: getJMX().enableJMX(mBeanServer, domain)

To add another JMX component to the agent: getJMX().addComponent(component)

Author:
Jimmy

Field Summary
protected  AgentEvents events
          Gateway for sending events into the event bus.
static String INTROSPECTION_ROOT_NAME
          Name of the root introspection folder.
protected  LogCategory log
          Agent's log category, goes under category name LOG_CATEGORY_NAME.
static String LOG_CATEGORY_NAME
          Log category name used for log.
 
Constructor Summary
AbstractAgent(IAgentId agentId, IComponentBus eventBus, IAgentLogger logger)
          Introspection folder with properties and other subfolders obtained from this agent.
 
Method Summary
protected  void addDependency(Class componentClass)
           
protected  void addDependency(IComponent component)
           
protected  void addDependency(cz.cuni.amis.utils.token.IToken componentId)
           
protected  void addJMXComponents()
          Called when AgentJMX (field jmx) is instantiated to populate it with agent's JMX enabled components.
 IAgentState awaitState(Class awaitAgentState)
          This method is designed to wait for the agent to reach state 'awaitAgentState' (usually used with IAgentStateUp.
 IAgentState awaitState(Class awaitAgentState, long timeoutMillis)
          This method is designed to wait for the agent's initialization until till 'timeoutMillis'.
protected  void componentFatalError(IFatalErrorEvent event)
          Called whenever some comopnent broadcasts IFatalErrorEvent.
protected  void componentStarted(IPausedEvent event)
          Called whenever some component that was not started before broadcasts IPausedEvent If you override this method don't forget to call super.componentStarted(event) as the first method.
protected  void componentStarted(IStartedEvent event)
          Called whenever some component that was not started before broadcasts IStartedEvent If you override this method don't forget to call super.componentStarted(event) as the first method.
protected  void componentStopped(IStoppedEvent event)
          Called whenever component that was running broadcasts IStoppedEvent.
protected  void componentStopping(IStoppingEvent event)
          Called whenever some component broadcasts IStoppingEvent If you override this method don't forget to call super.componentStopping(event) as the first method.
protected  AgentJMXComponents createAgentJMX()
           
protected  cz.cuni.amis.introspection.Folder createIntrospection()
          Create introspection root object.
 boolean equals(Object other)
           
 IAgentId getComponentId()
          Returns agent id - contains also a human-readable name that can be changed
 IComponentBus getEventBus()
          IComponentBus that the instance is working with.
 cz.cuni.amis.introspection.Folder getIntrospection()
          Returns folder with introspection information.
 AgentJMXComponents getJMX()
          Returns support class for the JMX feature of the agent.
 LogCategory getLog()
          Returns log category of the agent, used by agent lifecycle management methods itself.
 IAgentLogger getLogger()
          Returns AgentLogger for the instance allowing creating new log categories or adding new handlers to them.
 String getName()
          Returns human-readable agent's name.
 cz.cuni.amis.utils.flag.ImmutableFlag<IAgentState> getState()
          Returns the state of the agent (whether it's running / dead / etc.).
 int hashCode()
           
 boolean inState(Class<?>... states)
          Returns true if the agent is in one of 'states'.
 void kill()
          Method that requests the agent to be killed - this counts as fatal error as well.
protected  void killAgent()
          Called during kill() method - override to provide custom ruthless stopping (killing) behavior of the agent.
 boolean notInState(Class<?>... states)
          Returns true if the agent is not in any of 'states'.
 void pause()
          Pauses the agent - working only if the agent is in IAgentStateRunning 1) switches state to IAgentStatePausing 2) broadcasts IPausingEvent (transactional) 3) calls pauseAgent() 4) broadcasts IPausedEvent (transactional) 5) switches state to IAgentPaused Prevents recursion.
protected  void pauseAgent()
          Called during pause() method - override to provide custom pausing behavior of the agent.
protected  void preKillAgent()
          Called before any ComponentBusEvents.fatalError(String) event is broadcast.
protected  void preStopAgent()
          Called before any ComponentBusEvents.stopping() event is broadcast.
protected  void resetAgent()
          Called whenever the IComponentBus broadcast IResetEvent to reset all agent's components as well as an agent.
protected  void resetEvent(IResetEvent event)
           
 void resume()
          Resumes the agent - working only if the agent is in IAgentStatePaused 1) switches state to IAgentStateResuming 2) broadcasts IResumingEvent (transactional) 3) calls resumeAgent() 4) broadcasts IResumedEvent (transactional) 5) switches state to IAgentStateRunning Prevents recursion.
protected  void resumeAgent()
          Called during resume() method - override to provide custom resuming behavior of the agent.
protected  void setState(AgentState state)
          Sets the state of the agent ... note that the flag is private field so you can't change it directly.
 void start()
          Starts the agent.
protected  void startAgent()
          Called during start() method - override to provide custom starting behavior of the agent.
 void startPaused()
          Starts the agent into paused state.
protected  void startPausedAgent()
          Called during startPaused() method - override to provide custom starting-paused behavior of the agent.
 void stop()
          Stops the agent.
protected  void stopAgent()
          Called during stop() method - override to provide custom stopping behavior of the agent.
 String toString()
           
 
Methods inherited from class java.lang.Object
clone, finalize, getClass, notify, notifyAll, wait, wait, wait
 

Field Detail

INTROSPECTION_ROOT_NAME

public static final String INTROSPECTION_ROOT_NAME
Name of the root introspection folder.

See Also:
Constant Field Values

LOG_CATEGORY_NAME

public static final String LOG_CATEGORY_NAME
Log category name used for log.

See Also:
Constant Field Values

log

protected LogCategory log
Agent's log category, goes under category name LOG_CATEGORY_NAME.


events

protected AgentEvents events
Gateway for sending events into the event bus.

Constructor Detail

AbstractAgent

public AbstractAgent(IAgentId agentId,
                     IComponentBus eventBus,
                     IAgentLogger logger)
Introspection folder with properties and other subfolders obtained from this agent.

Parameters:
agentId - unique id of the agent
eventBus - agent's event bus system
logger - agent's logger, used to obtain AgentName instance
Method Detail

equals

public boolean equals(Object other)
Overrides:
equals in class Object

hashCode

public int hashCode()
Overrides:
hashCode in class Object

getLogger

public IAgentLogger getLogger()
Description copied from interface: IAgent
Returns AgentLogger for the instance allowing creating new log categories or adding new handlers to them.

Specified by:
getLogger in interface IAgent
Returns:

getState

public cz.cuni.amis.utils.flag.ImmutableFlag<IAgentState> getState()
Description copied from interface: IAgent
Returns the state of the agent (whether it's running / dead / etc.).

Note that the type AgentState wraps two things:

Specified by:
getState in interface IAgent
Returns:

inState

public boolean inState(Class<?>... states)
Returns true if the agent is in one of 'states'.

Parameters:
states -
Returns:

notInState

public boolean notInState(Class<?>... states)
Returns true if the agent is not in any of 'states'.

Parameters:
states -
Returns:

getEventBus

public IComponentBus getEventBus()
Description copied from interface: IComponentAware
IComponentBus that the instance is working with.

Note that by design-choice - the IComponentBus is a singleton inside AgentScoped, therefore you don't have to necessarily obtain the instance through the component, it suffice to obtain it using injection into your object.

Specified by:
getEventBus in interface IComponentAware
Returns:

getName

public String getName()
Description copied from interface: IAgent
Returns human-readable agent's name.

Do not use as unique id of the agent:

1) the name might change during the life of agent

2) we do not ensure it's unique

Use getComponentId().getToken() instead!

Use getComponentId().getName().setFlag() to change the name of the agent.

Specified by:
getName in interface IAgent
Returns:

getComponentId

public IAgentId getComponentId()
Description copied from interface: IAgent
Returns agent id - contains also a human-readable name that can be changed

Specified by:
getComponentId in interface IAgent
Specified by:
getComponentId in interface IComponent
Returns:

getLog

public LogCategory getLog()
Returns log category of the agent, used by agent lifecycle management methods itself.


start

public final void start()
                 throws ComponentCantStartException
Starts the agent.

1) switches state to IAgentStateStarting

2) broadcasts IStartingEvent (transactional)

3) calls startAgent()

3) broadcasts IStartedEvent (transactional)

4) switches state to IAgentStateStarted

Every agent component that wants to start together with the agent should do so during (2 or 3) and broadcast eventTransactionl(IStartedEvent / IPausedEvent).

Prevents recursion.

Specified by:
start in interface IAgent
Specified by:
start in interface IControllable
Throws:
ComponentCantStartException

startPaused

public final void startPaused()
                       throws ComponentCantStartException
Starts the agent into paused state.

1) switches state to IAgentStateStartingPaused

2) broadcasts IStartingPausedEvent (transactional)

3) calls startAgent()

3) broadcasts IPausedEvent (transactional)

4) switches state to IAgentStatePaused

Every agent component that wants to start together with the agent should do so during (2 or 3) and broadcast eventTransactionl(IStartedEvent / IPausedEvent).

Prevents recursion.

Specified by:
startPaused in interface IAgent
Throws:
ComponentCantStartException

preStopAgent

protected void preStopAgent()
Called before any ComponentBusEvents.stopping() event is broadcast. Hook that allows you to implement just-before-death stuff before any of agent component actually dies.


stop

public final void stop()
                throws ComponentCantStopException
Stops the agent.

1) switches state to IAgentStateStopping

2) broadcasts IStoppingEvent (transactional)

3) calls stopAgent()

4) checks whether all components has stopped, if not - performs kill(). 5) broadcasts IStoppedEvent (transactional)

6) switches state to IAgentStateStopped

Every agent's component that is still running must stop itself during (2) by broadcasting 'eventTransactional(IStoppedEvent)'.

If there will be some component that remains started after the propagation of IStoppingEvent the method will perform kill() method (counts as fatal error) and throws AgentException.

Prevents recursion.

Specified by:
stop in interface IAgent
Specified by:
stop in interface IControllable
Throws:
ComponentCantStopException

preKillAgent

protected void preKillAgent()
Called before any ComponentBusEvents.fatalError(String) event is broadcast. Hook that allows you to implement just-before-death stuff before any of agent component actually dies.


kill

public final void kill()
Method that requests the agent to be killed - this counts as fatal error as well.

1) switches state to IAgentStateFailed

2) broadcast IFatalErrorEvent

3) calls killAgent()

This should be used to ultimately kill the agent in a ruthless way - components will usually perform some dirty tricks to kill themselves.

Prevents recursion.

NEVER THROWS EXCEPTION

Specified by:
kill in interface IAgent
Specified by:
kill in interface IControllable

pause

public final void pause()
                 throws ComponentCantPauseException
Pauses the agent - working only if the agent is in IAgentStateRunning

1) switches state to IAgentStatePausing 2) broadcasts IPausingEvent (transactional)

3) calls pauseAgent()

4) broadcasts IPausedEvent (transactional)

5) switches state to IAgentPaused

Prevents recursion.

Specified by:
pause in interface IAgent
Throws:
ComponentCantPauseException

resume

public final void resume()
                  throws ComponentCantResumeException
Resumes the agent - working only if the agent is in IAgentStatePaused

1) switches state to IAgentStateResuming

2) broadcasts IResumingEvent (transactional)

3) calls resumeAgent()

4) broadcasts IResumedEvent (transactional)

5) switches state to IAgentStateRunning

Prevents recursion.

Specified by:
resume in interface IAgent
Throws:
ComponentCantResumeException

getJMX

public final AgentJMXComponents getJMX()
Returns support class for the JMX feature of the agent. You may use it to register new JMX components of the agent or for enabling of the whole feature.

Returns:

awaitState

public IAgentState awaitState(Class awaitAgentState)
                       throws AgentException
This method is designed to wait for the agent to reach state 'awaitAgentState' (usually used with IAgentStateUp.

The call on this method will blocks until this instance of agent switches to the desired state. Nevertheless - if the agent switches itself to the IAgentStateDown state, it returns null. (if it is not the state you are awaiting for of course). If you find this unsuitable, use WaitForAgentStateChange directly.

Parameters:
awaitAgentState -
Throws:
AgentException

awaitState

public IAgentState awaitState(Class awaitAgentState,
                              long timeoutMillis)
                       throws AgentException
This method is designed to wait for the agent's initialization until till 'timeoutMillis'.

The call on this method will blocks until this instance of agent switches to the IAgentStateUp. Nevertheless - if the agent switches itself to the IAgentStateDown state, it returns null. If you find this unsuitable, use WaitForAgentStateChange directly.

The method also returns null in the case of timeout.

Parameters:
awaitAgentState -
timeoutMillis - how long we should wait for the agent to ini
Throws:
AgentException
cz.cuni.amis.utils.exception.PogamutInterruptedException

getIntrospection

public final cz.cuni.amis.introspection.Folder getIntrospection()
Description copied from interface: IAgent
Returns folder with introspection information. Useful for showing agent model variables and parameters.

Specified by:
getIntrospection in interface IAgent
Returns:
Folder with introspection info

createIntrospection

protected cz.cuni.amis.introspection.Folder createIntrospection()
Create introspection root object.

Returns:

startAgent

protected void startAgent()
Called during start() method - override to provide custom starting behavior of the agent.

WARNING: DO NOT CALL ON YOUR OWN, ALWAYS USE PUBLIC INTERFACE (start()), but that should not be needed!

If you override this method don't forget to call super.startAgent() as the first method.


startPausedAgent

protected void startPausedAgent()
Called during startPaused() method - override to provide custom starting-paused behavior of the agent.

WARNING: DO NOT CALL ON YOUR OWN, ALWAYS USE PUBLIC INTERFACE (startPaused()), but that should not be needed!

If you override this method don't forget to call super.startPausedAgent() as the first method.


stopAgent

protected void stopAgent()
Called during stop() method - override to provide custom stopping behavior of the agent.

WARNING: DO NOT CALL ON YOUR OWN, ALWAYS USE PUBLIC INTERFACE (stop()).

If you override this method don't forget to call super.stopAgent() as the first method.


killAgent

protected void killAgent()
Called during kill() method - override to provide custom ruthless stopping (killing) behavior of the agent.

WARNING: DO NOT CALL ON YOUR OWN, ALWAYS USE PUBLIC INTERFACE (kill()).

If you override this method don't forget to call super.killAgent() as the first method.


pauseAgent

protected void pauseAgent()
Called during pause() method - override to provide custom pausing behavior of the agent.

WARNING: DO NOT CALL ON YOUR OWN, ALWAYS USE PUBLIC INTERFACE (pause()).

If you override this method don't forget to call super.pauseAgent() as the first method.


resumeAgent

protected void resumeAgent()
Called during resume() method - override to provide custom resuming behavior of the agent.

WARNING: DO NOT CALL ON YOUR OWN, ALWAYS USE PUBLIC INTERFACE (resume()).

If you override this method don't forget to call super.resumeAgent() as the first method.


resetAgent

protected void resetAgent()
Called whenever the IComponentBus broadcast IResetEvent to reset all agent's components as well as an agent. Clean up your private data structure, get ready to be started again.

WARNING: DO NOT CALL ON YOUR OWN, CALLED FROM THE resetEvent(IResetEvent) AUTOMATICALLY.

If you override this method don't forget to call super.resetAgent() as the first method.


componentStarted

protected void componentStarted(IStartedEvent event)
Called whenever some component that was not started before broadcasts IStartedEvent

If you override this method don't forget to call super.componentStarted(event) as the first method.

Parameters:
event -

componentStarted

protected void componentStarted(IPausedEvent event)
Called whenever some component that was not started before broadcasts IPausedEvent

If you override this method don't forget to call super.componentStarted(event) as the first method.

Parameters:
event -

componentStopping

protected void componentStopping(IStoppingEvent event)
Called whenever some component broadcasts IStoppingEvent

If you override this method don't forget to call super.componentStopping(event) as the first method.

Parameters:
event -

componentStopped

protected void componentStopped(IStoppedEvent event)
Called whenever component that was running broadcasts IStoppedEvent.

If you override this method don't forget to call super.componentStopped(event) as the first method.

Parameters:
event -

componentFatalError

protected void componentFatalError(IFatalErrorEvent event)
Called whenever some comopnent broadcasts IFatalErrorEvent.

If you override this method don't forget to call super.fatalError(event) as the first method.

Parameters:
event -

resetEvent

protected void resetEvent(IResetEvent event)

createAgentJMX

protected AgentJMXComponents createAgentJMX()

addDependency

protected void addDependency(IComponent component)

addDependency

protected void addDependency(Class componentClass)

addDependency

protected void addDependency(cz.cuni.amis.utils.token.IToken componentId)

setState

protected void setState(AgentState state)
Sets the state of the agent ... note that the flag is private field so you can't change it directly.

Parameters:
state -

addJMXComponents

protected void addJMXComponents()
Called when AgentJMX (field jmx) is instantiated to populate it with agent's JMX enabled components.

Currently two components are added:

  1. agent's logger
  2. agent's introspection

If you override this method don't forget to call super.addJMXComponents() as the first method.

Note that you don't need to override this method to introduce new jmx components if and only if:

1) you do not need the component before the agent starts up

2) your JMX component is also an IComponent that starts together with the agent

If (2) holds, the component will be added to the 'jmx' by the agent automatically and if jmx is already started it will start it as well.


toString

public String toString()
Overrides:
toString in class Object


Copyright © 2015 AMIS research group, Faculty of Mathematics and Physics, Charles University in Prague, Czech Republic. All Rights Reserved.