diff options
-rw-r--r-- | tutorius/TProbe.py | 83 | ||||
-rw-r--r-- | tutorius/service.py | 6 |
2 files changed, 56 insertions, 33 deletions
diff --git a/tutorius/TProbe.py b/tutorius/TProbe.py index 7f68b42..1146277 100644 --- a/tutorius/TProbe.py +++ b/tutorius/TProbe.py @@ -38,16 +38,12 @@ class TProbe(dbus.service.Object): a DBUS Interface. """ - def __init__(self, activity_name, activity): + def __init__(self, activity): """ Create and register a TProbe for an activity. - @param activity_name unique activity_id @param activity activity reference, must be a gtk container """ - LOGGER.debug("TProbe :: Creating TProbe for %s (%d)", activity_name, os.getpid()) - LOGGER.debug("TProbe :: Current gobject context: %s", str(gobject.main_context_default())) - LOGGER.debug("TProbe :: Current gobject depth: %s", str(gobject.main_depth())) # Moving the ObjectStore assignment here, in the meantime # the reference to the activity shouldn't be share as a # global variable but passed by the Probe to the objects @@ -56,24 +52,26 @@ class TProbe(dbus.service.Object): ObjectStore().activity = activity - self._activity_name = activity_name + self._activity_name = activity.get_bundle_id() + self._unique_id = activity.get_id() + + LOGGER.debug("TProbe :: Creating TProbe for %s (%d)", self._activity_name, os.getpid()) + LOGGER.debug("TProbe :: Current gobject context: %s", str(gobject.main_context_default())) + LOGGER.debug("TProbe :: Current gobject depth: %s", str(gobject.main_depth())) self._session_bus = dbus.SessionBus() # Giving a new name because _name is already used by dbus - self._name2 = dbus.service.BusName(activity_name, self._session_bus) - dbus.service.Object.__init__(self, self._session_bus, "/tutorius/Probe") + self._name2 = dbus.service.BusName(self._activity_name, self._session_bus) + dbus.service.Object.__init__(self, self._session_bus, "/tutorius/Probe/"+str(self._unique_id)) # Add the dictionary we will use to store which actions and events # are known self._installedActions = {} self._subscribedEvents = {} - LOGGER.debug("TProbe :: registering '%s'", activity_name) - # TODO: Once multiple probes are supported by the ProbeManager, - # pass the unique_id associated with this process instead - # of the activity_name twice + LOGGER.debug("TProbe :: registering '%s' with unique_id '%s'", self._activity_name, activity.get_id()) from .service import ServiceProxy - ServiceProxy().register_probe(activity_name, activity_name) + ServiceProxy().register_probe(self._activity_name, self._unique_id) @@ -83,9 +81,17 @@ class TProbe(dbus.service.Object): existing activity. Starts a gobject mainloop """ mainloop = gobject.MainLoop() - print "Starting Probe for " + self._activity_name mainloop.run() + def stop(self): + """ + Clean up the probe when finished. Should be called just + before a process ends + """ + from .service import ServiceProxy + LOGGER.debug("TProbe :: unregistering '%s' with unique_id '%s'", self._activity_name, self._unique_id) + ServiceProxy().unregister_probe(self._unique_id) + @dbus.service.method("org.tutorius.ProbeInterface", in_signature='s', out_signature='') def registered(self, service): @@ -243,16 +249,17 @@ class ProbeProxy: It provides an object interface to the TProbe, which requires pickled strings, across a DBus communication. """ - def __init__(self, activityName): + def __init__(self, activityName, unique_id): """ Constructor - @param activityName unique activity id. Must be a valid dbus bus name. + @param activityName generic activity name. Must be a valid dbus bus name. + @param unique_id unique id specific to an instance of an activity """ LOGGER.debug("ProbeProxy :: Creating ProbeProxy for %s (%d)", activityName, os.getpid()) LOGGER.debug("ProbeProxy :: Current gobject context: %s", str(gobject.main_context_default())) LOGGER.debug("ProbeProxy :: Current gobject depth: %s", str(gobject.main_depth())) bus = dbus.SessionBus() - self._object = bus.get_object(activityName, "/tutorius/Probe") + self._object = bus.get_object(activityName, "/tutorius/Probe/"+str(unique_id)) self._probe = dbus.Interface(self._object, "org.tutorius.ProbeInterface") self._actions = {} @@ -478,7 +485,7 @@ class ProbeManager(object): @return None """ if self.currentActivity: - return self._probes[self.currentActivity][0].install(action, block) + return self._first_proxy(self.currentActivity).install(action, block) else: raise RuntimeWarning("No activity attached") @@ -491,7 +498,7 @@ class ProbeManager(object): @return None """ if self.currentActivity: - return self._probes[self.currentActivity][0].update(action, newaction, block) + return self._first_proxy(self.currentActivity).update(action, newaction, block) else: raise RuntimeWarning("No activity attached") @@ -502,7 +509,7 @@ class ProbeManager(object): @param block Force a synchroneous dbus call if True """ if self.currentActivity: - return self._probes[self.currentActivity][0].uninstall(action, block) + return self._first_proxy(self.currentActivity).uninstall(action, block) else: raise RuntimeWarning("No activity attached") @@ -514,7 +521,7 @@ class ProbeManager(object): @return address identifier used for unsubscribing """ if self.currentActivity: - return self._probes[self.currentActivity][0].subscribe(event, callback) + return self._first_proxy(self.currentActivity).subscribe(event, callback) else: raise RuntimeWarning("No activity attached") @@ -525,7 +532,7 @@ class ProbeManager(object): @return None """ if self.currentActivity: - return self._probes[self.currentActivity][0].unsubscribe(address) + return self._first_proxy(self.currentActivity).unsubscribe(address) else: raise RuntimeWarning("No activity attached") @@ -542,10 +549,10 @@ class ProbeManager(object): process """ ProbeManager._LOGGER.debug("register_probe(%s,%s)", process_name, unique_id) - # For now make sure the process_name and unique_id are the same, - # until we support multiple probes for the same activity - assert process_name == unique_id - self._probes[process_name] = [self._ProxyClass(process_name)] + if process_name not in self._probes: + self._probes[process_name] = [(unique_id,self._ProxyClass(process_name, unique_id))] + else: + self._probes[process_name].append((unique_id,self._ProxyClass(process_name, unique_id))) def unregister_probe(self, unique_id): @@ -555,10 +562,22 @@ class ProbeManager(object): process """ ProbeManager._LOGGER.debug("unregister_probe(%s)", unique_id) - # For now simply assume the unique_id is the same as the process_name - # TODO: search through the dictionary to remove all probes with - # the unique_id name - if unique_id in self._probes: - probe = self._probes.pop(unique_id) - probe.detach() + for process_name, proxies in self._probes.items(): + for id, proxy in proxies: + if unique_id == id: + proxy.detach() + proxies.remove((id,proxy)) + if len(proxies) == 0: + self._probes.pop(process_name) + + def _first_proxy(self, process_name): + """ + Returns the oldest probe connected under the process_name + @param process_name The generic process name under which the probe + is connected + """ + if process_name in self._probes: + return self._probes[process_name][0][1] + else: + raise RuntimeWarning("No activity attached under '%s'", process_name) diff --git a/tutorius/service.py b/tutorius/service.py index 4be1f41..8694cb5 100644 --- a/tutorius/service.py +++ b/tutorius/service.py @@ -129,7 +129,11 @@ class ServiceProxy: @param unique_id The unique identification associated to this process """ - remote_call(self._service.unregister_probe, (unique_id), block=False) + # We make it synchronous because otherwise on closing, + # activities kill the dbus session bus too fast for the + # asynchronous call to be completed + self._service.unregister_probe(unique_id) + if __name__ == "__main__": import dbus.mainloop.glib |