manager.py
Go to the documentation of this file.
00001 # -*- Python -*-
00002 # -*- coding: utf-8 -*-
00003 
00004 '''rtctree
00005 
00006 Copyright (C) 2009-2014
00007     Geoffrey Biggs
00008     RT-Synthesis Research Group
00009     Intelligent Systems Research Institute,
00010     National Institute of Advanced Industrial Science and Technology (AIST),
00011     Japan
00012     All rights reserved.
00013 Licensed under the Eclipse Public License -v 1.0 (EPL)
00014 http://www.opensource.org/licenses/eclipse-1.0.txt
00015 
00016 Object representing a manager node in the tree.
00017 
00018 '''
00019 
00020 
00021 from omniORB import CORBA, TRANSIENT_ConnectFailed, UNKNOWN_UserException
00022 import os.path
00023 import sys
00024 
00025 from rtctree.component import Component
00026 from rtctree.exceptions import FailedToLoadModuleError, \
00027                                FailedToCreateComponentError, \
00028                                FailedToDeleteComponentError, \
00029                                FailedToSetConfigurationError, \
00030                                FailedToAddMasterManagerError, \
00031                                FailedToRemoveMasterManagerError, \
00032                                FailedToAddSlaveManagerError, \
00033                                FailedToRemoveSlaveManagerError
00034 from rtctree.node import TreeNode
00035 from rtctree.utils import nvlist_to_dict
00036 import RTC
00037 
00038 
00039 ##############################################################################
00040 ## Manager node object
00041 
00042 class Manager(TreeNode):
00043     '''Node representing a manager on a name server.
00044 
00045     Manager nodes can occur below name server and directory nodes. They may
00046     store child components and child managers. They can be used to add and
00047     remove new components and managers to the tree at run time.
00048 
00049     '''
00050     def __init__(self, name=None, parent=None, obj=None, *args, **kwargs):
00051         '''Constructor. Calls the TreeNode constructor.'''
00052         super(Manager, self).__init__(name=name, parent=parent, *args,
00053                                       **kwargs)
00054         self._obj = obj
00055         self._parse()
00056 
00057     ##########################################################################
00058     # Module and component management
00059 
00060     def create_component(self, module_name):
00061         '''Create a component out of a loaded module.
00062 
00063         Turns a previously-loaded shared module into a component in the
00064         manager. This will invalidate any objects that are children of this
00065         node.
00066 
00067         The @ref module_name argument can contain options that set various
00068         properties of the new component. These must be appended to the module
00069         name, prefixed by a question mark for each property, in key=value
00070         format. For example, to change the instance name of the new component,
00071         append '?instance_name=new_name' to the module name.
00072 
00073         @param module_name Name of the module to turn into a component.
00074         @raises FailedToCreateComponentError
00075 
00076         '''
00077         with self._mutex:
00078             if not self._obj.create_component(module_name):
00079                 raise FailedToCreateComponentError(module_name)
00080             # The list of child components will have changed now, so it must be
00081             # reparsed.
00082             self._parse_component_children()
00083 
00084     def delete_component(self, instance_name):
00085         '''Delete a component.
00086 
00087         Deletes the component specified by @ref instance_name from the manager.
00088         This will invalidate any objects that are children of this node.
00089 
00090         @param instance_name The instance name of the component to delete.
00091         @raises FailedToDeleteComponentError
00092 
00093         '''
00094         with self._mutex:
00095             if self._obj.delete_component(instance_name) != RTC.RTC_OK:
00096                 raise FailedToDeleteComponentError(instance_name)
00097             # The list of child components will have changed now, so it must be
00098             # reparsed.
00099             self._parse_component_children()
00100 
00101     def load_module(self, path, init_func):
00102         '''Load a shared library.
00103 
00104         Call this function to load a shared library (DLL file under Windows,
00105         shared object under UNIX) into the manager.
00106 
00107         @param path The path to the shared library.
00108         @param init_func The name entry function in the library.
00109         @raises FailedToLoadModuleError
00110 
00111         '''
00112         try:
00113             with self._mutex:
00114                 if self._obj.load_module(path, init_func) != RTC.RTC_OK:
00115                     raise FailedToLoadModuleError(path)
00116         except CORBA.UNKNOWN, e:
00117             if e.args[0] == UNKNOWN_UserException:
00118                 raise FailedToLoadModuleError(path, 'CORBA User Exception')
00119             else:
00120                 raise
00121 
00122     def unload_module(self, path):
00123         '''Unload a loaded shared library.
00124 
00125         Call this function to remove a shared library (e.g. a component) that
00126         was previously loaded.
00127 
00128         @param path The path to the shared library.
00129         @raises FailedToUnloadModuleError
00130 
00131         '''
00132         with self._mutex:
00133             if self._obj.unload_module(path) != RTC.RTC_OK:
00134                 raise FailedToUnloadModuleError(path)
00135 
00136     @property
00137     def components(self):
00138         '''The list of components in this manager, if any.
00139 
00140         This information can also be found by listing the children of this node
00141         that are of type @ref Component. That method is more useful as it returns
00142         the tree entries for the components.
00143 
00144         '''
00145         with self._mutex:
00146             if not self._components:
00147                 self._components = [c for c in self.children if c.is_component]
00148         return self._components
00149 
00150     @property
00151     def factory_profiles(self):
00152         '''The factory profiles of all loaded modules.'''
00153         with self._mutex:
00154             if not self._factory_profiles:
00155                 self._factory_profiles = []
00156                 for fp in self._obj.get_factory_profiles():
00157                     self._factory_profiles.append(nvlist_to_dict(fp.properties))
00158         return self._factory_profiles
00159 
00160     ##########################################################################
00161     # Manager configuration
00162 
00163     def set_config_parameter(self, param, value):
00164         '''Set a configuration parameter of the manager.
00165 
00166         @param The parameter to set.
00167         @value The new value for the parameter.
00168         @raises FailedToSetConfigurationError
00169 
00170         '''
00171         with self._mutex:
00172             if self._obj.set_configuration(param, value) != RTC.RTC_OK:
00173                 raise FailedToSetConfigurationError(param, value)
00174             # Force a reparse of the configuration
00175             self._configuration = None
00176 
00177     @property
00178     def configuration(self):
00179         '''The configuration dictionary of the manager.'''
00180         with self._mutex:
00181             if not self._configuration:
00182                 self._configuration = nvlist_to_dict(self._obj.get_configuration())
00183         return self._configuration
00184 
00185     @property
00186     def profile(self):
00187         '''The manager's profile.'''
00188         with self._mutex:
00189             if not self._profile:
00190                 profile = self._obj.get_profile()
00191                 self._profile = nvlist_to_dict(profile.properties)
00192         return self._profile
00193 
00194     ##########################################################################
00195     # Undocumented functions
00196 
00197     def fork(self):
00198         '''Fork the manager.'''
00199         with self._mutex:
00200             self._obj.fork()
00201 
00202     def shutdown(self):
00203         '''Shut down the manager.'''
00204         with self._mutex:
00205             self._obj.shutdown()
00206 
00207     def restart(self):
00208         '''Restart the manager.'''
00209         with self._mutex:
00210             self._obj.restart()
00211 
00212     ##########################################################################
00213     # Node functionality
00214 
00215     @property
00216     def is_directory(self):
00217         '''Is this node a directory?'''
00218         return True
00219 
00220     @property
00221     def is_manager(self):
00222         '''Is this node a manager?'''
00223         return True
00224 
00225 
00226     @property
00227     def object(self):
00228         '''The RTM::Manager object that this node contains.'''
00229         with self._mutex:
00230             return self._obj
00231 
00232     @property
00233     def is_master(self):
00234         '''Is this manager node a master manager?
00235 
00236         Master managers have a direct presence on the name server. Slave
00237         managers are only present as children of other managers.
00238 
00239         '''
00240         with self._mutex:
00241             return self._obj.is_master()
00242 
00243     @property
00244     def loadable_modules(self):
00245         '''The list of loadable module profile dictionaries.'''
00246         with self._mutex:
00247             if not self._loadable_modules:
00248                 self._loadable_modules = []
00249                 for mp in self._obj.get_loadable_modules():
00250                     self._loadable_modules.append(nvlist_to_dict(mp.properties))
00251         return self._loadable_modules
00252 
00253     @property
00254     def loaded_modules(self):
00255         '''The list of loaded module profile dictionaries.'''
00256         with self._mutex:
00257             if not self._loaded_modules:
00258                 self._loaded_modules = []
00259                 for mp in self._obj.get_loaded_modules():
00260                     self._loaded_modules.append(nvlist_to_dict(mp.properties))
00261         return self._loaded_modules
00262 
00263     @property
00264     def masters(self):
00265         '''The list of master managers of this manager, if any.
00266 
00267         If this manager is a master, this list will be empty.
00268 
00269         '''
00270         with self._mutex:
00271             if not self._masters:
00272                 raise NotImplementedError
00273         return self._masters
00274 
00275     @property
00276     def slaves(self):
00277         '''The list of slave managers of this manager, if any.
00278 
00279         This information can also be found by listing the children of this node
00280         that are of type @ref Manager.
00281 
00282         '''
00283         with self._mutex:
00284             if not self._slaves:
00285                 self._slaves = [c for c in self.children if c.is_manager]
00286         return self._slaves
00287 
00288     ##########################################################################
00289     # Internal functions
00290 
00291     def _add_master(self, new_master):
00292         # Add a new master to this manager. A slave manager can have multiple
00293         # masters. new_master should be a rtctree.manager.Manager object.
00294         with self._mutex:
00295             if self._obj.add_master_manager(new_master.object) != RTC.RTC_OK:
00296                 raise FailedToAddMasterManagerError
00297 
00298     def _add_slave(self, new_slave):
00299         # Add a slave to this manager. Master managers can hold slave managers,
00300         # which appear as child nodes in the tree. It will appear in the tree
00301         # as a new child node of this manager's node if the tree is reparsed.
00302         # new_slave should be a rtctree.manager.Manager object.
00303         with self._mutex:
00304             if self._obj.add_save_manager(new_slave.object) != RTC.RTC_OK:
00305                 raise FailedToAddSlaveManagerError(self.name, new_slave.name)
00306 
00307     def _parse(self):
00308         # Nearly everything is delay-parsed when it is first accessed.
00309         with self._mutex:
00310             self._components = None
00311             self._configuration = None
00312             self._profile = None
00313             self._factory_profiles = None
00314             self._loadable_modules = None
00315             self._loaded_modules = None
00316             self._masters = None
00317             self._slaves = None
00318             self._parse_children()
00319 
00320     def _parse_children(self):
00321         # Parses child managers and components.
00322         with self._mutex:
00323             self._parse_component_children()
00324             self._parse_manager_children()
00325 
00326     def _parse_component_children(self):
00327         # Parses the list returned by _obj.get_components into child nodes.
00328         with self._mutex:
00329             try:
00330                 comps = self._obj.get_components()
00331             except CORBA.BAD_PARAM, e:
00332                 print >>sys.stderr, '{0}: {1}'.format(
00333                         os.path.basename(sys.argv[0]), e)
00334                 return
00335             for c in comps:
00336                 # Get the instance profile - this will be the node's name
00337                 profile = c.get_component_profile()
00338                 instance_name = profile.instance_name
00339                 # Create and store the new leaf node
00340                 leaf = Component(instance_name + '.rtc', self, c)
00341                 self._add_child(leaf)
00342 
00343     def _parse_manager_children(self):
00344         # Parses the list returned by _obj.get_slave_managers into child nodes.
00345         with self._mutex:
00346             try:
00347                 mgrs = self._obj.get_slave_managers()
00348             except CORBA.BAD_OPERATION:
00349                 # This manager does not support slave managers; ignore
00350                 return
00351             index = 0
00352             for m in mgrs:
00353                 # Add each slave manager as a child node.
00354                 try:
00355                     props = nvlist_to_dict(m.get_profile().properties)
00356                 except CORBA.TRANSIENT, e:
00357                     if e.args[0] == TRANSIENT_ConnectFailed:
00358                         print >>sys.stderr, '{0}: Warning: zombie slave of '\
00359                                 'manager {1} found'.format(sys.argv[0],
00360                                         self.name)
00361                         continue
00362                     else:
00363                         raise
00364                 if 'name' in props:
00365                     name = props['name']
00366                 else:
00367                     name = 'slave{0}'.format(index)
00368                     index += 1
00369                 leaf = Manager(name, self, m)
00370                 self._add_child(leaf)
00371 
00372     def _remove_master(self, master):
00373         # Remove a new master from this manager. A slave manager can have multiple
00374         # masters. new_master should be a rtctree.manager.Manager object.
00375         with self._mutex:
00376             if self._obj.remove_master_manager(master.object) != RTC.RTC_OK:
00377                 raise FailedToRemoveMasterManagerError
00378 
00379     def _remove_slave(self, slave):
00380         # Remove a slave from this manager. Master managers can hold slave
00381         # managers, which appear as child nodes in the tree. slave should be a
00382         # rtctree.manager.Manager object.
00383         with self._mutex:
00384             if self._obj.remove_slave_manager(slave.object) != RTC.RTC_OK:
00385                 raise FailedToRemoveSlaveManagerError(self.name, slave.name)
00386 
00387     def _set_parent(self, new_parent):
00388         # When setting the parent of a manager node, we need to tell wrapped
00389         # object that it has a new master. If our old parent was a master, then
00390         # we need to remove ourselves from that one.
00391         # Note that rtctree assumes a singly-linked hierarchy of managers.
00392         with self._mutex:
00393             if self.parent:
00394                 if self.parent.is_manager:
00395                     self.parent._remove_slave(self)
00396                     self._remove_master(self.parent)
00397             self._add_master(new_parent)
00398             new_parent._add_slave(self)
00399             self.parent = new_parent
00400 
00401 
00402 # vim: tw=79
00403 


rtctree
Author(s): Geoffrey Biggs
autogenerated on Wed Aug 26 2015 16:13:08