[sugar] Improve ActivityFactory utility functions and reduce code-path duplication.
Michael Stone
michael at laptop.org
Mon Nov 5 13:55:56 EST 2007
* Remove a race in open_log_file()
* Make open_log_file return a path as well as a file-object so that
Rainbow-launched activities can log to the same path that sugar-launched
ones do.
* Change the call to Rainbow so that it writes to the log-file provided by
open_log_file()
* Define SUGAR_BUNDLE_ID env variable and change the location of the check
for /etc/olpc-security so that Rainbow doesn't have to search for or parse
the activity bundle.
* Remove import statements marked as unnecessary by pylint.
* Fix up some whitespace issues.
---
lib/sugar/activity/activityfactory.py | 98 ++++++++++++++++++---------------
1 files changed, 53 insertions(+), 45 deletions(-)
diff --git a/lib/sugar/activity/activityfactory.py b/lib/sugar/activity/activityfactory.py
index cd75edd..18a5abe 100644
--- a/lib/sugar/activity/activityfactory.py
+++ b/lib/sugar/activity/activityfactory.py
@@ -21,12 +21,10 @@ import subprocess
import dbus
import gobject
-import gtk
from sugar.presence import presenceservice
from sugar.activity.activityhandle import ActivityHandle
from sugar.activity import registry
-from sugar.datastore import datastore
from sugar import util
from sugar import env
@@ -91,6 +89,7 @@ def get_environment(activity):
os.mkdir(tmp_dir)
environ['SUGAR_BUNDLE_PATH'] = activity.path
+ environ['SUGAR_BUNDLE_ID'] = activity.bundle_id
environ['SUGAR_ACTIVITY_ROOT'] = activity_root
environ['PATH'] = bin_path + ':' + environ['PATH']
@@ -113,41 +112,47 @@ def get_command(activity, activity_id=None, object_id=None, uri=None):
return command
-def open_log_file(activity, activity_id):
- for i in range(1, 100):
+def open_log_file(activity):
+ i = 1
+ while True:
path = env.get_logs_path('%s-%s.log' % (activity.bundle_id, i))
- if not os.path.exists(path):
- return open(path, 'w')
+ try:
+ fd = os.open(path, os.O_EXCL | os.O_CREAT \
+ | os.O_SYNC | os.O_WRONLY, 0644)
+ f = os.fdopen(fd, 'w', 0)
+ return (path, f)
+ except:
+ i += 1
class ActivityCreationHandler(gobject.GObject):
"""Sugar-side activity creation interface
-
+
This object uses a dbus method on the ActivityFactory
- service to create the new activity. It generates
+ service to create the new activity. It generates
GObject events in response to the success/failure of
- activity startup using callbacks to the service's
+ activity startup using callbacks to the service's
create call.
"""
def __init__(self, service_name, handle):
"""Initialise the handler
-
+
service_name -- the service name of the bundle factory
- activity_handle -- stores the values which are to
+ activity_handle -- stores the values which are to
be passed to the service to uniquely identify
- the activity to be created and the sharing
+ the activity to be created and the sharing
service that may or may not be connected with it
-
+
sugar.activity.activityhandle.ActivityHandle instance
-
- calls the "create" method on the service for this
- particular activity type and registers the
- _reply_handler and _error_handler methods on that
+
+ calls the "create" method on the service for this
+ particular activity type and registers the
+ _reply_handler and _error_handler methods on that
call's results.
-
- The specific service which creates new instances of this
+
+ The specific service which creates new instances of this
particular type of activity is created during the activity
- registration process in shell bundle registry which creates
+ registration process in shell bundle registry which creates
service definition files for each registered bundle type.
If the file '/etc/olpc-security' exists, then activity launching
@@ -182,37 +187,40 @@ class ActivityCreationHandler(gobject.GObject):
def _create_activity(self):
if self._handle.activity_id is None:
- self._handle.activity_id = create_activity_id()
+ self._handle.activity_id = create_activity_id()
self._shell.NotifyLaunch(
self._service_name, self._handle.activity_id,
reply_handler=self._no_reply_handler,
error_handler=self._notify_launch_error_handler)
- if not os.path.exists('/etc/olpc-security'):
- activity_registry = registry.get_registry()
- activity = activity_registry.get_activity(self._service_name)
- if activity:
- env = get_environment(activity)
- log_file = open_log_file(activity, self._handle.activity_id)
- command = get_command(activity, self._handle.activity_id,
- self._handle.object_id,
- self._handle.uri)
- process = subprocess.Popen(command, env=env, cwd=activity.path,
+ activity_registry = registry.get_registry()
+ activity = activity_registry.get_activity(self._service_name)
+ if activity:
+ environ = get_environment(activity)
+ (log_path, log_file) = open_log_file(activity)
+ command = get_command(activity, self._handle.activity_id,
+ self._handle.object_id,
+ self._handle.uri)
+
+ if not os.path.exists('/etc/olpc-security'):
+ process = subprocess.Popen(command, env=environ, cwd=activity.path,
stdout=log_file, stderr=log_file)
- else:
- system_bus = dbus.SystemBus()
- factory = system_bus.get_object(_RAINBOW_SERVICE_NAME,
- _RAINBOW_ACTIVITY_FACTORY_PATH)
- stdio_paths = {'stdout': '/logs/stdout', 'stderr': '/logs/stderr'}
- factory.CreateActivity(
- self._service_name,
- self._handle.get_dict(),
- stdio_paths,
- timeout=120 * DBUS_PYTHON_TIMEOUT_UNITS_PER_SECOND,
- reply_handler=self._create_reply_handler,
- error_handler=self._create_error_handler,
- dbus_interface=_RAINBOW_ACTIVITY_FACTORY_INTERFACE)
+ else:
+ log_file.close()
+ system_bus = dbus.SystemBus()
+ factory = system_bus.get_object(_RAINBOW_SERVICE_NAME,
+ _RAINBOW_ACTIVITY_FACTORY_PATH)
+ factory.CreateActivity(
+ log_path,
+ environ,
+ command,
+ environ['SUGAR_BUNDLE_PATH'],
+ environ['SUGAR_BUNDLE_ID'],
+ timeout=30 * DBUS_PYTHON_TIMEOUT_UNITS_PER_SECOND,
+ reply_handler=self._create_reply_handler,
+ error_handler=self._create_error_handler,
+ dbus_interface=_RAINBOW_ACTIVITY_FACTORY_INTERFACE)
def _no_reply_handler(self, *args):
pass
@@ -231,7 +239,7 @@ class ActivityCreationHandler(gobject.GObject):
logging.error("Activity activation request failed %s" % err)
def _create_reply_handler(self, xid):
- logging.debug("Activity created %s (%s)." %
+ logging.debug("Activity created %s (%s)." %
(self._handle.activity_id, self._service_name))
def _create_error_handler(self, err):
--
1.5.3.1
More information about the Sugar
mailing list