00001
00002
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 directory node in the tree.
00017
00018 '''
00019
00020
00021 from copy import deepcopy
00022 import CosNaming
00023 from omniORB import URI, CORBA, TRANSIENT_ConnectFailed
00024 import sys
00025
00026 from rtctree.component import Component
00027 from rtctree.exceptions import BadPathError
00028 from rtctree.manager import Manager
00029 from rtctree.node import TreeNode
00030 from rtctree.options import Options
00031 from rtctree.unknown import Unknown
00032 from rtctree.zombie import Zombie
00033 from rtctree.utils import filtered, trim_filter
00034 import RTC
00035 import RTM
00036
00037
00038
00039
00040
00041 class Directory(TreeNode):
00042 '''Node representing a naming context on a name server.
00043
00044 Name servers contain contexts (including the root context) and objects. For
00045 us, contexts are directories and objects are managers and components. A
00046 directory context may specialise as a name server context, in which case
00047 it represents the root context of a name server.
00048
00049 '''
00050 def __init__(self, name=None, parent=None, children=None, filter=[], *args,
00051 **kwargs):
00052 '''Constructor. Calls the TreeNode constructor.'''
00053 super(Directory, self).__init__(name=name, parent=parent,
00054 children=children, filter=filter, *args, **kwargs)
00055
00056 def reparse(self):
00057 '''Reparse all children of this directory.
00058
00059 This effectively rebuilds the tree below this node.
00060
00061 This operation takes an unbounded time to complete; if there are a lot
00062 of objects registered below this directory's context, they will all
00063 need to be parsed.
00064
00065 '''
00066 self._remove_all_children()
00067 self._parse_context(self._context, self.orb)
00068
00069 def unbind(self, name):
00070 '''Unbind an object from the context represented by this directory.
00071
00072 Warning: this is a dangerous operation. You may unlink an entire
00073 section of the tree and be unable to recover it. Be careful what you
00074 unbind.
00075
00076 The name should be in the format used in paths. For example,
00077 'manager.mgr' or 'ConsoleIn0.rtc'.
00078
00079 '''
00080 with self._mutex:
00081 id, sep, kind = name.rpartition('.')
00082 if not id:
00083 id = kind
00084 kind = ''
00085 name = CosNaming.NameComponent(id=str(id), kind=str(kind))
00086 try:
00087 self.context.unbind([name])
00088 except CosNaming.NamingContext.NotFound:
00089 raise BadPathError(name)
00090
00091 @property
00092 def context(self):
00093 '''The object representing this naming context.'''
00094 with self._mutex:
00095 return self._context
00096
00097 @property
00098 def is_directory(self):
00099 '''Is this node a directory?'''
00100 return True
00101
00102 def _parse_context(self, context, orb, filter=[]):
00103 with self._mutex:
00104
00105 self._context = context
00106
00107 bindings, bindings_it = context.list(Options().\
00108 get_option('max_bindings'))
00109 for binding in bindings:
00110
00111 self._process_binding(binding, orb, filter)
00112 if bindings_it:
00113
00114 remaining, bindings = bindings_it.next_n(Options().\
00115 get_option('max_bindings'))
00116 while remaining:
00117 for binding in bindings:
00118 self._process_binding(binding, orb, filter)
00119 remaining, binding = bindings_it.next_n(Options().\
00120 get_option('max_bindings'))
00121 bindings_it.destroy()
00122
00123 def _process_binding(self, binding, orb, filter):
00124 if filtered([corba_name_to_string(binding.binding_name)], filter):
00125
00126 return
00127 trimmed_filter = trim_filter(deepcopy(filter))
00128 with self._mutex:
00129
00130
00131 if binding.binding_type == CosNaming.nobject:
00132
00133
00134 if binding.binding_name[0].kind == 'mgr':
00135 name = corba_name_to_string(binding.binding_name)
00136 obj = self._context.resolve(binding.binding_name)
00137 if not obj:
00138 leaf = Zombie(name, self)
00139 return
00140 obj = obj._narrow(RTM.Manager)
00141 try:
00142 leaf = Manager(name, self, obj, dynamic=self.dynamic)
00143 except CORBA.OBJECT_NOT_EXIST:
00144
00145 leaf = Zombie(name, self)
00146 except CORBA.TRANSIENT:
00147
00148 leaf = Zombie(name, self)
00149 self._add_child(leaf)
00150 elif binding.binding_name[0].kind == 'rtc':
00151 name = corba_name_to_string(binding.binding_name)
00152 obj = self._context.resolve(binding.binding_name)
00153 try:
00154 obj = obj._narrow(RTC.RTObject)
00155 except CORBA.TRANSIENT, e:
00156 if e.args[0] == TRANSIENT_ConnectFailed:
00157 self._add_child(Zombie(name, self))
00158 return
00159 else:
00160 raise
00161 except CORBA.OBJECT_NOT_EXIST:
00162 self._add_child(Zombie(name, self))
00163 return
00164 try:
00165 leaf = Component(name, self, obj, dynamic=self.dynamic)
00166 except CORBA.OBJECT_NOT_EXIST:
00167
00168 leaf = Zombie(name, self, dynamic=self.dynamic)
00169 except CORBA.TRANSIENT, e:
00170 if e.args[0] == TRANSIENT_ConnectFailed:
00171 self._add_child(Zombie(name, self))
00172 return
00173 else:
00174 raise
00175 self._add_child(leaf)
00176 else:
00177
00178 name = corba_name_to_string(binding.binding_name)
00179 obj = self._context.resolve(binding.binding_name)
00180 leaf = Unknown(name, self, obj)
00181 self._add_child(leaf)
00182 else:
00183
00184 subdir_name = corba_name_to_string(binding.binding_name)
00185 subdir = Directory(subdir_name, self, filter=trimmed_filter,
00186 dynamic=self.dynamic)
00187 subdir_context = self._context.resolve(binding.binding_name)
00188 subdir_context = subdir_context._narrow(CosNaming.NamingContext)
00189 subdir._parse_context(subdir_context, orb,
00190 filter=trimmed_filter)
00191 self._add_child(subdir)
00192
00193
00194 def corba_name_to_string(name):
00195 '''Convert a CORBA CosNaming.Name to a string.'''
00196 parts = []
00197 if type(name) is not list and type(name) is not tuple:
00198 raise NotCORBANameError(name)
00199 if len(name) == 0:
00200 raise NotCORBANameError(name)
00201
00202 for nc in name:
00203 if not nc.kind:
00204 parts.append(nc.id)
00205 else:
00206 parts.append('{0}.{1}'.format(nc.id, nc.kind))
00207 return '/'.join(parts)
00208
00209
00210
00211