[PATCH phosphor-objmgr 1/8] Add filter capability to introspection parser

OpenBMC Patches patches at stwcx.xyz
Thu Nov 5 03:33:27 AEDT 2015


From: Brad Bishop <bradleyb at us.ibm.com>

Can filter on:
  XML node tags
  interface names

Using filters cuts down on parsing cycles.
---
 OpenBMCMapper.py | 43 ++++++++++++++++++++++++++++++++++---------
 phosphor-mapper  | 34 ++++++++++++++++------------------
 2 files changed, 50 insertions(+), 27 deletions(-)

diff --git a/OpenBMCMapper.py b/OpenBMCMapper.py
index 30a93fb..cefed52 100644
--- a/OpenBMCMapper.py
+++ b/OpenBMCMapper.py
@@ -45,10 +45,22 @@ class Path:
 			last = self.depth()
 		return prefix + '/'.join(self.parts[first:last])
 
+def org_dot_openbmc_match(name):
+	return 'org.openbmc' in name
+
+class TagListMatch(object):
+	def __init__(self, tag_list):
+		self.tag_list = tag_list
+
+	def __call__(self, tag):
+		return tag in self.tag_list
+
 class IntrospectionNodeParser:
-	def __init__(self, data):
+	def __init__(self, data, tag_match = bool, intf_match = bool):
 		self.data = data
 		self.cache = {}
+		self.tag_match = tag_match
+		self.intf_match = intf_match
 
 	def parse_args(self):
 		return [ x.attrib for x in self.data.findall('arg') ]
@@ -64,16 +76,18 @@ class IntrospectionNodeParser:
 		iface = {}
 		iface['method'] = {}
 		iface['signal'] = {}
-		name = self.data.attrib['name']
 
 		for node in self.data:
-			p = IntrospectionNodeParser(node)
 			if node.tag not in ['method', 'signal']:
 				continue
+			if not self.tag_match(node.tag):
+				continue
+			p = IntrospectionNodeParser(
+					node, self.tag_match, self.intf_match)
 			n, element = p.parse_method_or_signal()
 			iface[node.tag][n] = element
 
-		return name, iface
+		return iface
 
 	def parse_node(self):
 		if self.cache:
@@ -83,10 +97,13 @@ class IntrospectionNodeParser:
 		self.cache['children'] = []
 
 		for node in self.data:
-			p = IntrospectionNodeParser(node)
 			if node.tag == 'interface':
-				name, ifaces = p.parse_interface()
-				self.cache['interfaces'][name] = ifaces
+				p = IntrospectionNodeParser(
+						node, self.tag_match, self.intf_match)
+				name = p.data.attrib['name']
+				if not self.intf_match(name):
+					continue
+				self.cache['interfaces'][name] = p.parse_interface()
 			elif node.tag == 'node':
 				self.cache['children'] = self.parse_children()
 
@@ -102,9 +119,11 @@ class IntrospectionNodeParser:
 		return any('/' in s for s in self.get_children())
 
 class IntrospectionParser:
-	def __init__(self, name, bus):
+	def __init__(self, name, bus, tag_match = bool, intf_match = bool):
 		self.name = name
 		self.bus = bus
+		self.tag_match = tag_match
+		self.intf_match = intf_match
 
 	def _introspect(self, path):
 		try:
@@ -114,7 +133,10 @@ class IntrospectionParser:
 		except dbus.DBusException:
 			return None
 
-		return IntrospectionNodeParser(ElementTree.fromstring(data))
+		return IntrospectionNodeParser(
+				ElementTree.fromstring(data),
+				self.tag_match,
+				self.intf_match)
 
 	def _discover_flat(self, path, parser):
 		items = {}
@@ -147,4 +169,7 @@ class IntrospectionParser:
 				continue
 			items.update(callback(path + k, parser))
 
+		if path == '/':
+			print items
+
 		return items
