diff options
Diffstat (limited to 'modules/CIAO/DAnCE/NodeManager')
-rw-r--r-- | modules/CIAO/DAnCE/NodeManager/BaseMonitor.h | 63 | ||||
-rw-r--r-- | modules/CIAO/DAnCE/NodeManager/CIAO_Monitor.cpp | 155 | ||||
-rw-r--r-- | modules/CIAO/DAnCE/NodeManager/CIAO_Monitor.h | 107 | ||||
-rw-r--r-- | modules/CIAO/DAnCE/NodeManager/Monitor.mpc | 28 | ||||
-rw-r--r-- | modules/CIAO/DAnCE/NodeManager/MonitorCB.cpp | 59 | ||||
-rw-r--r-- | modules/CIAO/DAnCE/NodeManager/MonitorCB.h | 73 | ||||
-rw-r--r-- | modules/CIAO/DAnCE/NodeManager/MonitorController.cpp | 234 | ||||
-rw-r--r-- | modules/CIAO/DAnCE/NodeManager/MonitorController.h | 123 | ||||
-rw-r--r-- | modules/CIAO/DAnCE/NodeManager/NAM_Map.cpp | 52 | ||||
-rw-r--r-- | modules/CIAO/DAnCE/NodeManager/NAM_Map.h | 72 | ||||
-rw-r--r-- | modules/CIAO/DAnCE/NodeManager/NodeManager.mpc | 33 | ||||
-rw-r--r-- | modules/CIAO/DAnCE/NodeManager/NodeManager_Impl.cpp | 698 | ||||
-rw-r--r-- | modules/CIAO/DAnCE/NodeManager/NodeManager_Impl.h | 341 | ||||
-rw-r--r-- | modules/CIAO/DAnCE/NodeManager/Node_Manager.cpp | 288 | ||||
-rw-r--r-- | modules/CIAO/DAnCE/NodeManager/README | 13 |
15 files changed, 2339 insertions, 0 deletions
diff --git a/modules/CIAO/DAnCE/NodeManager/BaseMonitor.h b/modules/CIAO/DAnCE/NodeManager/BaseMonitor.h new file mode 100644 index 00000000000..d05e798b523 --- /dev/null +++ b/modules/CIAO/DAnCE/NodeManager/BaseMonitor.h @@ -0,0 +1,63 @@ +// $Id$ +//---------------------------------------------------------------------------------- +/// Monitor Interface +/* + * @file BaseMonitor.h + * @brief The BaseMonitor.h file. + * This is an abstract class containing the interface to the Monitor plug-in + * + * @author Nilabja R <nilabjar@dre.vanderbilt.edu> + */ +//---------------------------------------------------------------------------------- + +#ifndef MONITOR_BASEH +#define MONITOR_BASEH +#include "tao/ORB.h" +#include "ciao/Deployment_TargetManagerC.h" + +namespace CIAO +{ + + class MonitorBase + { + public: + virtual ~MonitorBase () {}; + + /** + * This function is called by the controller to initialize + * parameters. + * @param domain The Initital domain for this host + * @param target_manager TargetManager_ptr + * @param interval The time interval after which updates need to be send. + */ + virtual int initialize_params ( + ::Deployment::Domain& domain, + ::Deployment::TargetManager_ptr target_manager, + int interval + )=0; + /** + * This function is called by the controller + * to start up the monitor. + * @param orb The ORB pointer + */ + virtual int start (CORBA::ORB_ptr orb) = 0; + /** + * This function is called by the controller + * to stop the monitor. + */ + virtual int stop ()=0; + /** + * This function is called by the controller + * to get the current data. + * @return The current Domain data + */ + virtual ::Deployment::Domain* get_current_data ()=0; + }; + + extern "C" ACE_Proper_Export_Flag CIAO::MonitorBase * + createMonitor (void); + +} // CIAO + + +#endif /* MONITOR_BASEH */ diff --git a/modules/CIAO/DAnCE/NodeManager/CIAO_Monitor.cpp b/modules/CIAO/DAnCE/NodeManager/CIAO_Monitor.cpp new file mode 100644 index 00000000000..9d9417da520 --- /dev/null +++ b/modules/CIAO/DAnCE/NodeManager/CIAO_Monitor.cpp @@ -0,0 +1,155 @@ +// $Id$ +//========================================================================== +/// The RSS Monitor class defination +/** + * @file CIAO_Monitor.cpp + * + * @brief The Monitor class defination + * + * @author Nilabja Roy <nilabjar@dre.vanderbilt.edu> + */ +//========================================================================== + +#include "CIAO_Monitor.h" +#include "CIAO_common.h" +#include "ace/OS_NS_stdio.h" + +extern "C" ACE_Proper_Export_Flag CIAO::MonitorBase * CIAO::createMonitor () +{ + CIAO::CIAO_Monitor* monitor = 0; + ACE_NEW_RETURN (monitor, CIAO::CIAO_Monitor, 0); + return monitor; +} + +CIAO::CIAO_Monitor::CIAO_Monitor () +{ +} + +/// The Desctructor +CIAO::CIAO_Monitor::~CIAO_Monitor () +{ +} + +int CIAO::CIAO_Monitor::initialize_params ( + ::Deployment::Domain& domain, + ::Deployment::TargetManager_ptr target_manager, + int interval + ) +{ + current_domain_.reset (new ::Deployment::Domain (domain)); + target_ptr_= target_manager; + this->interval_=interval; + + return 0; +} + +int CIAO::CIAO_Monitor::start (CORBA::ORB_ptr) +{ + return 0; +} + +int CIAO::CIAO_Monitor::stop () +{ + return 0; +} + +::Deployment::Domain* CIAO::CIAO_Monitor::get_current_data () +{ + if (CIAO::debug_level () > 9) + { + // ACE_DEBUG ((LM_DEBUG , + // "CIAO_Monitor::Inside the get_current_data of[%s]\n", + // current_domain_->node[0].name.in ())); + } + + CORBA::Double current_load = 0; + + long user_cpu; + long user_cpu_low; + long sys_cpu; + long idle_time; + + // get the load average value from the /proc/loadavg + + FILE *load_file = 0; + + load_file = ACE_OS::fopen ("/proc/stat", "r"); + + if (load_file == 0) + { + // load file cannot be opened .. + current_load = 0; + } + else + { + char buffer [99]; + + // read in the cpu label + fscanf (load_file, "%s", buffer); + + //read the user_cpu + fscanf (load_file, "%ld", &user_cpu); + + //read the user cpu low priority + fscanf (load_file, "%ld", &user_cpu_low); + + //read the system cpu + fscanf (load_file, "%ld", &sys_cpu); + + //read the cpu in idle time .. + fscanf (load_file, "%ld", &idle_time); + + ACE_OS::fclose (load_file); + + // Calculate the percent CPU + long const current_user_cpu = user_cpu - prev_user_cpu_; + long const total_cpu_usage = user_cpu + user_cpu_low + sys_cpu + + idle_time - prev_user_cpu_ - prev_idle_time_ - prev_sys_cpu_ + - prev_user_cpu_low_; + + current_load = (current_user_cpu * 100)/total_cpu_usage; + + // Save the current cpu values in the previous variables + + prev_user_cpu_ = user_cpu; + + prev_user_cpu_low_ = user_cpu_low; + + prev_sys_cpu_ = sys_cpu; + + prev_idle_time_ = idle_time; + + } + + + CORBA::Any any; + any <<= current_load; + + // here insert the util value, in the right position + + for (unsigned int i = 0; + i < current_domain_->node[0].resource.length (); + i++) + { + if (!ACE_OS::strcmp (current_domain_->node[0].resource[i].name, "Processor")) + { + for (unsigned int j = 0; + j < current_domain_->node[0].resource[i].property.length (); + j++) + { + if (!ACE_OS::strcmp ( + current_domain_ + ->node[0].resource[i].property[j].name.in (), + "LoadAverage")) + { + current_domain_->node[0].resource[i].property[j].kind = + ::Deployment::Quantity; + current_domain_->node[0].resource[i].property[j].value = + any; + } + } + } + } + + return current_domain_.get (); +} diff --git a/modules/CIAO/DAnCE/NodeManager/CIAO_Monitor.h b/modules/CIAO/DAnCE/NodeManager/CIAO_Monitor.h new file mode 100644 index 00000000000..5a134538701 --- /dev/null +++ b/modules/CIAO/DAnCE/NodeManager/CIAO_Monitor.h @@ -0,0 +1,107 @@ +// $Id$ +//========================================================================== +/** + * @file CIAO_Monitor.h + * + * @brief The Monitor class. + * + * This class periodically records the loadavg value of the machine in which it + * loaded + * + * @author Nilabja Roy <nilabjar@dre.vanderbilt.edu> + */ +//========================================================================== + + +#ifndef CIAO_MONITORH +#define CIAO_MONITORH + +#include "BaseMonitor.h" +#include "ace/Auto_Ptr.h" + +/** + * @namespace CIAO + * + * @brief The top level CIAO namespace + * + */ +namespace CIAO +{ + class ReceiverThread; + + /** + * @class CIAO_Monitor + * + * @brief The Monitor class + * + */ + class CIAO_Monitor : public MonitorBase + { + public: + + /** @function Constructor + */ + CIAO_Monitor (); + + /** + * This function is called by the controller to initialize + * parameters. + * @param domain The Initial Domain for this host + * @param target_manager TargetManager_ptr + * @param interval The time interval after whic updates need to be send. + */ + virtual int initialize_params ( + ::Deployment::Domain& domain, + ::Deployment::TargetManager_ptr target_manager, + int interval + ); + /** + * Destructor + */ + virtual ~CIAO_Monitor (); + + /** + * This method will starts up the Monitor in this case, + * @param orb The orb needed for resolving. + * @return -1 on error + */ + int start (CORBA::ORB_ptr orb); + + /** + * This method will stop the Monitor in this case + * @return -1 on error + */ + int stop (); + + /** + * This function retrieves the current Domain data + * @return -1 on error + */ + ::Deployment::Domain* get_current_data (); + + protected: + + /// The TargetManager Object to be sent to the RSSSubscriber .. + ::Deployment::TargetManager_ptr target_ptr_; + + /// The interval after which update is to be returned. + int interval_; + + /// The Domain data structure + auto_ptr <Deployment::Domain> current_domain_; + + /// The previous user cpu + long prev_user_cpu_; + + /// The previous user cpu low priority + long prev_user_cpu_low_; + + /// The previous system cpu + long prev_sys_cpu_; + + /// The previous idle time + long prev_idle_time_; + }; + +} // CIAO +#endif /* CIAO_MONITORH */ diff --git a/modules/CIAO/DAnCE/NodeManager/Monitor.mpc b/modules/CIAO/DAnCE/NodeManager/Monitor.mpc new file mode 100644 index 00000000000..9ccc91f0025 --- /dev/null +++ b/modules/CIAO/DAnCE/NodeManager/Monitor.mpc @@ -0,0 +1,28 @@ +// $Id$ + + +// MPC file for the Monitor + +project(*monitorlib): ciao_client_dnc, ciao_events_base_dnc { + after += CIAO_TargetManager_stub + includes += $(CIAO_ROOT)/DAnCE/TargetManager + sharedname = ciaomonlib + + libs += TargetManager_stub CIAO_Deployment_stub NodeManager_stub + + IDL_Files { + } + + Header_Files { + } + + Inline_Files { + } + + Template_Files { + } + + Source_Files { + CIAO_Monitor.cpp + } +} diff --git a/modules/CIAO/DAnCE/NodeManager/MonitorCB.cpp b/modules/CIAO/DAnCE/NodeManager/MonitorCB.cpp new file mode 100644 index 00000000000..56a789a76a3 --- /dev/null +++ b/modules/CIAO/DAnCE/NodeManager/MonitorCB.cpp @@ -0,0 +1,59 @@ +// $Id$ +//---------------------------------------------------------------------------------- +/** + * @file MonitorCB.cpp + * + * @brief The Monitor Update class + * + * The class which updates the resource data + * + * @author Nilabja Roy <nilabjar@dre.vanderbilt.edu> + */ +//---------------------------------------------------------------------------------- + +#include "MonitorCB.h" +#include "CIAO_common.h" + + +CIAO::MonitorCB::MonitorCB ( + CORBA::ORB_ptr orb, + Deployment::TargetManager_ptr target, + int interval) : + orb_ (orb), + target_mgr_ (target), + interval_ (interval) +{ +} + +int CIAO::MonitorCB::update_data (::Deployment::Domain& data) +{ + CORBA::StringSeq elements; + elements.length (0); + + // data to be updated ... + ::Deployment::DomainUpdateKind update_kind + = ::Deployment::UpdateAvailable; + + // The copy of the domain variable + ::Deployment::Domain_var domain + = new ::Deployment::Domain (data); + + try + { + if (CIAO::debug_level () > 20) + { + ACE_DEBUG ((LM_DEBUG , "CIAO::NM::MonitorCB::Making a call to update\n")); + } + target_mgr_->updateDomain (elements , domain , update_kind); + } + catch (CORBA::Exception& ) + { + //ACE_DEBUG ((LM_DEBUG, "CIAO::NM::MonitorCB::Unknown Exception\n")); + //ex._tao_print_exception ("NM::MonitorCB::updateDomain"); + } + catch (...) + { + // ignore + } + return 0; +} diff --git a/modules/CIAO/DAnCE/NodeManager/MonitorCB.h b/modules/CIAO/DAnCE/NodeManager/MonitorCB.h new file mode 100644 index 00000000000..777625bc9e0 --- /dev/null +++ b/modules/CIAO/DAnCE/NodeManager/MonitorCB.h @@ -0,0 +1,73 @@ +// $Id$ +//============================================================== +/** + * @file MonitorCB.h + * + * @brief The Monitor Callback Function + * + * This class updates data back to the Target Manager + * + * @author Nilabja Roy <nilabjar.vanderbilt.edu> +*/ +//============================================================== + +#ifndef MONITOR_CBH +#define MONITOR_CBH + +#include "ciao/Deployment_TargetManagerC.h" + +/** + * @namespace CIAO + * + * @brief The top level CIAO namespace + * + */ + +namespace CIAO +{ + /** + * @class MonitorCB + * + * @brief Updates data back to the TM. + * + */ + + class MonitorCB + { + public: + /** + * @param orb The ORB pointer + * @param target The TargetManager reference + * @param interval The time interval to sent update + */ + MonitorCB (CORBA::ORB_ptr orb, Deployment::TargetManager_ptr target, int interval); + /** + * This function is called by the monitor to + * update Domain data, which is then sent to + * TM. + * @param data Contains the updated Domain data + * @return int indicates success. + * @todo Check return value, seems not used at this moment + */ + int update_data (::Deployment::Domain& data); + private: + /// The ORB pointer + /// @todo Make this a _var + CORBA::ORB_ptr orb_; + + /// The Target Manager pointer to send back the + /// update + /// @todo Make this a _var + ::Deployment::TargetManager_ptr target_mgr_; + + /// The interval after which updates need to be send + int interval_; + + }; + + /// The Callback function pointer + typedef int (MonitorCB::*CallBack) (::Deployment::Domain &); + +} // CIAO namespace + +#endif /* MONITOR_CBH */ diff --git a/modules/CIAO/DAnCE/NodeManager/MonitorController.cpp b/modules/CIAO/DAnCE/NodeManager/MonitorController.cpp new file mode 100644 index 00000000000..76bd148613b --- /dev/null +++ b/modules/CIAO/DAnCE/NodeManager/MonitorController.cpp @@ -0,0 +1,234 @@ +// $Id$ + +//---------------------------------------------------------------------------------- +/** + * @file MonitorController.cpp + * + * @brief The Monitor Controller implementation. + * + * This is the facade class for Monitor + * + * @author Nilabja Roy <nilabjar@dre.vanderbilt.edu> + */ +//---------------------------------------------------------------------------------- + +#include "MonitorController.h" +#include "BaseMonitor.h" +#include "MonitorCB.h" +#include "CIAO_common.h" + +#include "ace/Log_Msg.h" +#include "ace/DLL.h" +#include "ace/SString.h" + +#include "NodeManager_Impl.h" + +namespace CIAO +{ + typedef MonitorBase* (*MonitorFactory) (void); + + /// for the CIAO monitor + const char* monitor_lib_name = "ciaomonlib"; + + // The interval after which update will be sent. + // This value will sent by the EM in the later implementation + const int interval = 10; + + static const char* factory_func = "createMonitor"; +} + +CIAO::MonitorController::MonitorController ( + ::CORBA::ORB_ptr orb, + ::Deployment::Domain& domain, + ::Deployment::TargetManager_ptr target, + ::CIAO::NodeManager_Impl_Base* node_mgr + ) + : target_facet_i_ (::Deployment::TargetManager::_duplicate (target)), + terminate_flag_ (0), + orb_ (orb), + initial_domain_ (domain), + node_mgr_ (node_mgr), + monitor_cpu_usage_ (false), + add_component_pid_ (true) +{ +} + +int +CIAO::MonitorController::svc (void) +{ + // @todo. Investigate whether we can't use the reactor with a timer + // eventhandler for this monitor controller, would safe us a thread + ACE_DLL dll; + + // Forming the library name. + ACE_CString lib_name = ACE_DLL_PREFIX; + lib_name += monitor_lib_name; + int retval = dll.open (lib_name.c_str ()); + + if (retval != 0) + { + ACE_ERROR_RETURN ((LM_ERROR, + "%p", + "dll.open"), + -1); + } + + // Cast the void* to non-pointer type first - it's not legal to + // cast a pointer-to-object directly to a pointer-to-function. + void *void_ptr = dll.symbol (factory_func); + ptrdiff_t tmp = reinterpret_cast<ptrdiff_t> (void_ptr); + MonitorFactory factory = reinterpret_cast<MonitorFactory> (tmp); + + if (factory == 0) + { + ACE_ERROR_RETURN ((LM_ERROR, + "%p", + "dll.symbol"), + -1); + } + + { + ACE_TRACE ((LM_DEBUG, "Inside the init call\n")); + + // Creating the monitor object. + monitor_.reset ((MonitorBase*) factory ()); + monitor_->initialize_params (initial_domain_, + target_facet_i_.in (), + interval); + + + // Start the Monitor. + monitor_->start (orb_); + auto_ptr <CIAO::MonitorCB> monitor_callback (new CIAO::MonitorCB (orb_, + target_facet_i_.in (), + interval)); + + // check if cpu needs to be monitored or not + for (unsigned int i = 0;i < initial_domain_.node[0].resource.length ();i++) + { + if (!strcmp (initial_domain_.node[0].resource[i].name, "Processor")) + monitor_cpu_usage_ = true; + } + + // Wait for system to stabilize itself + ACE_OS::sleep (interval); + + // The loop in which UpdateData is called + while (!terminating ()) + { + + //ACE_DEBUG ((LM_DEBUG , "=The Terminate is %d\n", terminate_flag_)); + + + // if monitoring of cpu is enable , monitor , else dont do + // anything + ::Deployment::Domain* domain = 0; + + if (monitor_cpu_usage_) + domain = monitor_->get_current_data (); + else + domain = &initial_domain_; + + // ****** add component data ******************* + + NodeManager_Impl_Base::Component_Ids cids = + node_mgr_->get_component_detail (); + + // Here save the old resource length + int counter = domain->node[0].resource.length (); + + // if pid is already added , dont add + if (add_component_pid_) + { + // then add more resource element to the + // domain structure + // ACE_DEBUG ((LM_DEBUG , "Going to add CID/PID data\n")); + int new_res_size = domain->node[0].resource.length () + + cids.cid_seq_.size (); + + domain->node[0].resource.length (new_res_size); + + ACE_Unbounded_Set_Iterator<ACE_CString> iter (cids.cid_seq_); + + for (iter = cids.cid_seq_.begin (); + iter != cids.cid_seq_.end (); + iter++,counter++) + { + domain->node[0].resource[counter].name = + CORBA::string_dup ("Component"); + domain->node[0].resource[counter].resourceType.length (0); + + // Have one property for now + domain->node[0].resource[counter].property.length (1); + domain->node[0].resource[counter].property[0].name = + CORBA::string_dup ((*iter).c_str ()); + domain->node[0].resource[counter].property[0].kind = + ::Deployment::Quantity; + domain->node[0].resource[counter].property[0].dynamic = + 0; + domain->node[0].resource[counter].property[0].value <<= + CORBA::Long (cids.process_id_); + + // ACE_DEBUG ((LM_DEBUG , "The process id is [%d]\n", + // CORBA::Long (cids.process_id_))); + } + // set the add_component_pid_ to 0 + add_component_pid_ = false; + } + + //******add compoennt data + + monitor_callback->update_data (*domain); + + // data will be updated in intervals of 10 secs. + // in the latest version of spec , this value will + // come from Execution Manager + ACE_OS::sleep (interval); + + } + + monitor_->stop (); + } + + // here delete the monitor object before + // unloading the library + monitor_.reset (); + + // unload the library + dll.close (); + + if (CIAO::debug_level () > 9) + { + ACE_DEBUG ((LM_DEBUG , "CIAO::Monitor::Terminating Monitor\n")); + } + + return 0; +} + +CIAO::MonitorController::~MonitorController () +{ + terminate (); + wait (); +} + +void +CIAO::MonitorController::terminate () +{ + // make the terminate flag false + ACE_GUARD (ACE_SYNCH_MUTEX, + guard, + lock_); + + terminate_flag_ = true; +} + +bool +CIAO::MonitorController::terminating () +{ + ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, + guard, + lock_, + 0); + + return terminate_flag_; +} diff --git a/modules/CIAO/DAnCE/NodeManager/MonitorController.h b/modules/CIAO/DAnCE/NodeManager/MonitorController.h new file mode 100644 index 00000000000..4da2dfb322f --- /dev/null +++ b/modules/CIAO/DAnCE/NodeManager/MonitorController.h @@ -0,0 +1,123 @@ +// $Id$ + +//--------------------------------------------------------------------------------- +/** + * @file MonitorController.h + * + * @brief The Monitor Controller class. + * + * This class is invoked by the Nodemanager object and it + * in turn loads the proper Monitor which is strategised. + * + * @author Nilabja Roy + */ +//---------------------------------------------------------------------------------- +#ifndef MONITOR_CONTROLLER_H +#define MONITOR_CONTROLLER_H + +#include "NodeManager_svnt_export.h" +#include "Deployment_BaseC.h" + +#include "TargetManager/TargetManagerImplC.h" +#include "ace/Task.h" +#include "ace/Auto_Ptr.h" + +#include "ace/Synch_Traits.h" +#include "ace/Synch.h" + + +/** + * @namespace CIAO + * + * @brief The top level CIAO namespace + * + */ + +namespace CIAO +{ + + class MonitorBase; + + class NodeManager_Impl_Base; + + /** + * @class MonitorController + * + * @brief The Controller class + * + * Acts as a facade to the Monitor + * module + * + */ + class NodeManager_svnt_Export MonitorController : public ACE_Task_Base + { + public: + /** + * @brief The main function containing the + * entire activity. + * + * This function runs in the context of the + * thread + * @return int The status of the function + */ + int svc (void); + /** + * @brief The terminate function + * + * This function is called to terminate the + * thread + */ + void terminate (); + + + /// The Constructor. + MonitorController (CORBA::ORB_ptr orb, + ::Deployment::Domain& domain, + ::Deployment::TargetManager_ptr target, + ::CIAO::NodeManager_Impl_Base* node_mgr + ); + + ~MonitorController (); + protected: + + /** + * @brief returns the terminating flag + * @return bool The terminating state of the thread + */ + bool terminating (); + + /// The monitor object + auto_ptr <MonitorBase> monitor_; + + /// The TargetManagerImpl object + CIAO::TargetManagerImpl_var target_impl_cmp_; + + /// The TargetManager Facet .... + Deployment::TargetManager_var target_facet_i_; + + /// The terminate flag_ + bool terminate_flag_; + + /// Thread Mutex for synchronizing call + ACE_SYNCH_MUTEX lock_; + + /// the ORB pointer .. + /// @todo Make this a _var + CORBA::ORB_ptr orb_; + + /// The initial domain + ::Deployment::Domain initial_domain_; + + /// The Node Manager + ::CIAO::NodeManager_Impl_Base* node_mgr_; + + /// Flag tells ; what to monitor + bool monitor_cpu_usage_; + + /// To add component pid or not .. + bool add_component_pid_; + }; + +} // CIAO + +#endif diff --git a/modules/CIAO/DAnCE/NodeManager/NAM_Map.cpp b/modules/CIAO/DAnCE/NodeManager/NAM_Map.cpp new file mode 100644 index 00000000000..f3aebb307a2 --- /dev/null +++ b/modules/CIAO/DAnCE/NodeManager/NAM_Map.cpp @@ -0,0 +1,52 @@ +// $Id$ +#include "NAM_Map.h" +#include "ciao/CIAO_Config.h" +#include "ciao/CIAO_common.h" + +namespace CIAO +{ + NAM_Map::NAM_Map (void) + : map_ (CIAO_DEFAULT_MAP_SIZE) + { + } + + bool + NAM_Map::is_available (const ACE_CString &str) const + { + if (this->map_.find (str) == 0) + return true; + + return false; + } + + bool + NAM_Map::insert_nam (const ACE_CString &str, + const PortableServer::ObjectId &oid) + { + return (this->map_.bind (str, oid) == 0); + } + + ::PortableServer::ObjectId + NAM_Map::get_nam (const ACE_CString &str) + { + MAP::ENTRY *entry = 0; + + if (this->map_.find (str, entry) != 0) + return ::PortableServer::ObjectId (); + + return entry->int_id_.in (); + } + + bool + NAM_Map::remove_nam (const PortableServer::ObjectId &oid) + { + for (Iterator i = this->map_.begin (); + i != this->map_.end (); + ++i) + { + if ((*i).int_id_.in() == oid) + return this->map_.unbind ((*i).ext_id_) == 0; + } + return false; + } +} diff --git a/modules/CIAO/DAnCE/NodeManager/NAM_Map.h b/modules/CIAO/DAnCE/NodeManager/NAM_Map.h new file mode 100644 index 00000000000..4b398d51927 --- /dev/null +++ b/modules/CIAO/DAnCE/NodeManager/NAM_Map.h @@ -0,0 +1,72 @@ + /** + * @file NAM_Map.h + * @author Will Otte <wotte@dre.vanderbilt.edu> + * + * Map of NodeApplicationManagers, inspired by the DAM_Map + * class. + * + * $Id$ + */ + +#ifndef CIAO_NAM_MAP_H +#define CIAO_NAM_MAP_H + +#include /**/ "ace/pre.h" + +#include "tao/PortableServer/PortableServer.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "ace/Null_Mutex.h" +#include "ace/Hash_Map_Manager.h" +#include "ace/SString.h" + +namespace CIAO +{ + /** + * @class NAM_Map + * @brief Implementation of a map of NodeApplicationManagers. + * + * This table is used by the NodeManager to keep track of + * NAMs started for multiple assemblies. + */ + class NAM_Map + { + public: + /// Constructor + NAM_Map (void); + + /// Determine if there is a NAM associated with a UUID + bool is_available (const ACE_CString &str) const; + + /// Insert a NAM OID into the collection + bool insert_nam (const ACE_CString &str, + const PortableServer::ObjectId &oid); + + /// Get a specified NAM. + ::PortableServer::ObjectId + get_nam (const ACE_CString &str); + + /// Remove a nam from the map, given its oid. + bool remove_nam (const PortableServer::ObjectId &oid); + + private: + typedef + ACE_Hash_Map_Manager_Ex <ACE_CString, + ::PortableServer::ObjectId_var, + ACE_Hash<ACE_CString>, + ACE_Equal_To<ACE_CString>, + ACE_Null_Mutex> MAP; + + typedef MAP::iterator Iterator; + + MAP map_; + + }; +} + +#include /**/ "ace/post.h" + +#endif /*CIAO_NAM_MAP_H*/ diff --git a/modules/CIAO/DAnCE/NodeManager/NodeManager.mpc b/modules/CIAO/DAnCE/NodeManager/NodeManager.mpc new file mode 100644 index 00000000000..e58cc2d27d4 --- /dev/null +++ b/modules/CIAO/DAnCE/NodeManager/NodeManager.mpc @@ -0,0 +1,33 @@ +// -*- MPC -*- +// $Id$ + +//For static D&C, the NodeManager should be available as a linkable library +project(NodeManager_svnt): ciao_component_dnc, ciao_deployment_svnt, iortable, ifr_client, dance_extension_stub, ciao_server_dnc, ciao_nodeapplicationmanager, ciao_nodemanager_stub { + sharedname = NodeManager + dynamicflags = NODEMANAGER_SVNT_BUILD_DLL + + IDL_Files { + } + + Source_Files { + ../Interfaces/NodeManagerDaemonS.cpp + NodeManager_Impl.cpp + NAM_Map.cpp + MonitorController.cpp + MonitorCB.cpp + } +} + +project(NodeManager): ciao_server_dnc, iortable, ifr_client, dance_extension_stub, ciao_nodeapplicationmanager, ciao_targetmanager_stub, ciao_nodemanager_stub { + after += NodeManager_svnt + libs += NodeManager + exename = NodeManager + + IDL_Files { + } + + Source_Files { + Node_Manager.cpp + } +} + diff --git a/modules/CIAO/DAnCE/NodeManager/NodeManager_Impl.cpp b/modules/CIAO/DAnCE/NodeManager/NodeManager_Impl.cpp new file mode 100644 index 00000000000..5e8fea451cd --- /dev/null +++ b/modules/CIAO/DAnCE/NodeManager/NodeManager_Impl.cpp @@ -0,0 +1,698 @@ +// $Id$ + +#include "NodeManager_Impl.h" +#include "DAnCE/NodeApplicationManager/NodeApplicationManager_Impl.h" +#include "ace/Log_Msg.h" + +CIAO::NodeManager_Impl_Base::NodeManager_Impl_Base (const char *name, + CORBA::ORB_ptr orb, + PortableServer::POA_ptr poa, + const char * nodeapp_loc, + const char * nodeapp_options, + int spawn_delay) + ACE_THROW_SPEC ((CORBA::SystemException)) + : orb_ (CORBA::ORB::_duplicate (orb)), + poa_ (PortableServer::POA::_duplicate (poa)), + name_ (CORBA::string_dup (name)), + nodeapp_location_ (CORBA::string_dup (nodeapp_loc)), + nodeapp_options_ (CORBA::string_dup (nodeapp_options)), + callback_poa_ (PortableServer::POA::_nil ()), + spawn_delay_ (spawn_delay) +{ +} + +CIAO::NodeManager_Impl_Base::~NodeManager_Impl_Base () +{ +} + +void +CIAO::NodeManager_Impl_Base::init () + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + try + { + // Create the call back poa for NAM. + PortableServer::POAManager_var mgr + = this->poa_->the_POAManager (); + + this->callback_poa_ = + this->poa_->create_POA ("callback_poa", + mgr.in (), + 0); + } + catch (const CORBA::Exception& ex) + { + ex._tao_print_exception ("NodeManager_Impl::init\t\n"); + throw; + } +} + +PortableServer::POA_ptr +CIAO::NodeManager_Impl_Base::_default_POA (void) +{ + return PortableServer::POA::_duplicate (this->poa_.in ()); +} + + +char * +CIAO::NodeManager_Impl_Base::name () + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + return CORBA::string_dup (this->name_.in ()); +} + +void +CIAO::NodeManager_Impl_Base::shutdown () + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + + this->orb_->shutdown (0); +} + +void +CIAO::NodeManager_Impl_Base::joinDomain (const Deployment::Domain & domain, + Deployment::TargetManager_ptr target, + Deployment::Logger_ptr) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + // ACE_THROW (CORBA::NO_IMPLEMENT ()); + // Here start the Monitor + CIAO_TRACE("CIAO::NodeManager_Impl_Base::joinDomain"); + + ::Deployment::Domain this_domain = domain; + + monitor_controller_.reset ( + new MonitorController (orb_.in (), + this_domain, + target, + this)); + + if (CIAO::debug_level () > 9) + { + ACE_DEBUG ((LM_DEBUG , "Before Activate\n")); + } + + // Activate the Monitor Controller to + // start the monitoring + monitor_controller_->activate (); + + if (CIAO::debug_level () > 9) + { + ACE_DEBUG ((LM_DEBUG , "Monitor Activated\n")); + } +} + +void +CIAO::NodeManager_Impl_Base::leaveDomain () + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + // Delete the monitor , this will also terminate the thread + monitor_controller_.reset (); +} + +CORBA::Long +CIAO::NodeManager_Impl_Base::set_priority ( + const char * plan_id, + const char * cid, + const ::Deployment::Sched_Params & nm_params + ) + ACE_THROW_SPEC ((::CORBA::SystemException)) + +{ + ACE_CString key (plan_id); + key += "@"; + key += this->name_.in (); + + if (CIAO::debug_level () > 10) + { + ACE_DEBUG ((LM_DEBUG , "Inside the set_priority\n")); + ACE_DEBUG ((LM_DEBUG , "pid = [%s] , cid = [%s]\n", key.c_str () , cid)); + } + + try { + CORBA::Object_var obj = + this->poa_->id_to_reference (this->map_.get_nam (key)); + + Deployment::NodeApplicationManager_var nam = + Deployment::NodeApplicationManager::_narrow (obj.in ()); + + return nam->set_priority (cid, nm_params); + } + catch (CORBA::Exception& ex) + { + + ex._tao_print_exception ("(%P|%t) NodeManager_Impl::set_priority ()\t\n"); + throw; + } +} + +::Components::FacetDescriptions * +CIAO::NodeManager_Impl_Base:: +get_all_facets (ACE_CString & name) +{ + Component_Facets_Map::ENTRY *entry = 0; + + if (this->comp_facets_map_.find (name.c_str (), entry) != 0) + { + ACE_ERROR ((LM_ERROR, "(%P|%t) - NodeManager_Impl_Base::get_all_facets - " + "No component with name [%s] was found in the NodeManager\n", name.c_str ())); + } + + CORBA::ULong const facet_len = entry->int_id_->length (); + + Components::FacetDescriptions_var retv; + ACE_NEW_RETURN (retv, + Components::FacetDescriptions, + 0); + + retv->length (facet_len); + + for (CORBA::ULong i = 0; i < facet_len; ++i) + { + retv[i] = entry->int_id_[i]; + } + + return retv._retn (); +} + +::Components::ConsumerDescriptions * +CIAO::NodeManager_Impl_Base:: +get_all_consumers (ACE_CString & name) +{ + Component_Consumers_Map::ENTRY *entry = 0; + + if (this->comp_consumers_map_.find (name.c_str (), entry) != 0) + { + ACE_ERROR ((LM_ERROR, "(%P|%t) - NodeManager_Impl_Base::get_all_facets - " + "Component [%s] was not found in the NodeManager\n", name.c_str ())); + } + + CORBA::ULong const consumer_len = entry->int_id_->length (); + + Components::ConsumerDescriptions_var retv; + ACE_NEW_RETURN (retv, + Components::ConsumerDescriptions, + 0); + + retv->length (consumer_len); + + for (CORBA::ULong i = 0; i < consumer_len; ++i) + { + retv[i] = entry->int_id_[i]; + } + + return retv._retn (); +} + +void +CIAO::NodeManager_Impl_Base:: +set_all_facets (ACE_CString &name, + const ::Components::FacetDescriptions_var & facets) +{ + this->comp_facets_map_.rebind (name, facets); +} + +void +CIAO::NodeManager_Impl_Base:: +set_all_consumers (ACE_CString &name, + const ::Components::ConsumerDescriptions_var & consumers) +{ + this->comp_consumers_map_.rebind (name, consumers); +} + + +Deployment::NodeApplicationManager_ptr +CIAO::NodeManager_Impl_Base:: +preparePlan (const Deployment::DeploymentPlan &plan) + ACE_THROW_SPEC ((CORBA::SystemException, + Deployment::StartError, + Deployment::PlanError)) +{ + CIAO_TRACE("CIAO::NodeManager_Impl::preparePlan"); + + if (! this->validate_plan (plan)) + { + ACE_ERROR ((LM_ERROR, "(%P|%t) NodeManager <%s>:prepare_plan:Plan_Error.\n", + plan.instance[0].node.in ())); + ACE_ERROR ((LM_ERROR, "(%P|%t) All component instances hosted in the " + "same component server must have the " + "same \"resourceName\" defined.\n")); + + ACE_THROW_RETURN (Deployment::PlanError (), + Deployment::NodeApplicationManager::_nil ()); + } + + // Update the reference count map based on the deployment plan input + for (CORBA::ULong i = 0; i < plan.instance.length (); ++i) + { + Reference_Count_Map::ENTRY *entry = 0; + if (this->ref_count_map_.find (plan.instance[i].name.in (), entry) != 0) + { + // Create a new entry, set the initial ref count "1", and insert to the map. + Ref_Count_Info new_entry; + new_entry.plan_uuid_ = plan.UUID.in (); + new_entry.count_ = 1; + this->ref_count_map_.bind (plan.instance[i].name.in (), new_entry); + } + else + { + // If the instance is within the same deployment plan, e.g., + // when ReDaC service is used, then just do nothing since it is NOT + // actually a shared component at all. + if (ACE_OS::strcmp (plan.UUID.in (), + entry->int_id_.plan_uuid_.c_str ()) == 0) + continue; + + // Otherwise, it is really a shared component, so let's increase + // the ref count by 1 + this->shared_components_.insert (plan.instance[i].name.in ()); + ++ entry->int_id_.count_; + } + } + + // Create/find NodeApplicationManager and set/reset plan on it + try + { + if (!this->map_.is_available (plan.UUID.in ())) + { + if (CIAO::debug_level () > 10) + { + ACE_DEBUG ((LM_DEBUG, "NM:prepare_plan: " + "creating a new NAM with UUID: %s\n", + plan.UUID.in ())); + } + + // Implementation undefined. + CIAO::NodeApplicationManager_Impl_Base *node_app_mgr = + this->create_node_app_manager (this->orb_.in (), this->poa_.in ()); + + PortableServer::ServantBase_var safe (node_app_mgr); + + //@@ Note: after the init call the servant ref count would + // become 2. so we can leave the safeservant along and be + // dead. Also note that I added + PortableServer::ObjectId_var oid = + node_app_mgr->init (this->nodeapp_location_.in (), + this->nodeapp_options_.in (), + this->spawn_delay_, + plan, + this->callback_poa_.in (), + this // pass in a copy of ourself (servant object) + ); + + this->map_.insert_nam (plan.UUID.in (), oid.in ()); + + CORBA::Object_var obj = + this->poa_->id_to_reference (this->map_.get_nam (plan.UUID.in ())); + + // We should inform NAM about "shared" components, so they + // won't be instantiated again + Deployment::NodeApplicationManager_var nam = + Deployment::NodeApplicationManager::_narrow (obj.in ()); + + // Convert the ACE Set into CORBA sequence, and make the remote invocation + Deployment::ComponentPlans_var shared = + this->get_shared_components_i (); + nam->set_shared_components (shared.in ()); + + // narrow should return a nil reference if it fails. + return Deployment::NodeApplicationManager::_narrow (nam.in ()); + } + else + { + if (CIAO::debug_level () > 10) + { + ACE_DEBUG ((LM_DEBUG, "NM:prepare_plan: reusing an old NAM " + "with UUID: %s\n", + plan.UUID.in ())); + } + + CORBA::Object_var obj = + this->poa_->id_to_reference (this->map_.get_nam (plan.UUID.in ())); + + Deployment::NodeApplicationManager_var nam = + Deployment::NodeApplicationManager::_narrow (obj.in ()); + + nam->reset_plan (plan); + + // Similarly, we should inform NAM about "shared" components, so + // they won't be instantiated again + Deployment::ComponentPlans_var shared = + this->get_shared_components_i (); + nam->set_shared_components (shared.in ()); + + // Potentially we could reset many other configuration settings + // such as command line options, service configuration file, etc. + return nam._retn (); + } + } + catch (const PortableServer::POA::ObjectNotActive&) + { + ACE_THROW_RETURN (Deployment::StartError (), + Deployment::NodeApplicationManager::_nil ()); + } + catch (const CORBA::Exception& ex) + { + ex._tao_print_exception ("(%P|%t) NodeManager_Impl::preparePlan\t\n"); + throw; + } + + return Deployment::NodeApplicationManager::_nil (); +} + +void +CIAO::NodeManager_Impl_Base::destroyManager +(Deployment::NodeApplicationManager_ptr manager) + ACE_THROW_SPEC ((CORBA::SystemException, + Deployment::StopError, + Deployment::InvalidReference)) +{ + CIAO_TRACE("CIAO::NodeManager_Impl::destroyManager"); + try + { + // Deactivate this object + PortableServer::ObjectId_var id = + this->poa_->reference_to_id (manager); + + if (!this->map_.remove_nam (id.in ())) + { + ACE_ERROR ((LM_ERROR, + "NodeManager_Impl::destroyManager: " + "Unable to remove object from map!\n")); + } + + this->poa_->deactivate_object (id.in ()); + } + catch (const PortableServer::POA::WrongAdapter&) + { + ACE_ERROR ((LM_ERROR, + "NodeManager_Impl::destroyManager: EXCEPTION - " + "Invalid reference passed to destroyManager\n")); + + throw ::Deployment::InvalidReference (); + } + catch (const PortableServer::POA::ObjectNotActive&) + { + ACE_ERROR ((LM_ERROR, + "NodeManager_Impl::destroyManager: EXCEPTION - " + " asked to destroy an already inactive object.\n")); + throw ::Deployment::InvalidReference (); + } + catch (const CORBA::Exception& ex) + { + ex._tao_print_exception ("NodeManager_Impl::destroyManager\t\n"); + throw; + } +} + +void +CIAO::NodeManager_Impl_Base:: +destroyPlan (const Deployment::DeploymentPlan & plan) + ACE_THROW_SPEC ((::CORBA::SystemException, + ::Deployment::StopError)) +{ + // Update the reference counting map (subtract by 1 for each instance) + // If the ref count becomes 0, then remove this component, otherwise, + // we should remove the necesary bindings on this component specified + // in the deployment plan. + + // Clean up the cached "Facets" and "Consumers" map of the components + // if their ref count become 0 + CORBA::ULong const length = plan.instance.length (); + for (CORBA::ULong i = 0; i < length; ++i) + { + ACE_DEBUG ((LM_DEBUG, "NM_DP - forloop instance %s\n", + plan.instance[i].name.in ())); + + Reference_Count_Map::ENTRY *entry = 0; + if (this->ref_count_map_.find (plan.instance[i].name.in (), entry) == 0) + { + --entry->int_id_.count_; // decrease ref count by 1 + + if (entry->int_id_.count_ == 0) + { + // Remove this component from the shared set + ACE_DEBUG ((LM_DEBUG, "\tremoving shared...\n")); + this->shared_components_.remove (plan.instance[i].name.in ()); + ACE_DEBUG ((LM_DEBUG, "\tunbinding from the ref count map\n")); + // Unbind this component from the ref_count_map_ + this->ref_count_map_.unbind (plan.instance[i].name.in ()); + + ACE_DEBUG ((LM_DEBUG, "\tunbinding from the facet/consumer maps\n")); + // Unbind this component from the facet/consumer maps + if (this->comp_facets_map_.unbind ( + plan.instance[i].name.in ()) != 0 || + this->comp_consumers_map_.unbind ( + plan.instance[i].name.in ()) != 0) + { + throw + (Deployment::StopError ("NodeManager_Impl_Base::destroyPlan ", + "Unable to find component instance")); + } + } + } + } + + // Find the NAM from the map and invoke the destroyPlan() operation on + // it, which will actuall remove components and connections in this plan. + // If + CORBA::Object_var obj = + this->poa_->id_to_reference (this->map_.get_nam (plan.UUID.in ())); + + Deployment::NodeApplicationManager_var nam = + Deployment::NodeApplicationManager::_narrow (obj.in ()); + + + // Reset each NAM about the shared components information + Deployment::ComponentPlans_var shared = this->get_shared_components_i (); + nam->set_shared_components (shared.in ()); + + nam->destroyApplication (0); + + // @@ The problem is that we should NOT actually kill the NA process if + // there are some components that are shared by other plans. +} + +Deployment::ComponentPlans * +CIAO::NodeManager_Impl_Base:: +get_shared_components () + ACE_THROW_SPEC ((::CORBA::SystemException)) +{ + return this->get_shared_components_i (); +} + +Deployment::ComponentPlans * +CIAO::NodeManager_Impl_Base::get_shared_components_i (void) +{ + Deployment::ComponentPlans_var retv; + ACE_NEW_RETURN (retv, + Deployment::ComponentPlans, + 0); + retv->length (0); + + ACE_Unbounded_Set<ACE_CString>::iterator + end = this->shared_components_.end (); + + for (ACE_Unbounded_Set<ACE_CString>::iterator + iter = this->shared_components_.begin (); + iter != end; + ++iter) + { + CORBA::ULong const curr_len = retv->length (); + retv->length (curr_len + 1); + (*retv)[curr_len].name = (*iter).c_str (); + + // Fill in the plan_uuid information about this component, by + // searching in the ref_count_map_ + Reference_Count_Map::ENTRY *entry = 0; + if (this->ref_count_map_.find ((*iter).c_str (), entry) == 0) + { + // Get the plan_uuid_ info and populate the field + (*retv)[curr_len].plan_uuid = entry->int_id_.plan_uuid_.c_str (); + } + else + { + // should never happen + ACE_ERROR ((LM_ERROR, "Component [%s] in the list of shared component, " + "was not found in the NodeManager ref count map.\n", + (*iter).c_str ())); + } + } + + return retv._retn (); +} + + +CORBA::StringSeq * +CIAO::NodeManager_Impl_Base::shared_components_seq (void) +{ + CORBA::StringSeq * retv = 0; + ACE_NEW_RETURN (retv, CORBA::StringSeq, 0); + retv->length (0); + + // @todo rewrite to just set the length once and then copy the strings + // to reduce allocations + + ACE_Unbounded_Set<ACE_CString>::iterator end = this->shared_components_.end (); + for (ACE_Unbounded_Set<ACE_CString>::iterator + iter = this->shared_components_.begin (); + iter != end; + ++iter) + { + CORBA::ULong const curr_len = retv->length (); + retv->length (curr_len + 1); + (*retv)[curr_len] = (*iter).c_str (); + } + + return retv; +} + +bool +CIAO::NodeManager_Impl_Base:: +validate_plan (const Deployment::DeploymentPlan &plan) +{ + const char * resource_id = 0; + CORBA::ULong i = 0; + + // Update the name of ourself + this->name_ = plan.instance[0].node.in (); + + for (i = 0; i < plan.instance.length (); ++i) + { + if (plan.instance[i].deployedResource.length () != 0) + { + // Since the "name" field represents the server_resource_id, and + // the "resourceValue" field represents the policy_set_id, so we + // are checking to make sure that all component instances have + // the same server_resource_id. + + resource_id = + plan.instance[i].deployedResource[0].resourceName.in (); + break; + } + } + if (i == plan.instance.length ()) // No server resource id has been set for any instance + return true; + + for (i = 0; i < plan.instance.length (); ++i) + { + const char * my_resource_id = 0; + if (plan.instance[i].deployedResource.length () == 0) + { + continue; + } + else + { + my_resource_id = + plan.instance[i].deployedResource[0].resourceName.in ();; + if (ACE_OS::strcmp (resource_id, my_resource_id) != 0) + { + // Error, inconsistent server resource id found. + return false; + } + } + } + return true; +} + + +void CIAO::NodeManager_Impl_Base:: +push_component_id_info (Component_Ids comps) +{ + components_ = comps; +} + +CIAO::NodeManager_Impl_Base::Component_Ids +CIAO::NodeManager_Impl_Base:: +get_component_detail () +{ + return components_; +} + +CIAO::NodeManager_Impl::~NodeManager_Impl () +{ +} + +CIAO::NodeManager_Impl:: +NodeManager_Impl (const char *name, + CORBA::ORB_ptr orb, + PortableServer::POA_ptr poa, + const char * nodeapp_loc, + const char * nodeapp_options, + int spawn_delay) + : NodeManager_Impl_Base (name, orb, poa, nodeapp_loc, nodeapp_options, spawn_delay) +{} + + +::CIAO::NodeApplicationManager_Impl_Base * +CIAO::NodeManager_Impl:: +create_node_app_manager (CORBA::ORB_ptr orb, + PortableServer::POA_ptr poa) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + CIAO::NodeApplicationManager_Impl_Base *app_mgr = 0; + ACE_NEW_THROW_EX (app_mgr, + CIAO::NodeApplicationManager_Impl (orb, + poa), + CORBA::NO_MEMORY ()); + return app_mgr; +} + +CIAO::Static_NodeManager_Impl::~Static_NodeManager_Impl () +{ +} + +CIAO::Static_NodeManager_Impl:: +Static_NodeManager_Impl (const char *name, + CORBA::ORB_ptr orb, + PortableServer::POA_ptr poa, + const char * nodeapp_loc, + const char * nodeapp_options, + int spawn_delay, + Static_Config_EntryPoints_Maps* static_config_entrypoints_maps) + : NodeManager_Impl_Base (name, orb, poa, nodeapp_loc, nodeapp_options, spawn_delay), + static_config_entrypoints_maps_ (static_config_entrypoints_maps) +{} + +::CIAO::NodeApplicationManager_Impl_Base * +CIAO::Static_NodeManager_Impl:: +create_node_app_manager (CORBA::ORB_ptr orb, + PortableServer::POA_ptr poa) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + if (CIAO::debug_level () > 10) + { + ACE_DEBUG ((LM_DEBUG, "creating static_node_app_manager\n")); + } + + CIAO::NodeApplicationManager_Impl_Base *app_mgr = 0; + ACE_NEW_THROW_EX (app_mgr, + CIAO::Static_NodeApplicationManager_Impl (orb, + poa, + this->static_config_entrypoints_maps_), + CORBA::NO_MEMORY ()); + return app_mgr; +} + +void +CIAO::Static_NodeManager_Impl::destroyManager +(Deployment::NodeApplicationManager_ptr manager) + ACE_THROW_SPEC ((CORBA::SystemException, + Deployment::StopError, + Deployment::InvalidReference)) +{ + CIAO_TRACE("CIAO::Static_NodeManager_Impl::destroyManager"); + try + { + CIAO::NodeManager_Impl_Base::destroyManager (manager); + + this->orb_->shutdown (0); + + } + catch (const CORBA::Exception& ex) + { + ex._tao_print_exception ("Static_NodeManager_Impl::destroyManager\t\n"); + throw; + } + +} diff --git a/modules/CIAO/DAnCE/NodeManager/NodeManager_Impl.h b/modules/CIAO/DAnCE/NodeManager/NodeManager_Impl.h new file mode 100644 index 00000000000..cea98f0fa91 --- /dev/null +++ b/modules/CIAO/DAnCE/NodeManager/NodeManager_Impl.h @@ -0,0 +1,341 @@ +// -*- C++ -*- +//============================================================================= +/** + * @file NodeManager_Impl.h + * + * $Id$ + * + * This file contains servant implementation for Deployment:NodeManager + * interface. In the current design of the NodeManager, each NodeManager + * could manage one or more NodeApplication Managers. + * Though, the name intuitively suggests + * that there be one NodeManager for every node, our design, allows + * the end-user to have multiple components run on the same node. + * + * @author Arvind S. Krishna <arvindk@dre.vanderbilt.edu> + * @author Gan Deng <dengg@dre.vanderbilt.edu> + */ +//============================================================================= + + +#ifndef CIAO_NODEMANAGER_IMPL_H +#define CIAO_NODEMANAGER_IMPL_H +#include /**/ "ace/pre.h" + +#include "Interfaces/NodeManagerDaemonS.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#if defined (_MSC_VER) +# pragma warning(push) +# pragma warning (disable:4250) +#endif /* _MSC_VER */ + +#include "NodeManager_svnt_export.h" +#include "NAM_Map.h" +#include "MonitorController.h" +#include "ace/Vector_T.h" + +namespace CIAO +{ + class NodeApplicationManager_Impl_Base; + + /** + * @class NodeManager_Impl + * + * @brief Servant implementation CIAO's daemon process control + * interface + * + * This class implements the CIAO:NodeManagerDaemon interface. + * + */ + class NodeManager_svnt_Export NodeManager_Impl_Base + : public virtual POA_CIAO::NodeManagerDaemon + { + public: + /// A struct that tracks the reference count of a particular + /// component as well as the "child_plan_uuid" where the component is + /// actually installed + typedef struct _ref_count_info + { + ACE_CString plan_uuid_; + size_t count_; + } Ref_Count_Info; + + /// Constructor + NodeManager_Impl_Base (const char *name, + CORBA::ORB_ptr orb, + PortableServer::POA_ptr p, + const char * nodeapp_loc, + const char* nodeapp_options, + int spawn_delay) + ACE_THROW_SPEC ((CORBA::SystemException)); + + /// Initializes the NodeManager. + virtual void init () + ACE_THROW_SPEC ((CORBA::SystemException)); + + /// POA operation.. + virtual PortableServer::POA_ptr _default_POA (void); + + /// CIAO::Daemon defined attributes/operations. + virtual char * name () + ACE_THROW_SPEC ((CORBA::SystemException)); + + virtual void shutdown () + ACE_THROW_SPEC ((CORBA::SystemException)); + + virtual void joinDomain (const Deployment::Domain & domain, + Deployment::TargetManager_ptr manager, + Deployment::Logger_ptr log + ) + ACE_THROW_SPEC ((CORBA::SystemException)); + + virtual void leaveDomain () + ACE_THROW_SPEC ((CORBA::SystemException)); + + virtual ::Deployment::NodeApplicationManager_ptr + preparePlan (const Deployment::DeploymentPlan &plan) + ACE_THROW_SPEC ((CORBA::SystemException, + Deployment::StartError, + Deployment::PlanError)); + + virtual void + destroyManager (Deployment::NodeApplicationManager_ptr appManager) + ACE_THROW_SPEC ((CORBA::SystemException, + Deployment::StopError, + Deployment::InvalidReference)); + + /// CIAO specific extension, which is particularly useful for dealing with + /// shared components issue + virtual void destroyPlan (const Deployment::DeploymentPlan & plan) + ACE_THROW_SPEC ((::CORBA::SystemException, + ::Deployment::StopError)); + + /// CIAO specific extension, return a set of shared components + virtual ::Deployment::ComponentPlans * + get_shared_components () + ACE_THROW_SPEC ((::CORBA::SystemException)); + + /// RACE specific extension. Modify the priority of a node application + /// process. + + virtual ::CORBA::Long + set_priority ( + const char * plan_id, + const char * cid, + const ::Deployment::Sched_Params & nm_params) + ACE_THROW_SPEC ((::CORBA::SystemException)); + + // ********* CIAO Specific Helper functions ************ + + virtual ::Components::FacetDescriptions * + get_all_facets (ACE_CString & name); + + virtual ::Components::ConsumerDescriptions * + get_all_consumers (ACE_CString & name); + + virtual void + set_all_facets (ACE_CString &name, + const ::Components::FacetDescriptions_var & facets); + + virtual void + set_all_consumers (ACE_CString &name, + const ::Components::ConsumerDescriptions_var & consumers); + + // ********* Function added for getting component ids... + + struct Component_Ids + { + ACE_Unbounded_Set <ACE_CString> cid_seq_; + pid_t process_id_; + }; + + virtual void push_component_id_info (Component_Ids comps); + + + Component_Ids get_component_detail (); + + private: + /// Validate the child deployment plan. In particular, we are + /// trying to verify that all the component instances within this + /// child deployment plan have the same "server_resource_id" + /// assigned. + bool validate_plan (const Deployment::DeploymentPlan &plan); + + protected: + /// Since this class is reference counted, making this + /// destructor protected to enforce proper memory managment + /// through the reference counting mechanism (i.e. to + /// disallow calling operator delete() on an instance of + /// this class. + virtual ~NodeManager_Impl_Base (void); + + virtual ::CIAO::NodeApplicationManager_Impl_Base * + create_node_app_manager (CORBA::ORB_ptr orb, + PortableServer::POA_ptr poa) + ACE_THROW_SPEC ((CORBA::SystemException))=0; + + /// Actual implementation of the @c get_shared_components IDL operation + virtual ::Deployment::ComponentPlans * + get_shared_components_i (void); + + /// A helper method that convert ACE_Unbounded_Set to CORBA StringSeq + CORBA::StringSeq * shared_components_seq (void); + + /// Keep a pointer to the managing ORB serving this servant. + CORBA::ORB_var orb_; + + /// Keep a pointer to the managing POA. + PortableServer::POA_var poa_; + + /// My Canonical name. + CORBA::String_var name_; + + /// NodeApplication location + CORBA::String_var nodeapp_location_; + + /// NodeApplication options + CORBA::String_var nodeapp_options_; + + /// Cached callback POA. + PortableServer::POA_var callback_poa_; + + /// Spawn delay for the NodeAppMgr + int spawn_delay_; + + /// Cache reference of last NodeAppManager + /// Deployment::NodeApplicationManager_var manager_; + NAM_Map map_; + + /// A reference count map for the components installed on this node + /// @@TODO We should also keep the information about *where* the + /// component is installed + typedef + ACE_Hash_Map_Manager_Ex <ACE_CString, + Ref_Count_Info, + ACE_Hash<ACE_CString>, + ACE_Equal_To<ACE_CString>, + ACE_Null_Mutex> Reference_Count_Map; + typedef Reference_Count_Map::iterator Ref_Count_Iterator; + + Reference_Count_Map ref_count_map_; + + /// A set to track the names of shared component instances + ACE_Unbounded_Set<ACE_CString> shared_components_; + + /// Cached object references of ports (facets/consumers) of + /// all components. This is useful for getting the port object + /// references of "shared components". The key in the map + /// is the component instance name. + typedef + ACE_Hash_Map_Manager_Ex <ACE_CString, + Components::FacetDescriptions_var, + ACE_Hash<ACE_CString>, + ACE_Equal_To<ACE_CString>, + ACE_Null_Mutex> Component_Facets_Map; + + Component_Facets_Map comp_facets_map_; + + typedef + ACE_Hash_Map_Manager_Ex <ACE_CString, + Components::ConsumerDescriptions_var, + ACE_Hash<ACE_CString>, + ACE_Equal_To<ACE_CString>, + ACE_Null_Mutex> Component_Consumers_Map; + + Component_Consumers_Map comp_consumers_map_; + + /// The MonitorController pointer + auto_ptr <MonitorController> monitor_controller_; + + /// The set of Components + Component_Ids components_; + }; + + + /** + * @class NodeManager_Impl + * + */ + class NodeManager_svnt_Export NodeManager_Impl + : public virtual NodeManager_Impl_Base + { + public: + + /// Constructor + NodeManager_Impl (const char *name, + CORBA::ORB_ptr orb, + PortableServer::POA_ptr p, + const char * nodeapp_loc, + const char * nodeapp_options, + int spawn_delay); + + protected: + /// Since this class is reference counted, making this + /// destructor protected to enforce proper memory managment + /// through the reference counting mechanism (i.e. to + /// disallow calling operator delete() on an instance of + /// this class. + virtual ~NodeManager_Impl (void); + + virtual ::CIAO::NodeApplicationManager_Impl_Base * + create_node_app_manager (CORBA::ORB_ptr orb, + PortableServer::POA_ptr poa) + ACE_THROW_SPEC ((CORBA::SystemException)); + }; + + class NodeApplicationManager_Impl; + struct Static_Config_EntryPoints_Maps; + + /** + * @class Static_NodeManager_Impl + * + */ + class NodeManager_svnt_Export Static_NodeManager_Impl + : public virtual NodeManager_Impl_Base + { + public: + + /// Constructor + Static_NodeManager_Impl (const char *name, + CORBA::ORB_ptr orb, + PortableServer::POA_ptr p, + const char * nodeapp_loc, + const char * nodeapp_options, + int spawn_delay, + Static_Config_EntryPoints_Maps* static_config_entrypoints_maps + ); + + void destroyManager + (Deployment::NodeApplicationManager_ptr manager) + ACE_THROW_SPEC ((CORBA::SystemException, + Deployment::StopError, + Deployment::InvalidReference)); + + protected: + /// Since this class is reference counted, making this + /// destructor protected to enforce proper memory managment + /// through the reference counting mechanism (i.e. to + /// disallow calling operator delete() on an instance of + /// this class. + virtual ~Static_NodeManager_Impl (void); + + virtual ::CIAO::NodeApplicationManager_Impl_Base * + create_node_app_manager (CORBA::ORB_ptr orb, + PortableServer::POA_ptr poa) + ACE_THROW_SPEC ((CORBA::SystemException)); + + Static_Config_EntryPoints_Maps* static_config_entrypoints_maps_; + }; + +} + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif /* _MSC_VER */ + +#include /**/ "ace/post.h" +#endif /* CIAO_NODEMANAGER_IMPL_H */ diff --git a/modules/CIAO/DAnCE/NodeManager/Node_Manager.cpp b/modules/CIAO/DAnCE/NodeManager/Node_Manager.cpp new file mode 100644 index 00000000000..7a10e719cc0 --- /dev/null +++ b/modules/CIAO/DAnCE/NodeManager/Node_Manager.cpp @@ -0,0 +1,288 @@ +// $Id$ + +#include "NodeManager_Impl.h" +#include "orbsvcs/CosNamingC.h" +#include "tao/IORTable/IORTable.h" +#include "ace/SString.h" +#include "ace/Read_Buffer.h" +#include "ace/Get_Opt.h" +#include "ace/OS_NS_stdio.h" +#include "ace/OS_NS_unistd.h" +#include "ace/os_include/os_netdb.h" +#include "ciao/Server_init.h" +#include "ciao/CIAO_common.h" + +const char *ior_file_name_ = "nodedaemon.ior"; +char *nodeapp_location_ = 0; +const char *pid_file_name_ = 0; +bool write_to_ior_ = false; +bool register_with_ns_ = false; +int nodeapp_loc_ = 0; +int spawn_delay = 1; + +ACE_CString nodeapp_options_; + +int +parse_args (int argc, char *argv[]) +{ + ACE_Get_Opt get_opts (argc, argv, "o:c:m:s:d:na:p:z:"); + int c; + + while ((c = get_opts ()) != -1) + { + switch (c) + { + case 'z': + nodeapp_options_ += " -ORBDebugLevel "; + nodeapp_options_ += get_opts.opt_arg (); + break; + + case 'o': // Get the file name to write to. + ior_file_name_ = get_opts.opt_arg (); + write_to_ior_ = true; + break; + + case 'c': // Get the default svc.conf filename. + nodeapp_options_ += " -ORBSvcConf "; + nodeapp_options_ += get_opts.opt_arg (); + break; + + case 's': // Get the location to spawn the NodeApplication. + nodeapp_location_ = get_opts.opt_arg (); + nodeapp_loc_ = 1; + break; + + case 'a': // Nodeapplication arguments. + nodeapp_options_ = get_opts.opt_arg (); + break; + + case 'd': // Get the spawn delay argument. + spawn_delay = ACE_OS::atoi (get_opts.opt_arg ()); + break; + + case 'n': + register_with_ns_ = true; + break; + + case 'p': + pid_file_name_ = get_opts.opt_arg (); + break; + + case '?': // Display help for use of the server. + default: + ACE_ERROR_RETURN ((LM_ERROR, + "usage: %s\n" + "-o <ior_output_file>\n" + "-c <svc.conf file>\n" + "-n <use naming service>\n" + "-s <NodeApplication executable path>\n" + "-a <arguments to NodeApplication>\n" + "-d <spawn delay for nodeapplication>\n" + "-p <pid file>\n" + "\n", + argv [0]), + -1); + break; + } + } + + return 0; +} + +int +write_IOR (const char* ior) +{ + FILE* ior_output_file_ = + ACE_OS::fopen (ior_file_name_, "w"); + + if (ior_output_file_) + { + ACE_OS::fprintf (ior_output_file_, + "%s", + ior); + ACE_OS::fclose (ior_output_file_); + } + + return 0; +} + +void +write_pid (void) +{ + if (pid_file_name_ == 0) + { + return; + } + + FILE* pid_file = ACE_OS::fopen (pid_file_name_, "w"); + + if (pid_file) + { + ACE_OS::fprintf (pid_file, + "%i", + ACE_OS::getpid ()); + ACE_OS::fclose (pid_file); + } +} + +bool +register_with_ns (const char * name_context, + CORBA::ORB_ptr orb, + CIAO::NodeManagerDaemon_ptr obj) +{ + // Naming Service related operations + CORBA::Object_var naming_context_object = + orb->resolve_initial_references ("NameService"); + + CosNaming::NamingContext_var naming_context = + CosNaming::NamingContext::_narrow (naming_context_object.in ()); + + // Initialize the Naming Sequence + CosNaming::Name name (1); + name.length (1); + name[0].id = name_context; + + try + { + // Register the servant with the Naming Service + naming_context->bind (name, obj); + } + catch (CosNaming::NamingContext::AlreadyBound &) + { + ACE_DEBUG ((LM_DEBUG, "Node_Manager.cpp: Name already bound, rebinding....\n")); + naming_context->rebind (name, obj); + } + + return true; +} + +int +main (int argc, char *argv[]) +{ + try + { + // Initialize orb + // @@TODO: Add error checking. There is absoluteley none. + CORBA::ORB_var orb = CORBA::ORB_init (argc, + argv, + ""); + + CIAO::Server_init (orb.in ()); + + if (parse_args (argc, argv) != 0) + return -1; + + // Check if NodeApplication executable location has been + // specified + if (! nodeapp_loc_) + { + ACE_DEBUG ((LM_DEBUG, "Use -s <NodeApplicationPath> to specify \ + executable path\n")); + ACE_OS::exit (1); + } + + // Get reference to Root POA. + CORBA::Object_var obj + = orb->resolve_initial_references ("RootPOA"); + + PortableServer::POA_var poa + = PortableServer::POA::_narrow (obj.in ()); + + CORBA::Object_var table_object = + orb->resolve_initial_references ("IORTable"); + + IORTable::Table_var adapter = + IORTable::Table::_narrow (table_object.in ()); + + if (CORBA::is_nil (adapter.in ())) + { + ACE_ERROR_RETURN ((LM_ERROR, "Nil IORTable\n"), -1); + } + + // Create and install the CIAO NodeManager servant + CIAO::NodeManager_Impl *node_manager_servant = 0; + ACE_NEW_RETURN (node_manager_servant, + CIAO::NodeManager_Impl("NodeManager", + orb.in (), + poa.in (), + nodeapp_location_, + nodeapp_options_.c_str (), + spawn_delay), + -1); + + PortableServer::ServantBase_var safe_daemon (node_manager_servant); + + node_manager_servant->init (); + + // Implicit activation + CIAO::NodeManagerDaemon_var node_manager = + node_manager_servant->_this (); + + CORBA::String_var str = + orb->object_to_string (node_manager.in ()); + + adapter->bind ("NodeManager", + str.in ()); + + if (write_to_ior_) + { + write_IOR (str.in ()); + } + else if (register_with_ns_) + { + char name [MAXHOSTNAMELEN + 1]; + + if (ACE_OS::hostname (name, MAXHOSTNAMELEN + 1) == -1) + { + ACE_ERROR ((LM_ERROR, + "gethostname call failed! \n")); + ACE_OS::exit (1); + } + + // Register this name with the Naming Service + (void) register_with_ns (name, + orb.in (), + node_manager.in ()); + } + + ACE_DEBUG ((LM_INFO, "CIAO_NodeManager IOR: %s\n", str.in ())); + + // Activate POA manager + PortableServer::POAManager_var mgr + = poa->the_POAManager (); + + mgr->activate (); + + // Here start the Monitor + /* + MonitorController* monitor_controller + = new MonitorController (orb); + + ACE_DEBUG ((LM_DEBUG , "Before Activate")); + monitor_controller->activate (); + ACE_DEBUG ((LM_DEBUG , "After Activate")); + */ + + // Finishing Deployment part + ACE_DEBUG ((LM_DEBUG, + "CIAO_NodeManager is running...\n")); + + write_pid (); + + // Run the main event loop for the ORB. + orb->run (); + + poa->destroy (1, 1); + + orb->destroy (); + } + catch (const CORBA::Exception& ex) + { + ex._tao_print_exception ("CIAO_NodeManager::main\t\n"); + return 1; + } + + ACE_DEBUG ((LM_DEBUG, + "CIAO_NodeManager has closed\n")); + return 0; +} diff --git a/modules/CIAO/DAnCE/NodeManager/README b/modules/CIAO/DAnCE/NodeManager/README new file mode 100644 index 00000000000..dda9201e240 --- /dev/null +++ b/modules/CIAO/DAnCE/NodeManager/README @@ -0,0 +1,13 @@ +/** + +@page NodeManager README File + + CIAO's NodeManager implementation. NodeManager is the bootstraping +mechanism to create new NodeApplication on the localhost. We +currently depend on starting the NodeApplicationManager process on +some port of all the hosts that have NodeApplication install to +function properly. The port to run this daemon can be set by using the +TAO ORB options command of -ORBEndpoint <port>. This replaces the +earlier CIAO_Daemon implementation of CIAO as defined in the CCM +specification. +*/ |