tree.py
Go to the documentation of this file.
1 # -*- Python -*-
2 # -*- coding: utf-8 -*-
3 
4 '''rtctree
5 
6 Copyright (C) 2009-2014
7  Geoffrey Biggs
8  RT-Synthesis Research Group
9  Intelligent Systems Research Institute,
10  National Institute of Advanced Industrial Science and Technology (AIST),
11  Japan
12  All rights reserved.
13 Licensed under the Eclipse Public License -v 1.0 (EPL)
14 http://www.opensource.org/licenses/eclipse-1.0.txt
15 
16 Objects and functions used to build and store a tree representing a hierarchy
17 of name servers, directories, managers and components.
18 
19 '''
20 
21 from copy import deepcopy
22 from omniORB import CORBA
23 import os
24 import sys
25 
26 from rtctree import NAMESERVERS_ENV_VAR, ORB_ARGS_ENV_VAR
27 from rtctree.exceptions import *
28 from rtctree.path import BadPathError
29 from rtctree.node import TreeNode
30 from rtctree.directory import Directory
31 from rtctree.nameserver import NameServer
32 from rtctree.manager import Manager
33 from rtctree.component import Component
34 from rtctree.utils import filtered, trim_filter
35 
36 
37 ##############################################################################
38 ## Tree object
39 
40 class RTCTree(object):
41  '''Represents a tree of name servers, directories, managers and components.
42 
43  This stores the root node. All other nodes branch off from that.
44 
45  When creating a tree, you may pass no arguments, or a list of name servers
46  to load, or a path or list of paths (as returned by
47  rtctree.path.parse_path). If no arguments are given, the tree will load
48  name servers from the environment variable specified in
49  NAMESERVERS_ENV_VAR. If a list of servers are given, only those servers
50  will be loaded.
51 
52  If paths are given, and the path is just '/', behaviour is as if no path
53  argument were given. If a path starts with '/' and contains an element
54  after it, that element will be treated as a name server. Otherwise the path
55  is considered to be bad.
56 
57  '''
58  def __init__(self, servers=None, paths=None, orb=None, filter=[],
59  dynamic=False, *args, **kwargs):
60  '''Constructor.
61 
62  @param servers A list of servers to parse into the tree.
63  @param paths A list of paths from which to get servers to parse
64  into the tree.
65  @param orb If not None, the specified ORB will be used. If None,
66  the tree object will create its own ORB.
67  @param filter A list of paths (each a list of strings).
68  If not empty, then only objects in the paths will
69  be parsed, to increase speed. If the tail of a
70  path is a directory, that entire directory will be
71  parsed. Directories that are not the tail will
72  only have the next entry in the path parsed.
73  @param dynamic Use observers to keep the tree up-to-date. For example,
74  when a component changes state, an observer can notify
75  RTCTree so that the corresponding object in the tree can
76  be updated. Currently this only affects components.
77  @raises NonRootPathError
78 
79  '''
80  super(RTCTree, self).__init__()
81  self._root = TreeNode('/', None, dynamic=dynamic)
82  self._create_orb(orb)
83  self._dynamic = dynamic
84  if servers:
85  self._parse_name_servers(servers, filter=filter, dynamic=dynamic)
86  if paths:
87  if type(paths[0]) == str:
88  if paths[0][0] != '/':
89  raise NonRootPathError(paths[0])
90  if len(paths) > 1:
91  self.add_name_server(paths[1], filter=filter,
92  dynamic=dynamic)
93  else:
94  for p in paths:
95  if p[0] != '/':
96  raise NonRootPathError(p)
97  if len(p) > 1:
98  self.add_name_server(p[1], filter=filter,
99  dynamic=dynamic)
100  self.load_servers_from_env(filter=filter, dynamic=dynamic)
101  if not servers and not paths:
102  self.load_servers_from_env(filter=filter, dynamic=dynamic)
103 
104  def __del__(self):
105  # Destructor to ensure the ORB shuts down correctly.
106  if self._orb_is_mine:
107  self._orb.shutdown(wait_for_completion=CORBA.FALSE)
108  self._orb.destroy()
109 
110  def __str__(self):
111  # Get a (potentially very large) string describing the tree.
112  return str(self._root)
113 
114  def add_name_server(self, server, filter=[], dynamic=None):
115  '''Parse a name server, adding its contents to the tree.
116 
117  @param server The address of the name server, in standard
118  address format. e.g. 'localhost',
119  'localhost:2809', '59.7.0.1'.
120  @param filter Restrict the parsed objects to only those in this
121  path. For example, setting filter to [['/',
122  'localhost', 'host.cxt', 'comp1.rtc']] will
123  prevent 'comp2.rtc' in the same naming context
124  from being parsed.
125  @param dynamic Override the tree-wide dynamic setting. If not provided,
126  the value given when the tree was created will be used.
127 
128  '''
129  if dynamic == None:
130  dynamic = self._dynamic
131  self._parse_name_server(server, filter, dynamic=dynamic)
132 
133  def get_node(self, path):
134  '''Get a node by path.
135 
136  @param path A list of path elements pointing to a node in the tree.
137  For example, ['/', 'localhost', 'dir.host']. The first
138  element in this path should be the root node's name.
139 
140  '''
141  return self._root.get_node(path)
142 
143  def has_path(self, path):
144  '''Check if the tree has a path.
145 
146  @param path A list of path elements pointing to a node in the tree.
147  For example, ['/', 'localhost', 'dir.host']. The first
148  element in this path should be the root node's name.
149 
150  '''
151  return self._root.has_path(path)
152 
153  def is_component(self, path):
154  '''Is the node pointed to by @ref path a component?'''
155  node = self.get_node(path)
156  return node.is_component
157 
158  def is_directory(self, path):
159  '''Is the node pointed to by @ref path a directory (name servers and
160  naming contexts)?
161 
162  '''
163  node = self.get_node(path)
164  return node.is_directory
165 
166  def is_manager(self, path):
167  '''Is the node pointed to by @ref path a manager?'''
168  node = self.get_node(path)
169  return node.is_manager
170 
171  def is_nameserver(self, path):
172  '''Is the node pointed to by @ref path a name server (specialisation
173  of directory nodes)?
174 
175  '''
176  node = self.get_node(path)
177  return node.is_nameserver
178 
179  def is_unknown(self, path):
180  '''Is the node pointed to by @ref path an unknown object?'''
181  node = self.get_node(path)
182  return node.is_unknown
183 
184  def is_zombie(self, path):
185  '''Is the node pointed to by @ref path a zombie object?'''
186  node = self.get_node(path)
187  return node.is_zombie
188 
189  def iterate(self, func, args=None, filter=[]):
190  '''Call a function on the root node, and recursively all its children.
191 
192  This is a depth-first iteration.
193 
194  @param func The function to call. Its declaration must be
195  'def blag(node, args)', where 'node' is the current node
196  in the iteration and args is the value of @ref args.
197  @param args Extra arguments to pass to the function at each iteration.
198  Pass multiple arguments in as a tuple.
199  @param filter A list of filters to apply before calling func for each
200  node in the iteration. If the filter is not True,
201  @ref func will not be called for that node. Each filter
202  entry should be a string, representing on of the is_*
203  properties (is_component, etc), or a function object.
204  @return The results of the calls to @ref func in a list.
205 
206  '''
207  return self._root.iterate(func, args, filter)
208 
209  def load_servers_from_env(self, filter=[], dynamic=None):
210  '''Load the name servers environment variable and parse each server in
211  the list.
212 
213  @param filter Restrict the parsed objects to only those in this
214  path. For example, setting filter to [['/',
215  'localhost', 'host.cxt', 'comp1.rtc']] will
216  prevent 'comp2.rtc' in the same naming context
217  from being parsed.
218  @param dynamic Override the tree-wide dynamic setting. If not provided,
219  the value given when the tree was created will be used.
220 
221  '''
222  if dynamic == None:
223  dynamic = self._dynamic
224  if NAMESERVERS_ENV_VAR in os.environ:
225  servers = [s for s in os.environ[NAMESERVERS_ENV_VAR].split(';') \
226  if s]
227  self._parse_name_servers(servers, filter, dynamic)
228 
229  def give_away_orb(self):
230  '''Releases ownership of an ORB created by the tree.
231 
232  This will prevent the ORB being destroyed when the tree is.
233 
234  '''
235  self._orb_is_mine = False
236 
237  def own_orb(self):
238  '''Claims ownership of an ORB created elsewhere.
239 
240  This will cause the ORB to be destroyed when the tree is.
241 
242  '''
243  self._orb_is_mine = True
244 
245  @property
246  def orb(self):
247  '''The reference to the ORB held by this tree.'''
248  return self._orb
249 
250  def _create_orb(self, orb=None):
251  # Create the ORB, optionally checking the environment variable for
252  # arguments to pass to the ORB.
253  if orb:
254  self._orb = orb
255  self._orb_is_mine = False
256  else:
257  if ORB_ARGS_ENV_VAR in os.environ:
258  orb_args = os.environ[ORB_ARGS_ENV_VAR].split(';')
259  else:
260  orb_args = []
261  self._orb = CORBA.ORB_init(orb_args)
262  self._orb_is_mine = True
263  # Run the POA manager
264  self._poa = self._orb.resolve_initial_references('RootPOA')
265  self._poa._get_the_POAManager().activate()
266 
267  def _parse_name_servers(self, servers, filter=[], dynamic=False):
268  # Parse a list of name servers.
269  if type(servers) is str:
270  # Don't parse any servers already parsed
271  if servers in self._root.children_names:
272  return
273  self._parse_name_server(servers, filter, dynamic=dynamic)
274  else:
275  for server in servers:
276  # Don't parse any servers already parsed
277  if server in self._root.children_names:
278  return
279  self._parse_name_server(server, filter, dynamic=dynamic)
280 
281  def _parse_name_server(self, address, filter=[], dynamic=False):
282  # Parse a single name server and add it to the root node.
283  if not filtered(['/', address], filter):
284  new_ns_node = NameServer(self._orb, address, self._root,
285  trim_filter(deepcopy(filter), 2), dynamic=dynamic)
286  self._root._add_child(new_ns_node)
287 
288 
289 # vim: tw=79
290 
def _parse_name_servers(self, servers, filter=[], dynamic=False)
Definition: tree.py:267
def is_directory(self, path)
Definition: tree.py:158
def is_unknown(self, path)
Definition: tree.py:179
Name server node object.
Definition: nameserver.py:31
def load_servers_from_env(self, filter=[], dynamic=None)
Definition: tree.py:209
def __init__(self, servers=None, paths=None, orb=None, filter=[], dynamic=False, args, kwargs)
Definition: tree.py:59
def __del__(self)
Definition: tree.py:104
def get_node(self, path)
Definition: tree.py:133
def trim_filter(filter, levels=1)
Definition: utils.py:201
def is_nameserver(self, path)
Definition: tree.py:171
def orb(self)
Definition: tree.py:246
def filtered(path, filter)
Definition: utils.py:177
Tree object.
Definition: tree.py:40
def is_component(self, path)
Definition: tree.py:153
def own_orb(self)
Definition: tree.py:237
def has_path(self, path)
Definition: tree.py:143
def iterate(self, func, args=None, filter=[])
Definition: tree.py:189
def is_zombie(self, path)
Definition: tree.py:184
Base node object.
Definition: node.py:29
def __str__(self)
Definition: tree.py:110
def _create_orb(self, orb=None)
Definition: tree.py:250
def is_manager(self, path)
Definition: tree.py:166
def add_name_server(self, server, filter=[], dynamic=None)
Definition: tree.py:114
def _parse_name_server(self, address, filter=[], dynamic=False)
Definition: tree.py:281
def give_away_orb(self)
Definition: tree.py:229


rtctree
Author(s): Geoffrey Biggs
autogenerated on Fri Jun 7 2019 21:56:24