Merge lp:~mhr3/libunity/multiple-fixes into lp:libunity

Proposed by Michal Hruby
Status: Merged
Approved by: James Henstridge
Approved revision: 271
Merged at revision: 269
Proposed branch: lp:~mhr3/libunity/multiple-fixes
Merge into: lp:libunity
Diff against target: 332 lines (+126/-32)
4 files modified
src/unity-aggregator-scope-private.vala (+24/-9)
src/unity-master-scope.vala (+43/-5)
src/unity-scope-dbus-connector.vala (+24/-9)
src/unity-scope-dbus-impl.vala (+35/-9)
To merge this branch: bzr merge lp:~mhr3/libunity/multiple-fixes
Reviewer Review Type Date Requested Status
James Henstridge Approve
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+178458@code.launchpad.net

Commit message

Apps scope port-related fixes

Description of the change

Apps scope port-related fixes:
1) fix ScopeDBusConnector incorrectly unexporting unused scopes
2) try to coalesce transactions when talking to multiple scopes
3) a small behaviour change to sorting

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
James Henstridge (jamesh) wrote :

Looks good. At first I was a little confused by the use of multiplier for null string properties, but it made sense after reading the comment again.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/unity-aggregator-scope-private.vala'
2--- src/unity-aggregator-scope-private.vala 2013-07-25 10:21:46 +0000
3+++ src/unity-aggregator-scope-private.vala 2013-08-04 13:41:25 +0000
4@@ -159,8 +159,6 @@
5 dummy2 = var2.lookup_value ("content", VariantType.VARDICT).lookup_value (field_name, null);
6 // handle non-presence of optional fields
7 if (dummy1 == null && dummy2 == null) return 0;
8- if (dummy1 == null || dummy2 == null)
9- return dummy1 == null ? 1 : -1;
10 var1 = dummy1;
11 var2 = dummy2;
12 }
13@@ -168,23 +166,40 @@
14 switch (schema)
15 {
16 case 's':
17- // FIXME: implement a way to use simple ascii sort
18- result = var1.get_string ().collate (var2.get_string ());
19+ // strings are special, if optional field is not present,
20+ // bury the result; numeric types behave as if 0 was set
21+ if (var1 == null) result = 1 * multiplier;
22+ else if (var2 == null) result = -1 * multiplier;
23+ else
24+ {
25+ // FIXME: implement a way to use simple ascii sort
26+ result = var1.get_string ().collate (var2.get_string ());
27+ }
28 break;
29 case 'i':
30- result = compare_int (var1.get_int32 (), var2.get_int32 ());
31+ int i1 = var1 != null ? var1.get_int32 () : 0;
32+ int i2 = var2 != null ? var2.get_int32 () : 0;
33+ result = compare_int (i1, i2);
34 break;
35 case 'u':
36- result = compare_uint (var1.get_uint32 (), var2.get_uint32 ());
37+ uint u1 = var1 != null ? var1.get_uint32 () : 0;
38+ uint u2 = var2 != null ? var2.get_uint32 () : 0;
39+ result = compare_uint (u1, u2);
40 break;
41 case 'x':
42- result = compare_int64 (var1.get_int64 (), var2.get_int64 ());
43+ int64 x1 = var1 != null ? var1.get_int64 () : 0;
44+ int64 x2 = var2 != null ? var2.get_int64 () : 0;
45+ result = compare_int64 (x1, x2);
46 break;
47 case 't':
48- result = compare_uint64 (var1.get_uint64 (), var2.get_uint64 ());
49+ uint64 t1 = var1 != null ? var1.get_uint64 () : 0;
50+ uint64 t2 = var2 != null ? var2.get_uint64 () : 0;
51+ result = compare_uint64 (t1, t2);
52 break;
53 case 'd':
54- result = compare_double (var1.get_double (), var2.get_double ());
55+ double d1 = var1 != null ? var1.get_double () : 0.0;
56+ double d2 = var2 != null ? var2.get_double () : 0.0;
57+ result = compare_double (d1, d2);
58 break;
59 default:
60 return 0;
61
62=== modified file 'src/unity-master-scope.vala'
63--- src/unity-master-scope.vala 2013-05-01 22:30:59 +0000
64+++ src/unity-master-scope.vala 2013-08-04 13:41:25 +0000
65@@ -24,10 +24,13 @@
66
67 public class MasterScope : AggregatorScope
68 {
69+ const int COALESCE_TIME_MS = 150;
70+
71 public MasterScope (string dbus_path_, string id_)
72 {
73 Object (dbus_path: dbus_path_, id: id_, is_master: true,
74- merge_mode: AggregatorScope.MergeMode.CATEGORY_ID, proxy_filter_hints: true);
75+ merge_mode: AggregatorScope.MergeMode.CATEGORY_ID,
76+ proxy_filter_hints: true, automatic_flushing: false);
77 }
78
79 public string no_content_hint { get; set; }
80@@ -94,7 +97,9 @@
81 var registry = registry_once.get_data ();
82 if (registry == null) return;
83
84- uint num_scopes = 0;
85+ uint total_searches = 0;
86+ uint running_searches = 0;
87+ uint timer_source_id = 0;
88
89 AsyncReadyCallback cb = (obj, res) =>
90 {
91@@ -108,7 +113,7 @@
92 if (!(err is IOError.CANCELLED))
93 warning ("Unable to search scope: '%s'", err.message);
94 }
95- if (--num_scopes == 0) search.callback ();
96+ if (--running_searches == 0) search.callback ();
97 };
98
99 string[] search_subscopes = {};
100@@ -119,6 +124,31 @@
101 search_subscopes = (string[]) filter_variant;
102 }
103
104+ ulong sig_id;
105+ sig_id = scope_search.transaction_complete.connect ((agg_scope_search, scope_id) =>
106+ {
107+ // if we're searching multiple scopes, try to coalesce the changes,
108+ // otherwise flush the changes immediately
109+ if (total_searches <= 1)
110+ {
111+ agg_scope_search.search_context.result_set.flush ();
112+ }
113+ else
114+ {
115+ // TODO: do this only if this channel is "visible" (opened by the dash)
116+ if (timer_source_id != 0) return;
117+ timer_source_id = Timeout.add (COALESCE_TIME_MS, () =>
118+ {
119+ if (!agg_scope_search.search_context.cancellable.is_cancelled ())
120+ {
121+ agg_scope_search.search_context.result_set.flush ();
122+ }
123+ timer_source_id = 0;
124+ return false;
125+ });
126+ }
127+ });
128+
129 foreach (var scope_node in registry.scopes)
130 {
131 if (search_subscopes.length > 0 && !(scope_node.scope_info.id in search_subscopes))
132@@ -126,7 +156,8 @@
133
134 if (metadata_matches (scope_node.scope_info))
135 {
136- num_scopes++;
137+ total_searches++;
138+ running_searches++;
139 scope_search.search_scope.begin (scope_node.scope_info.id,
140 scope_search.search_string,
141 scope_search.search_type,
142@@ -139,7 +170,14 @@
143 }
144 }
145
146- if (num_scopes > 0) yield;
147+ if (running_searches > 0) yield;
148+
149+ SignalHandler.disconnect (scope_search, sig_id);
150+ if (timer_source_id != 0)
151+ {
152+ Source.remove (timer_source_id);
153+ scope_search.search_context.result_set.flush ();
154+ }
155
156 if (scope_search.results_model.get_n_rows () == 0
157 && scope_search.search_context.search_query.strip () == ""
158
159=== modified file 'src/unity-scope-dbus-connector.vala'
160--- src/unity-scope-dbus-connector.vala 2013-06-19 01:31:25 +0000
161+++ src/unity-scope-dbus-connector.vala 2013-08-04 13:41:25 +0000
162@@ -42,6 +42,7 @@
163 private Internal.DefaultScopeDBusImpl pimpl;
164 private bool exported;
165 private bool name_owned;
166+ private ulong name_unowned_id;
167
168 private static int proxy_usage_count = 0;
169
170@@ -51,7 +52,8 @@
171 {
172 if (pimpl == null) pimpl = new Internal.DefaultScopeDBusImpl (scope);
173 pimpl.timeout = DAEMON_TIMEOUT_SEC;
174- pimpl.on_timeout_reached.connect (timeout_reached);
175+ pimpl.on_timeout_reached.connect (on_inactivity_timeout_reached);
176+ pimpl.on_unexport_timeout_reached.connect (on_unexport_timeout_reached);
177 pimpl.export ();
178 exported = true;
179 own_name ();
180@@ -72,15 +74,22 @@
181 }
182 }
183
184- private void timeout_reached ()
185+ private void on_inactivity_timeout_reached ()
186 {
187+ // there were no requests to this for a while, prepare to exit
188 unown_name ();
189- Timeout.add_seconds_full (Priority.DEFAULT_IDLE, 30, () =>
190- {
191- unexport ();
192- if (proxy_usage_count == 0) quit ();
193- return false;
194- });
195+ }
196+
197+ private void on_unexport_timeout_reached ()
198+ {
199+ unexport ();
200+ if (proxy_usage_count == 0) quit ();
201+ }
202+
203+ private void on_name_unowned ()
204+ {
205+ // not starting a timer here, cause it would keep this object alive
206+ pimpl.start_unexport_timer ();
207 }
208
209 private void own_name ()
210@@ -89,9 +98,15 @@
211 var dbus_name = scope.get_group_name ();
212 manager.own_name (dbus_name);
213 name_owned = true;
214+
215+ if (name_unowned_id == 0)
216+ {
217+ name_unowned_id = manager.name_unowned[dbus_name].connect (
218+ this.on_name_unowned);
219+ }
220 }
221
222- private void unown_name()
223+ private void unown_name ()
224 {
225 if (name_owned)
226 {
227
228=== modified file 'src/unity-scope-dbus-impl.vala'
229--- src/unity-scope-dbus-impl.vala 2013-07-24 13:15:22 +0000
230+++ src/unity-scope-dbus-impl.vala 2013-08-04 13:41:25 +0000
231@@ -51,7 +51,8 @@
232 private string _dbus_name;
233 private DBusConnection? _dbus_connection;
234 private Rand _rand;
235- private uint _timeout_source_id;
236+ private uint _inactivity_timeout_source_id;
237+ private uint _unexport_timeout_source_id;
238 private ulong _scope_results_invalidated_id;
239 private bool _query_happened;
240
241@@ -66,6 +67,7 @@
242 public int timeout { get; set; default = -1; }
243
244 public signal void on_timeout_reached ();
245+ public signal void on_unexport_timeout_reached ();
246
247 public DefaultScopeDBusImpl (AbstractScope owner)
248 {
249@@ -74,10 +76,16 @@
250
251 protected override void dispose ()
252 {
253- if (_timeout_source_id != 0)
254- {
255- Source.remove (_timeout_source_id);
256- _timeout_source_id = 0;
257+ if (_inactivity_timeout_source_id != 0)
258+ {
259+ Source.remove (_inactivity_timeout_source_id);
260+ _inactivity_timeout_source_id = 0;
261+ }
262+
263+ if (_unexport_timeout_source_id != 0)
264+ {
265+ Source.remove (_unexport_timeout_source_id);
266+ _unexport_timeout_source_id = 0;
267 }
268 }
269
270@@ -164,6 +172,20 @@
271 }
272 }
273
274+ public void start_unexport_timer ()
275+ {
276+ if (_unexport_timeout_source_id != 0)
277+ Source.remove (_unexport_timeout_source_id);
278+
279+ _unexport_timeout_source_id =
280+ Timeout.add_seconds_full (Priority.DEFAULT_IDLE, 30, () =>
281+ {
282+ this.on_unexport_timeout_reached ();
283+ _unexport_timeout_source_id = 0;
284+ return false;
285+ });
286+ }
287+
288 private VariantBuilder? changed_props;
289
290 public void queue_property_notification (string prop_name, Variant prop_value)
291@@ -327,7 +349,7 @@
292 }
293 else
294 {
295- _timeout_source_id = 0;
296+ _inactivity_timeout_source_id = 0;
297 on_timeout_reached ();
298 return false;
299 }
300@@ -599,9 +621,9 @@
301 // after first search request, a timeout is started and if no activity
302 // happens while the timeout runs, the on_timeout_reached signal
303 // will be emitted, which might end up quitting this process
304- if (_timeout_source_id == 0)
305+ if (_inactivity_timeout_source_id == 0)
306 {
307- _timeout_source_id = Timeout.add_seconds_full (Priority.DEFAULT_IDLE,
308+ _inactivity_timeout_source_id = Timeout.add_seconds_full (Priority.DEFAULT_IDLE,
309 (uint) timeout,
310 timeout_reached);
311 }
312@@ -841,6 +863,9 @@
313 }
314 }
315
316+ [Signal (detailed=true)]
317+ public signal void name_unowned ();
318+
319 public void unown_name (string dbus_name)
320 {
321 unowned Internal.OwnedName? info = owned_names.get (dbus_name);
322@@ -853,8 +878,9 @@
323 if (info.bus_name_own_handle != 0)
324 {
325 Bus.unown_name (info.bus_name_own_handle);
326+ Signal.emit_by_name (this, "name_unowned::" + dbus_name, typeof (void));
327 }
328- owned_names.remove(dbus_name);
329+ owned_names.remove (dbus_name);
330 }
331 }
332 }

Subscribers

People subscribed via source and target branches