2020-03-04 18:05:57 +03:00
/* -------------------------------------------------------------------------- */
2024-07-29 15:25:20 +03:00
/* Copyright 2002-2024, OpenNebula Project, OpenNebula Systems */
2020-03-04 18:05:57 +03: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 DRIVER_MANAGER_H_
# define DRIVER_MANAGER_H_
# include "Driver.h"
# include "Attribute.h"
# include "NebulaLog.h"
2020-06-29 13:14:00 +03:00
# include "SyncRequest.h"
2020-03-04 18:05:57 +03:00
# include <string>
2020-06-29 13:14:00 +03:00
template < typename D >
2020-03-04 18:05:57 +03:00
class DriverManager
{
public :
2020-06-29 13:14:00 +03:00
explicit DriverManager ( const std : : string & mad_location )
2020-03-04 18:05:57 +03:00
: mad_location ( mad_location )
{
}
2022-12-13 17:46:54 +03:00
virtual ~ DriverManager ( ) = default ;
2020-03-04 18:05:57 +03:00
2020-06-29 13:14:00 +03:00
int load_driver ( const VectorAttribute * mad_config ) ;
2020-07-02 23:42:10 +03:00
int load_drivers ( const std : : vector < const VectorAttribute * > & mads_config ) ;
2020-03-04 18:05:57 +03:00
D * get_driver ( const std : : string & name ) const ;
/**
* Register an action for a given message type . The action is registered
* for all installed drivers . Must be called after load_drivers method .
*/
2020-06-29 13:14:00 +03:00
void register_action ( typename D : : message_t : : msg_enum t ,
2024-06-03 12:40:24 +03:00
std : : function < void ( std : : unique_ptr < typename D : : message_t > ) > a ) ;
2020-03-04 18:05:57 +03:00
/**
* Start all drivers
*/
int start ( std : : string & error ) ;
/**
* Stop all drivers
2020-04-16 19:15:07 +03:00
* @ param secs to wait for each driver before killing it
2020-03-04 18:05:57 +03:00
*/
2020-04-16 19:15:07 +03:00
void stop ( int secs ) ;
2020-03-04 18:05:57 +03:00
2020-06-29 13:14:00 +03:00
protected :
int add ( const std : : string & name , std : : unique_ptr < D > driver ) ;
/* SyncReqeust methods implementation */
/**
* This function can be periodically executed to check time_outs on
* request . It will fail requests with an expired timeout and will notify
* the clients .
*/
void check_time_outs_action ( ) ;
/**
* Add a new request to the Request map
* @ param ar pointer to the request
* @ return the id for the request
*/
void add_request ( SyncRequest * ar ) ;
/**
* Gets request from the Request map
* @ param id for the request
* @ return pointer to the Request
*/
SyncRequest * get_request ( int id ) ;
/**
* Notify the result of an auth request
*/
void notify_request ( int id , bool result , const std : : string & message ) ;
static Log : : MessageType log_type ( char type ) ;
2024-09-05 17:25:03 +03:00
/**
* Callback called when the driver is reconnected . Override this function
* to perform any actions when the driver is reconnected
*/
virtual void reconnected ( ) { } ;
2020-03-04 18:05:57 +03:00
private :
std : : map < std : : string , std : : unique_ptr < D > > drivers ;
2020-06-29 13:14:00 +03:00
std : : string mad_location ;
/**
* List of pending requests
*/
std : : map < int , SyncRequest * > sync_requests ;
std : : mutex _mutex ;
2020-03-04 18:05:57 +03:00
} ;
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
2020-06-29 13:14:00 +03:00
template < typename D >
int DriverManager < D > : : load_driver ( const VectorAttribute * mad_config )
2020-03-04 18:05:57 +03:00
{
2023-03-08 17:52:20 +03:00
const auto & name = mad_config - > vector_value ( " NAME " ) ;
2020-06-29 13:14:00 +03:00
auto exec = mad_config - > vector_value ( " EXECUTABLE " ) ;
2023-03-08 17:52:20 +03:00
const auto & args = mad_config - > vector_value ( " ARGUMENTS " ) ;
2020-06-29 13:14:00 +03:00
int threads ;
2020-03-04 18:05:57 +03:00
2020-06-29 13:14:00 +03:00
mad_config - > vector_value ( " THREADS " , threads , 0 ) ;
2022-12-13 17:46:54 +03:00
NebulaLog : : info ( " DrM " , " Loading driver: " + name ) ;
2020-06-29 13:14:00 +03:00
if ( exec . empty ( ) )
2020-03-04 18:05:57 +03:00
{
2022-12-13 17:46:54 +03:00
NebulaLog : : error ( " DrM " , " \t Empty executable for driver: " + name ) ;
2020-06-29 13:14:00 +03:00
return - 1 ;
}
2020-03-04 18:05:57 +03:00
2020-06-29 13:14:00 +03:00
if ( exec [ 0 ] ! = ' / ' ) //Look in ONE_LOCATION/lib/mads or in "/usr/lib/one/mads"
{
exec = mad_location + exec ;
}
2020-03-04 18:05:57 +03:00
2020-06-29 13:14:00 +03:00
if ( access ( exec . c_str ( ) , F_OK ) ! = 0 )
{
2022-12-13 17:46:54 +03:00
NebulaLog : : error ( " DrM " , " File not exists: " + exec ) ;
2020-06-29 13:14:00 +03:00
return - 1 ;
}
2020-03-04 18:05:57 +03:00
2020-06-29 13:14:00 +03:00
auto rc = drivers . insert ( std : : make_pair ( name ,
2024-06-03 12:40:24 +03:00
std : : unique_ptr < D > ( new D ( exec , args , threads ) ) ) ) ;
2020-03-04 18:05:57 +03:00
2020-06-29 13:14:00 +03:00
if ( rc . second )
{
2022-12-13 17:46:54 +03:00
NebulaLog : : info ( " DrM " , " \t Driver loaded: " + name ) ;
2020-06-29 13:14:00 +03:00
}
else
{
2022-12-13 17:46:54 +03:00
NebulaLog : : error ( " DrM " , " \t Driver already exists: " + name ) ;
2020-06-29 13:14:00 +03:00
return - 1 ;
}
2020-03-04 18:05:57 +03:00
2020-06-29 13:14:00 +03:00
return 0 ;
}
2020-03-04 18:05:57 +03:00
2020-06-29 13:14:00 +03:00
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
2020-03-04 18:05:57 +03:00
2020-06-29 13:14:00 +03:00
template < typename D >
2020-07-02 23:42:10 +03:00
int DriverManager < D > : : load_drivers ( const std : : vector < const VectorAttribute * > & mads_config )
2020-06-29 13:14:00 +03:00
{
NebulaLog : : info ( " DrM " , " Loading drivers. " ) ;
int rc = 0 ;
for ( const auto & vattr : mads_config )
{
rc + = load_driver ( vattr ) ;
2020-03-04 18:05:57 +03:00
}
2020-06-29 13:14:00 +03:00
return rc ;
2020-03-04 18:05:57 +03:00
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
2020-06-29 13:14:00 +03:00
template < typename D >
D * DriverManager < D > : : get_driver ( const std : : string & name ) const
2020-03-04 18:05:57 +03:00
{
auto driver = drivers . find ( name ) ;
if ( driver = = drivers . end ( ) )
{
return nullptr ;
}
return driver - > second . get ( ) ;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
2020-06-29 13:14:00 +03:00
template < typename D >
void DriverManager < D > : : register_action ( typename D : : message_t : : msg_enum t ,
2024-06-03 12:40:24 +03:00
std : : function < void ( std : : unique_ptr < typename D : : message_t > ) > a )
2020-03-04 18:05:57 +03:00
{
for ( auto & driver : drivers )
{
driver . second - > register_action ( t , a ) ;
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
2020-06-29 13:14:00 +03:00
template < typename D >
int DriverManager < D > : : start ( std : : string & error )
2020-03-04 18:05:57 +03:00
{
for ( auto & driver : drivers )
{
2024-09-05 17:25:03 +03:00
driver . second - > set_reconnect_callback ( std : : bind ( & DriverManager < D > : : reconnected , this ) ) ;
2020-03-04 18:05:57 +03:00
auto rc = driver . second - > start ( error ) ;
2024-09-05 17:25:03 +03:00
2020-03-04 18:05:57 +03:00
if ( rc ! = 0 )
{
2020-06-29 13:14:00 +03:00
NebulaLog : : error ( " DrM " , " Unable to start driver ' " + driver . first
2024-06-03 12:40:24 +03:00
+ " ': " + error ) ;
2020-03-04 18:05:57 +03:00
return rc ;
}
}
return 0 ;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
2020-06-29 13:14:00 +03:00
template < typename D >
void DriverManager < D > : : stop ( int secs )
2020-03-04 18:05:57 +03:00
{
2020-07-02 23:42:10 +03:00
std : : vector < std : : thread > threads ;
2020-04-13 19:03:11 +03:00
2020-03-04 18:05:57 +03:00
for ( auto & driver : drivers )
{
2020-04-16 19:15:07 +03:00
int _secs = secs ;
2024-06-03 12:40:24 +03:00
threads . push_back ( std : : thread ( [ _secs , & driver ] ( )
{
2020-04-16 19:15:07 +03:00
driver . second - > stop ( _secs ) ;
2020-04-13 19:03:11 +03:00
} ) ) ;
}
for ( auto & thr : threads )
{
thr . join ( ) ;
2020-03-04 18:05:57 +03:00
}
}
2020-06-29 13:14:00 +03:00
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
template < typename D >
int DriverManager < D > : : add ( const std : : string & name , std : : unique_ptr < D > driver )
{
auto rc = drivers . insert ( std : : make_pair ( name , std : : move ( driver ) ) ) ;
if ( ! rc . second )
{
// Driver already exists
return - 1 ;
}
return 0 ;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
template < typename D >
void DriverManager < D > : : check_time_outs_action ( )
{
time_t the_time = time ( 0 ) ;
std : : lock_guard < std : : mutex > lock ( _mutex ) ;
auto it = sync_requests . begin ( ) ;
while ( it ! = sync_requests . end ( ) )
{
if ( ( it - > second - > time_out ! = 0 ) & & ( the_time > it - > second - > time_out ) )
{
SyncRequest * ar = it - > second ;
sync_requests . erase ( it + + ) ;
ar - > result = false ;
ar - > timeout = true ;
ar - > message = " Request timeout " ;
ar - > notify ( ) ;
}
else
{
+ + it ;
}
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
template < typename D >
void DriverManager < D > : : add_request ( SyncRequest * ar )
{
static int request_id = 0 ;
std : : lock_guard < std : : mutex > lock ( _mutex ) ;
ar - > id = request_id + + ;
2024-06-03 12:40:24 +03:00
sync_requests . insert ( sync_requests . end ( ) , std : : make_pair ( ar - > id , ar ) ) ;
2020-06-29 13:14:00 +03:00
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
template < typename D >
SyncRequest * DriverManager < D > : : get_request ( int id )
{
SyncRequest * ar = nullptr ;
std : : lock_guard < std : : mutex > lock ( _mutex ) ;
auto it = sync_requests . find ( id ) ;
if ( it ! = sync_requests . end ( ) )
{
ar = it - > second ;
sync_requests . erase ( it ) ;
}
return ar ;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
template < typename D >
void DriverManager < D > : : notify_request ( int id , bool result , const std : : string & message )
{
SyncRequest * ar = get_request ( id ) ;
if ( ar = = 0 )
{
return ;
}
ar - > result = result ;
if ( message ! = " - " )
{
if ( ! ar - > message . empty ( ) )
{
ar - > message . append ( " ; " ) ;
}
ar - > message . append ( message ) ;
}
ar - > notify ( ) ;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
template < typename D >
Log : : MessageType DriverManager < D > : : log_type ( char type )
{
auto log_type = Log : : INFO ;
switch ( type )
{
case ' E ' :
log_type = Log : : ERROR ;
break ;
case ' W ' :
log_type = Log : : WARNING ;
break ;
case ' D ' :
log_type = Log : : DEBUG ;
break ;
}
return log_type ;
}
2020-03-04 18:05:57 +03:00
# endif // DRIVER_MANAGER_H_