~ubuntu-branches/ubuntu/quantal/desktopcouch/quantal

« back to all changes in this revision

Viewing changes to debian/patches/5-defer-dbus-service-for-plugins.patch

  • Committer: Martin Pitt
  • Date: 2011-09-13 15:08:39 UTC
  • mfrom: (46.1.3 1.0.8-0u1)
  • Revision ID: martin.pitt@canonical.com-20110913150839-i38sgr7k9xb7tgi4
* New upstream release.
  - Behavior change: Preserves Ubuntu One service through longer replication
    period, 10 minutes changed to 60 minutes.
  - Feature: Allow COUCH_INI environment variable to override /etc/ default
    config.
  - Feature: Install apport hook.
  - Bug fix: When ubuntuone credentials don't exist, don't wait forever and
    consume CPU. (LP: #760236, #787583)
  - Bug fix: Accept "linux3" kernel also. (LP: #803062)
  - Bug fix: Clean up all children when service exits. (LP: #597197)
* Update standards-version 3.9.1 to 3.9.2.
* Remove brace-expansion from python-desktopcouch-application.install .
* Remove brace-expansion from python-desktopcouch-recordtypes.install .
* Remove patch
  - patches/5-defer-dbus-service-for-plugins.patch
* Remove deprecated CDBS simple-patch system from rules.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
Description: Make plugins be able to stall dbus service from signaling that
2
 
  couchdb is ready to use.
3
 
Bug-Ubuntu: https://bugs.edge.launchpad.net/ubuntu/+source/desktopcouch/+bug/760236
4
 
Applied-upstream: bzr id chad.miller@canonical.com-20110412173802-flmya9dma0et83qr
5
 
Author: Chad Miller <chad.miller@canonical.com>
6
 
 
7
 
 
8
 
=== modified file 'desktopcouch/application/plugins/__init__.py'
9
 
--- desktopcouch/application/plugins/__init__.py        2011-02-02 18:15:53 +0000
10
 
+++ desktopcouch/application/plugins/__init__.py        2011-04-15 23:40:28 +0000
11
 
@@ -19,8 +19,18 @@
12
 
 DESKTOPCOUCH_PLUGIN_PATHS = [os.path.join(os.path.dirname(__file__))]
13
 
 
14
 
 
15
 
-def load_plugins(couchdb_port):
16
 
-    """Load the desktopcouch application plug-ins."""
17
 
+def load_plugins(couchdb_port, blocking_semaphores, gobject):
18
 
+    """Load the desktopcouch application plug-ins.
19
 
+
20
 
+    The blocking_semaphores set is OPTIONALLY mutated by any plugin to signal
21
 
+    that the service is not ready until a plugin has finished its asynchronous
22
 
+    operations.  Plugins may add a distinguishing object to the set, and it
23
 
+    must remove what it adds when it is finished.
24
 
+
25
 
+    couchdb -- the integer of the port number of the running couchdb
26
 
+    blocking_semaphores -- the set() of semaphores, which we will mutate
27
 
+    gobject -- the mainloop module. always 'gobject' except when testing.
28
 
+    """
29
 
     plugin_names = set()
30
 
     for path in DESKTOPCOUCH_PLUGIN_PATHS:
31
 
         try:
32
 
@@ -37,6 +47,6 @@
33
 
         modpath = name.replace(os.path.sep, '.')[:-3]
34
 
         try:
35
 
             plugin = __import__(modpath, None, None, [''])
36
 
-            plugin.plugin_init(couchdb_port)
37
 
+            plugin.plugin_init(couchdb_port, blocking_semaphores, gobject)
38
 
         except (ImportError, AttributeError):
39
 
             logging.warning('Failed to load plug-in: %s', modpath)
40
 
 
41
 
=== modified file 'desktopcouch/application/plugins/ubuntuone_pairing.py'
42
 
--- desktopcouch/application/plugins/ubuntuone_pairing.py       2011-02-02 18:15:53 +0000
43
 
+++ desktopcouch/application/plugins/ubuntuone_pairing.py       2011-04-15 23:41:29 +0000
44
 
@@ -24,6 +24,7 @@
45
 
 from desktopcouch.application.server import DesktopDatabase
46
 
 from ubuntuone.clientdefs import APP_NAME
47
 
 
48
 
+PLUGIN_NAME = __name__
49
 
 U1_PAIR_RECORD = "ubuntu_one_pair_record"
50
 
 MAP_JS = """function(doc) {
51
 
     if (doc.service_name == "ubuntuone") {
52
 
@@ -33,48 +34,57 @@
53
 
 """
54
 
 
55
 
 
56
 
-def pair_with_ubuntuone(couchdb_port, management_db=None,
57
 
+def pair_with_ubuntuone(couchdb_port, blocking_semaphores,
58
 
+                        management_db=None,
59
 
                         db_class=DesktopDatabase,
60
 
                         put_service_fn=put_static_paired_service):
61
 
     """Adds a pairing record with ubuntu one when needed."""
62
 
-    # Use explicit uri so that we do not access dbus service.
63
 
-    uri = "http://localhost:%s" % (couchdb_port,)
64
 
-    if not management_db:
65
 
-        management_db = db_class("management", uri=uri, create=True, ctx=None)
66
 
-    # we indeed have credentials to add to the pairing records
67
 
-    # but first we ensure that the required view is present
68
 
-    if not management_db.view_exists(U1_PAIR_RECORD, U1_PAIR_RECORD):
69
 
-        management_db.add_view(
70
 
-            U1_PAIR_RECORD, MAP_JS, design_doc=U1_PAIR_RECORD)
71
 
-    view_results = management_db.execute_view(U1_PAIR_RECORD, U1_PAIR_RECORD)
72
 
-    pairing_found = False
73
 
-    # Results should contain either one row or no rows
74
 
-    # If there is one row, its value will be 0, meaning that there is
75
 
-    #   already an Ubuntu One pairing record, or 1, meaning that there
76
 
-    #   was an Ubuntu One pairing record but it has since been unpaired
77
 
-    # Only create a new record if there is not one already. Specifically,
78
 
-    #   do not add the record if there is a deleted one, as this means
79
 
-    #   that the user explicitly unpaired it!
80
 
-    for row in view_results:
81
 
-        pairing_found = True
82
 
-        if row.value == 1:
83
 
-            logging.debug("Not adding desktopcouch pairing since the user "
84
 
-                "has explicitly unpaired with Ubuntu One")
85
 
-        else:
86
 
-            logging.debug("Not adding desktopcouch pairing since we are "
87
 
-                "already paired")
88
 
-    if not pairing_found:
89
 
-        put_service_fn(None, "ubuntuone", uri=uri, ctx=None)
90
 
-        logging.debug("Pairing desktopcouch with Ubuntu One")
91
 
-
92
 
-
93
 
-def got_new_credentials(couchdb_port, app_name, credentials):
94
 
+    try:
95
 
+        # Use explicit uri so that we do not access dbus service.
96
 
+        uri = "http://localhost:%s" % (couchdb_port,)
97
 
+        if not management_db:
98
 
+            management_db = db_class("management", uri=uri, create=True,
99
 
+                                     ctx=None)
100
 
+        # we indeed have credentials to add to the pairing records
101
 
+        # but first we ensure that the required view is present
102
 
+        if not management_db.view_exists(U1_PAIR_RECORD, U1_PAIR_RECORD):
103
 
+            management_db.add_view(
104
 
+                U1_PAIR_RECORD, MAP_JS, design_doc=U1_PAIR_RECORD)
105
 
+        view_results = management_db.execute_view(U1_PAIR_RECORD,
106
 
+                                                  U1_PAIR_RECORD)
107
 
+        pairing_found = False
108
 
+        # Results should contain either one row or no rows
109
 
+        # If there is one row, its value will be 0, meaning that there is
110
 
+        #   already an Ubuntu One pairing record, or 1, meaning that there
111
 
+        #   was an Ubuntu One pairing record but it has since been unpaired
112
 
+        # Only create a new record if there is not one already. Specifically,
113
 
+        #   do not add the record if there is a deleted one, as this means
114
 
+        #   that the user explicitly unpaired it!
115
 
+        for row in view_results:
116
 
+            pairing_found = True
117
 
+            if row.value == 1:
118
 
+                logging.debug("Not adding desktopcouch pairing since the user "
119
 
+                    "has explicitly unpaired with Ubuntu One")
120
 
+            else:
121
 
+                logging.debug("Not adding desktopcouch pairing since we are "
122
 
+                    "already paired")
123
 
+        if not pairing_found:
124
 
+            put_service_fn(None, "ubuntuone", uri=uri, ctx=None)
125
 
+            logging.debug("Pairing desktopcouch with Ubuntu One")
126
 
+
127
 
+    finally:
128
 
+        logging.info("removing semaphore for %s", PLUGIN_NAME)
129
 
+        blocking_semaphores.discard(PLUGIN_NAME)
130
 
+
131
 
+
132
 
+def got_new_credentials(couchdb_port, blocking_semaphores,
133
 
+                        app_name, credentials):
134
 
     """Pair with Ubuntu One when we get the new credentials."""
135
 
     if app_name == APP_NAME:
136
 
-        pair_with_ubuntuone(couchdb_port)
137
 
-
138
 
-
139
 
-def listen_to_dbus(couchdb_port):
140
 
+        pair_with_ubuntuone(couchdb_port, blocking_semaphores)
141
 
+
142
 
+
143
 
+def listen_to_dbus(couchdb_port, blocking_semaphores):
144
 
     """Set up the signal handler on D-Bus for Ubuntu One pairing."""
145
 
     import dbus
146
 
     bus = dbus.SessionBus()
147
 
@@ -82,7 +92,9 @@
148
 
     try:
149
 
         import ubuntu_sso
150
 
 
151
 
-        receiver = lambda *args: got_new_credentials(couchdb_port, *args)
152
 
+        receiver = lambda *args: \
153
 
+                got_new_credentials(couchdb_port, blocking_semaphores,
154
 
+                                                     *args)
155
 
 
156
 
         iface = ubuntu_sso.DBUS_CREDENTIALS_IFACE
157
 
         bus.add_signal_receiver(handler_function=receiver,
158
 
@@ -96,13 +108,20 @@
159
 
         sso_backend.find_credentials(APP_NAME, {})
160
 
     except ImportError:
161
 
         logging.info('Ubuntu SSO is not available.')
162
 
-
163
 
-
164
 
-def plugin_init(couchdb_port):
165
 
+        blocking_semaphores.discard(PLUGIN_NAME)
166
 
+
167
 
+
168
 
+def plugin_init(couchdb_port, blocking_semaphores, gobject):
169
 
     """Set up the signal handler for pairing with Ubuntu One."""
170
 
     logging.info('Loaded Ubuntu One extension for desktopcouch.')
171
 
     if sys.platform == 'win32':
172
 
         logging.warning('Windows support for Ubuntu One is not yet ready.')
173
 
     else:
174
 
-        import gobject
175
 
-        gobject.idle_add(listen_to_dbus, couchdb_port)
176
 
+
177
 
+        # Signal that we are critical for desktopcouch usage, and the server
178
 
+        # must not begin until we are finished.  We are responsible for
179
 
+        # removing this item from the list.
180
 
+        logging.info("adding %s to to blocking semaphore list", PLUGIN_NAME)
181
 
+        blocking_semaphores.add(PLUGIN_NAME)
182
 
+
183
 
+        gobject.idle_add(listen_to_dbus, couchdb_port, blocking_semaphores)
184
 
 
185
 
=== modified file 'desktopcouch/application/service.py'
186
 
--- desktopcouch/application/service.py 2011-02-02 18:15:53 +0000
187
 
+++ desktopcouch/application/service.py 2011-04-15 23:42:17 +0000
188
 
@@ -39,6 +39,7 @@
189
 
 import logging
190
 
 import logging.handlers
191
 
 import signal
192
 
+import gobject
193
 
 
194
 
 from desktopcouch.application import local_files
195
 
 from desktopcouch.application import replication
196
 
@@ -84,7 +85,8 @@
197
 
                  replication_actions=replication,
198
 
                  advertiser_factory=PortAdvertiser, set_logging=set_up_logging,
199
 
                  fork=os.fork, nice=os.nice,
200
 
-                 kill=os.kill, sleep=time.sleep):
201
 
+                 kill=os.kill, sleep=time.sleep, set_type=set,
202
 
+                 gobject_module=gobject):
203
 
         self._mainloop = main_loop
204
 
         self._pid_finder = pid_finder
205
 
         self._port_finder = port_finder
206
 
@@ -97,6 +99,8 @@
207
 
         self._nice = nice
208
 
         self._kill = kill
209
 
         self._sleep = sleep
210
 
+        self._set = set_type
211
 
+        self._gobject = gobject_module
212
 
     # pylint: enable=C0301
213
 
 
214
 
     def _start_replicator_main(self, couchdb_port):
215
 
@@ -112,11 +116,30 @@
216
 
                 replication.tear_down(*replication_runtime)
217
 
 
218
 
     def _start_server_main(self, couchdb_port):
219
 
-        """Start server."""
220
 
-        self._advertiser_factory(self._mainloop.stop, self._ctx)
221
 
+        """Start server answering DBus calls, and run plugins first."""
222
 
+
223
 
+        def if_all_semaphores_cleared(blocking_semaphores,
224
 
+                func, *args, **kwargs):
225
 
+            """Run a function if no semaphores exist, else try later."""
226
 
+            if blocking_semaphores:
227
 
+                return True  # Make idle call try us again.
228
 
+            else:
229
 
+                func(*args, **kwargs)
230
 
+                return False  # Handled!
231
 
+
232
 
+        blocking_semaphores = self._set()
233
 
+        load_plugins(couchdb_port, blocking_semaphores, self._gobject)
234
 
+
235
 
+        # Answering queries on DBus signals that we are ready for users
236
 
+        # to connect.  We mustn't begin that until every plugin has a chance
237
 
+        # to run to completion if it needs it.
238
 
+        self._gobject.idle_add(if_all_semaphores_cleared, blocking_semaphores,
239
 
+                               self._advertiser_factory,
240
 
+                               self._mainloop.stop,
241
 
+                               self._ctx)
242
 
+
243
 
         logging.debug("starting dbus main loop")
244
 
         try:
245
 
-            load_plugins(couchdb_port)
246
 
             self._mainloop.run()
247
 
         finally:
248
 
             logging.debug("ending dbus main loop")
249