2008-06-17 20:27:32 +04:00
/* -------------------------------------------------------------------------- */
2019-01-16 13:27:59 +03:00
/* Copyright 2002-2019, OpenNebula Project, OpenNebula Systems */
2008-06-17 20:27:32 +04:00
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
# ifndef ACTION_MANAGER_H_
# define ACTION_MANAGER_H_
# include <queue>
# include <pthread.h>
# include <ctime>
# include <string>
/**
2017-02-03 16:19:15 +03:00
* Represents a generic request , pending actions are stored in a queue .
* Each element stores the base action type , additional data is added by each
* ActionListener implementation .
2008-06-17 20:27:32 +04:00
*/
2017-02-03 16:19:15 +03:00
class ActionRequest
2008-06-17 20:27:32 +04:00
{
public :
/**
2017-02-03 16:19:15 +03:00
* Base Action types
2008-06-17 20:27:32 +04:00
*/
2017-02-03 16:19:15 +03:00
enum Type
{
FINALIZE ,
TIMER ,
USER
} ;
2008-06-17 20:27:32 +04:00
2017-02-03 16:19:15 +03:00
Type type ( ) const
{
return _type ;
}
2008-06-17 20:27:32 +04:00
2017-02-03 16:19:15 +03:00
ActionRequest ( Type __type ) : _type ( __type ) { } ;
2017-02-08 14:24:42 +03:00
virtual ~ ActionRequest ( ) { } ;
virtual ActionRequest * clone ( ) const
{
return new ActionRequest ( _type ) ;
}
2017-02-03 16:19:15 +03:00
protected :
Type _type ;
} ;
/**
* ActionListener class . Interface to be implemented by any class that need to
* handle actions .
*/
class ActionListener
{
protected :
2008-06-17 20:27:32 +04:00
ActionListener ( ) { } ;
2015-07-01 22:15:40 +03:00
2008-06-17 20:27:32 +04:00
virtual ~ ActionListener ( ) { } ;
/**
2017-02-03 16:19:15 +03:00
* the user_action ( ) function is executed upon action arrival .
2008-06-17 20:27:32 +04:00
* This function should check the action type , and perform the
* corresponding action .
2017-02-03 16:19:15 +03:00
* @ param ar the ActionRequest
*/
virtual void user_action ( const ActionRequest & ar ) { } ;
2017-02-07 19:26:23 +03:00
/**
* Periodic timer action , executed each time the time_out expires . Listener
* needs to re - implement the default timer action if needed .
* @ param ar the ActionRequest
*/
2017-02-03 16:19:15 +03:00
virtual void timer_action ( const ActionRequest & ar ) { } ;
2017-02-07 19:26:23 +03:00
/**
* Action executed when the Manager finlizes . Listener needs to re - implement
* the default action if needed .
* @ param ar the ActionRequest
*/
2017-02-03 16:19:15 +03:00
virtual void finalize_action ( const ActionRequest & ar ) { } ;
private :
friend class ActionManager ;
/**
* Invoke the action handler
2008-06-17 20:27:32 +04:00
*/
2017-02-03 16:19:15 +03:00
void _do_action ( const ActionRequest & ar )
{
switch ( ar . type ( ) )
{
case ActionRequest : : FINALIZE :
finalize_action ( ar ) ;
break ;
case ActionRequest : : TIMER :
timer_action ( ar ) ;
break ;
case ActionRequest : : USER :
user_action ( ar ) ;
break ;
}
}
2008-06-17 20:27:32 +04:00
} ;
/**
* ActionManager . Provides action support for a class implementing
* the ActionListener interface .
*/
class ActionManager
{
public :
ActionManager ( ) ;
2017-02-03 16:19:15 +03:00
2008-06-17 20:27:32 +04:00
virtual ~ ActionManager ( ) ;
2017-02-07 19:26:23 +03:00
/**
* Function to trigger an action to this manager .
2008-06-17 20:27:32 +04:00
* @ param action the action name
* @ param args arguments for the action
*/
2017-02-03 16:19:15 +03:00
void trigger ( const ActionRequest & ar ) ;
2008-06-17 20:27:32 +04:00
2017-02-03 16:19:15 +03:00
/**
* Trigger the FINALIZE event
2008-06-17 20:27:32 +04:00
*/
2017-02-03 16:19:15 +03:00
void finalize ( )
{
ActionRequest frequest ( ActionRequest : : FINALIZE ) ;
2015-07-01 22:15:40 +03:00
2017-02-03 16:19:15 +03:00
trigger ( frequest ) ;
}
/**
* The calling thread will be suspended until an action is triggered .
* @ param timeout for the periodic action .
* @ param timer_args arguments for the timer action
*/
2017-04-30 20:56:47 +03:00
void loop ( struct timespec & _timeout , const ActionRequest & trequest ) ;
void loop ( time_t timeout , const ActionRequest & trequest )
{
struct timespec _timeout ;
_timeout . tv_sec = timeout ;
_timeout . tv_nsec = 0 ;
loop ( _timeout , trequest ) ;
}
2017-02-03 16:19:15 +03:00
/**
* The calling thread will be suspended until an action is triggered .
* @ param timeout for the periodic action , the timer action will recieve
* an " empty " ActionRequest .
2008-06-17 20:27:32 +04:00
*/
2017-02-03 16:19:15 +03:00
void loop ( time_t timeout )
2008-06-17 20:27:32 +04:00
{
2017-02-03 16:19:15 +03:00
ActionRequest trequest ( ActionRequest : : TIMER ) ;
2008-06-17 20:27:32 +04:00
2017-04-30 20:56:47 +03:00
struct timespec _timeout ;
_timeout . tv_sec = timeout ;
_timeout . tv_nsec = 0 ;
loop ( _timeout , trequest ) ;
}
void loop ( struct timespec & _timeout )
{
ActionRequest trequest ( ActionRequest : : TIMER ) ;
loop ( _timeout , trequest ) ;
2017-02-03 16:19:15 +03:00
}
2008-06-17 20:27:32 +04:00
/**
2017-02-07 19:26:23 +03:00
* The calling thread will be suspended until an action is triggered . No
* periodic action is defined .
2017-02-03 16:19:15 +03:00
*/
void loop ( )
{
ActionRequest trequest ( ActionRequest : : TIMER ) ;
2017-04-30 20:56:47 +03:00
struct timespec _timeout ;
_timeout . tv_sec = 0 ;
_timeout . tv_nsec = 0 ;
2017-02-03 16:19:15 +03:00
2017-04-30 20:56:47 +03:00
loop ( _timeout , trequest ) ;
2017-02-03 16:19:15 +03:00
}
2017-02-07 19:26:23 +03:00
/**
* Register the calling object in this action manager .
* @ param listener a pointer to the action listner
2008-06-17 20:27:32 +04:00
*/
2017-02-03 16:19:15 +03:00
void addListener ( ActionListener * listener )
2008-06-17 20:27:32 +04:00
{
2017-02-03 16:19:15 +03:00
this - > listener = listener ;
2008-06-17 20:27:32 +04:00
} ;
2017-02-03 16:19:15 +03:00
private :
2008-06-17 20:27:32 +04:00
/**
* Queue of pending actions , processed in a FIFO manner
*/
2017-02-08 14:24:42 +03:00
std : : queue < ActionRequest * > actions ;
2008-06-17 20:27:32 +04:00
/**
* Action synchronization is implemented using the pthread library ,
* with condition variable and its associated mutex
*/
2017-02-03 16:19:15 +03:00
pthread_mutex_t mutex ;
pthread_cond_t cond ;
2008-06-17 20:27:32 +04:00
/**
* The listener notified by this manager
*/
2017-02-03 16:19:15 +03:00
ActionListener * listener ;
2008-06-17 20:27:32 +04:00
/**
* Function to lock the Manager mutex
*/
void lock ( )
{
pthread_mutex_lock ( & mutex ) ;
} ;
/**
* Function to unlock the Manager mutex
*/
void unlock ( )
{
pthread_mutex_unlock ( & mutex ) ;
} ;
2017-02-03 16:19:15 +03:00
2008-06-17 20:27:32 +04:00
} ;
# endif /*ACTION_MANAGER_H_*/