diff --git a/phosphor-mapper b/phosphor-mapper
index 313baa2..fda70c7 100644
--- a/phosphor-mapper
+++ b/phosphor-mapper
@@ -167,13 +167,15 @@ class ObjectMatch(PathMatch):
 
 class ObjectMapper(dbus.service.Object):
 	def __init__(self, bus, path,
-			name_match = 'org.openbmc',
-			intf_match = 'org.openbmc'):
+			name_match = OpenBMCMapper.org_dot_openbmc_match,
+			intf_match = OpenBMCMapper.org_dot_openbmc_match):
 		super(ObjectMapper, self).__init__(bus.dbus, path)
 		self.cache = DictionaryCache()
 		self.bus = bus
 		self.name_match = name_match
 		self.intf_match = intf_match
+		self.tag_match = OpenBMCMapper.TagListMatch(['children', 'interface'])
+
 		self.discovery_done = False
 
 		gobject.idle_add(self.discover)
@@ -191,7 +193,7 @@ class ObjectMapper(dbus.service.Object):
 
 	def interfaces_added_handler(self, path, iprops, **kw):
 		for x in iprops.iterkeys():
-			if self.intf_match in x:
+			if self.intf_match(x):
 				self.cache.add_item((path, kw['sender'], x))
 
 	def interfaces_removed_handler(self, path, interfaces, **kw):
@@ -200,7 +202,8 @@ class ObjectMapper(dbus.service.Object):
 
 	def process_new_owner(self, name):
 		# unique name
-		return self.discover([ IntrospectionParser(name, self.bus.dbus) ])
+		return self.discover([ IntrospectionParser(name,
+			self.bus.dbus, self.tag_match, self.intf_match) ])
 
 	def process_old_owner(self, name):
 		# unique name
@@ -208,7 +211,7 @@ class ObjectMapper(dbus.service.Object):
 
 	def bus_handler(self, service, old, new):
 		if not self.discovery_done or \
-				self.name_match not in service:
+				not self.name_match(service):
 			return
 
 		if new:
@@ -216,21 +219,20 @@ class ObjectMapper(dbus.service.Object):
 		if old:
 			self.process_old_owner(old)
 
-	def add_match_interfaces(self, owner, path, interfaces):
+	def add_interfaces(self, owner, path, interfaces):
 		for x in interfaces:
-			if self.intf_match not in x:
-				continue
-
 			self.cache.add_item((path, owner, x))
 
-	def add_match_items(self, owner, bus_items):
+	def add_items(self, owner, bus_items):
 		for x,y in bus_items.iteritems():
-			self.add_match_interfaces(owner, x, y['interfaces'])
+			self.add_interfaces(owner, x, y['interfaces'])
 
 	def discover(self, owners = None):
 		discovery = not self.discovery_done
 		if not owners:
-			owners = self.bus.get_owners(self.name_match)
+			owners = [ IntrospectionParser(x, self.bus.dbus,
+				self.tag_match, self.intf_match) \
+						for x in self.bus.get_owner_names(self.name_match) ]
 			self.discovery_done = True
 		for o in owners:
 
@@ -239,7 +241,7 @@ class ObjectMapper(dbus.service.Object):
 			if self.cache.has_bus(o.name):
 				continue
 
-			self.add_match_items(o.name, o.introspect())
+			self.add_items(o.name, o.introspect())
 
 		if discovery:
 			print "ObjectMapper discovery complete..."
@@ -266,17 +268,13 @@ class BusWrapper:
 	def get_service_names(self, match):
 		# these are well known names
 		return [ x for x in self.dbus.list_names() \
-				if match in x and x != OpenBMCMapper.MAPPER_NAME ]
+				if match(x) and x != OpenBMCMapper.MAPPER_NAME ]
 
 	def get_owner_names(self, match):
 		# these are unique connection names
 		return list( set( [ self.dbus.get_name_owner(x) \
 				for x in self.get_service_names(match) ] ) )
 
-	def get_owners(self, match):
-		return [ IntrospectionParser(x, self.dbus) \
-				for x in self.get_owner_names(match) ]
-
 if __name__ == '__main__':
 	dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
 	bus = dbus.SystemBus()
-- 
2.6.0




More information about the openbmc mailing list