Merge lp:~mhr3/libunity/dbus-activation-fixes into lp:libunity

Proposed by Michal Hruby
Status: Merged
Approved by: Didier Roche-Tolomelli
Approved revision: 114
Merged at revision: 115
Proposed branch: lp:~mhr3/libunity/dbus-activation-fixes
Merge into: lp:libunity
Diff against target: 259 lines (+125/-6)
6 files modified
src/unity-lens-private.vala (+2/-2)
src/unity-lens-search.vala (+12/-0)
src/unity-lens-tools.vala (+2/-1)
src/unity-scope-private.vala (+28/-2)
test/vala/test-lens.vala (+47/-1)
test/vala/test-remote-scope.vala (+34/-0)
To merge this branch: bzr merge lp:~mhr3/libunity/dbus-activation-fixes
Reviewer Review Type Date Requested Status
Mikkel Kamstrup Erlandsen (community) Approve
Review via email: mp+90919@code.launchpad.net

Description of the change

Fixes an issue where a search which didn't change the search key could finish before the search that was actually searching.

The problem manifested itself where a DBus-activated lens daemon would return a result set with model-seqnum=0. This was the case because all lenses call during initialization queue_search_changed() which creates a LensSearch instance with empty search string, this generates empty string search-key and therefore the actual Search method just returned because the search key didn't change from the last search.

The fix for this is to properly wait for the last search to finish before returning from the non-changed one.

Added test to detect this issue.

To post a comment you must log in.
Revision history for this message
Michal Hruby (mhr3) wrote :

This fixes the problem where DBus-activated lens daemon would return result set with model-seqnum=0. This was the case because all lenses call during initialization queue_search_changed() which creates a LensSearch instance with empty search string, this generates empty string search-key and therefore the actual Search method just returned because the search key didn't change from the last search.

The fix for this is to properly wait for the last search to finish before returning from the non-changed one.

Revision history for this message
Mikkel Kamstrup Erlandsen (kamstrup) wrote :

Looking good and tests are passing. Awesome work dude!

review: Approve
Revision history for this message
Unity Merger (unity-merger) wrote :

The Jenkins job https://jenkins.qa.ubuntu.com/job/automerge-libunity/46/console reported an error when processing this lp:~mhr3/libunity/dbus-activation-fixes branch.
Not merging it.

Revision history for this message
Didier Roche-Tolomelli (didrocks) wrote :

This one is due to https://code.launchpad.net/~mhr3/libunity/test-tool/+merge/91027 failing. sorry, I need to fix this race (should be easy, just have to take the time :))

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/unity-lens-private.vala'
--- src/unity-lens-private.vala 2012-01-09 17:40:45 +0000
+++ src/unity-lens-private.vala 2012-01-31 18:37:22 +0000
@@ -516,7 +516,7 @@
516 // wait for the results from all scopes - yield will wait for516 // wait for the results from all scopes - yield will wait for
517 // search.callback to resume execution, and that will be called once all517 // search.callback to resume execution, and that will be called once all
518 // scopes finish search (thanks to closure magic)518 // scopes finish search (thanks to closure magic)
519 yield;519 if (num_scopes > 0) yield;
520520
521 result.insert ("model-seqnum", new Variant.uint64 (_results_model.get_seqnum ()));521 result.insert ("model-seqnum", new Variant.uint64 (_results_model.get_seqnum ()));
522522
@@ -572,7 +572,7 @@
572 // wait for the results from all scopes - yield will wait for572 // wait for the results from all scopes - yield will wait for
573 // search.callback to resume execution, and that will be called once all573 // search.callback to resume execution, and that will be called once all
574 // scopes finish search (thanks to closure magic)574 // scopes finish search (thanks to closure magic)
575 yield;575 if (num_scopes > 0) yield;
576576
577 var result = new HashTable<string, Variant> (str_hash, str_equal);577 var result = new HashTable<string, Variant> (str_hash, str_equal);
578 result.insert ("model-seqnum", new Variant.uint64 (_global_results_model.get_seqnum ()));578 result.insert ("model-seqnum", new Variant.uint64 (_global_results_model.get_seqnum ()));
579579
=== modified file 'src/unity-lens-search.vala'
--- src/unity-lens-search.vala 2011-12-09 09:23:25 +0000
+++ src/unity-lens-search.vala 2012-01-31 18:37:22 +0000
@@ -49,6 +49,18 @@
49 results_model:results_model);49 results_model:results_model);
50 }50 }
5151
52 private bool got_finished = false;
53
54 construct
55 {
56 this.finished.connect (() => { got_finished = true; });
57 }
58
59 internal bool was_finished ()
60 {
61 return got_finished;
62 }
63
52 public bool equals (LensSearch? other)64 public bool equals (LensSearch? other)
53 {65 {
54 if (other == null ||66 if (other == null ||
5567
=== modified file 'src/unity-lens-tools.vala'
--- src/unity-lens-tools.vala 2012-01-05 10:29:50 +0000
+++ src/unity-lens-tools.vala 2012-01-31 18:37:22 +0000
@@ -203,7 +203,8 @@
203 }203 }
204 else204 else
205 {205 {
206 warning (@"Could not find row to remove: $(provider.get_string (iter, 0))");206 /* this can easily happen now that we support custom merge strategies */
207 debug (@"Could not find row to remove: $(provider.get_string (iter, 0))");
207 }208 }
208 }209 }
209210
210211
=== modified file 'src/unity-scope-private.vala'
--- src/unity-scope-private.vala 2012-01-17 20:38:42 +0000
+++ src/unity-scope-private.vala 2012-01-31 18:37:22 +0000
@@ -395,6 +395,9 @@
395 search_internal.callback ();395 search_internal.callback ();
396 });396 });
397397
398 LensSearch? last_search = null;
399 ulong ls_sig_id = 0;
400
398 string search_key = get_search_key (s, search_type);401 string search_key = get_search_key (s, search_type);
399 if ((search_key != null && search_key != search_keys[search_type]) ||402 if ((search_key != null && search_key != search_keys[search_type]) ||
400 (search_key == null && !s.equals (_owner.get_last_search (search_type))))403 (search_key == null && !s.equals (_owner.get_last_search (search_type))))
@@ -406,8 +409,28 @@
406 }409 }
407 else410 else
408 {411 {
409 // returning empty HashTable in this case (search_key didn't change)412 // search key didn't change, but the last search might not have finished
410 return result;413 // yet, let's wait for it if that's the case
414 last_search = _owner.get_last_search (search_type);
415 if (last_search != null && !last_search.was_finished ())
416 {
417 // wait for the last search to finish
418 ls_sig_id = last_search.finished.connect (() =>
419 {
420 s.finished ();
421 });
422
423 // update view_type if necessary, because schedule_search_changed
424 // might be waiting for it
425 ViewType current_view = is_global_search ?
426 ViewType.HOME_VIEW : ViewType.LENS_VIEW;
427 if (view_type != current_view) set_view_type (current_view);
428 }
429 else
430 {
431 // returning empty HashTable in this case (search_key didn't change)
432 return result;
433 }
411 }434 }
412435
413 // now we have a Cancellable associated with this search436 // now we have a Cancellable associated with this search
@@ -425,6 +448,7 @@
425 yield;448 yield;
426 // we just got finished signal, or the cancellable was cancelled449 // we just got finished signal, or the cancellable was cancelled
427450
451 if (ls_sig_id != 0) SignalHandler.disconnect (last_search, ls_sig_id);
428 SignalHandler.disconnect (s, sig_id);452 SignalHandler.disconnect (s, sig_id);
429 cancellable.disconnect (canc_id);453 cancellable.disconnect (canc_id);
430454
@@ -441,6 +465,7 @@
441 string search_string, HashTable<string, Variant> hints) throws Error465 string search_string, HashTable<string, Variant> hints) throws Error
442 {466 {
443 HashTable<string, Variant> result;467 HashTable<string, Variant> result;
468
444 result = yield search_internal (search_string, hints, SearchType.DEFAULT);469 result = yield search_internal (search_string, hints, SearchType.DEFAULT);
445470
446 return result;471 return result;
@@ -450,6 +475,7 @@
450 string search_string, HashTable<string, Variant> hints) throws Error475 string search_string, HashTable<string, Variant> hints) throws Error
451 {476 {
452 HashTable<string, Variant> result;477 HashTable<string, Variant> result;
478
453 result = yield search_internal (search_string, hints, SearchType.GLOBAL);479 result = yield search_internal (search_string, hints, SearchType.GLOBAL);
454480
455 return result;481 return result;
456482
=== modified file 'test/vala/test-lens.vala'
--- test/vala/test-lens.vala 2012-01-20 11:29:46 +0000
+++ test/vala/test-lens.vala 2012-01-31 18:37:22 +0000
@@ -47,6 +47,7 @@
47 Test.add_data_func ("/Unit/LocalScope/SearchChanged", test_local_scope_search);47 Test.add_data_func ("/Unit/LocalScope/SearchChanged", test_local_scope_search);
48 Test.add_data_func ("/Unit/LocalScope/MergeStrategy", test_merge_strategy);48 Test.add_data_func ("/Unit/LocalScope/MergeStrategy", test_merge_strategy);
49 Test.add_data_func ("/Unit/Lens/ReturnAfterScopeFinish", test_lens_return_after_scope_finish);49 Test.add_data_func ("/Unit/Lens/ReturnAfterScopeFinish", test_lens_return_after_scope_finish);
50 Test.add_data_func ("/Unit/Lens/SuccessiveSearches", test_lens_successive_searches);
50 Test.add_data_func ("/Unit/Lens/TwoSearches", test_lens_two_searches);51 Test.add_data_func ("/Unit/Lens/TwoSearches", test_lens_two_searches);
51 Test.add_data_func ("/Unit/Lens/ModelSync", test_lens_model_sync);52 Test.add_data_func ("/Unit/Lens/ModelSync", test_lens_model_sync);
52 Test.add_data_func ("/Unit/Lens/ReplyHint", test_lens_reply_hint);53 Test.add_data_func ("/Unit/Lens/ReplyHint", test_lens_reply_hint);
@@ -237,6 +238,7 @@
237 /* Since test cases are not completely isolated we need 238 /* Since test cases are not completely isolated we need
238 * to instantate the default merge strategy when done */239 * to instantate the default merge strategy when done */
239 var old_merge_strategy = exported_lens.merge_strategy;240 var old_merge_strategy = exported_lens.merge_strategy;
241 local_scope.results_model.clear ();
240 242
241 var merge_strategy = new TestMergeStrategy ();243 var merge_strategy = new TestMergeStrategy ();
242 exported_lens.merge_strategy = merge_strategy;244 exported_lens.merge_strategy = merge_strategy;
@@ -296,6 +298,51 @@
296 SignalHandler.disconnect (local_scope, sig_id);298 SignalHandler.disconnect (local_scope, sig_id);
297 }299 }
298300
301 public static void test_lens_successive_searches ()
302 {
303 assert (local_scope != null);
304
305 var ml = new MainLoop ();
306 bool got_search_changed = false;
307 bool finish_called = false;
308
309 ulong sig_id = local_scope.search_changed.connect ((lens_search) =>
310 {
311 got_search_changed = true;
312 Timeout.add (750, () =>
313 {
314 lens_search.results_model.clear ();
315 lens_search.results_model.append ("", "", 0, "", "", "", "");
316 lens_search.finished ();
317 finish_called = true;
318 return false;
319 });
320 });
321
322 // we want to make sure the Search DBus call doesn't return before we
323 // call finished on the LensSearch instance
324 Variant? result1 = null;
325 Variant? result2 = null;
326 call_lens_search ("successive-searches", (result) =>
327 {
328 result1 = result;
329 });
330 // and another search with the same search string, it shouldn't return first
331 call_lens_search ("successive-searches", (result) =>
332 {
333 result2 = result;
334 ml.quit ();
335 });
336
337 run_with_timeout (ml, 5000);
338
339 assert (got_search_changed == true);
340 assert (finish_called == true);
341 assert (result1.equal (result2));
342
343 SignalHandler.disconnect (local_scope, sig_id);
344 }
345
299 public static void test_lens_two_searches ()346 public static void test_lens_two_searches ()
300 {347 {
301 assert (local_scope != null);348 assert (local_scope != null);
@@ -460,7 +507,6 @@
460 {507 {
461 assert (local_scope != null);508 assert (local_scope != null);
462509
463 bool got_search_changed = false;
464 local_scope.sources.add_option ("id1", "Source1", null);510 local_scope.sources.add_option ("id1", "Source1", null);
465 local_scope.sources.add_option ("id2", "Source2", null);511 local_scope.sources.add_option ("id2", "Source2", null);
466512
467513
=== modified file 'test/vala/test-remote-scope.vala'
--- test/vala/test-remote-scope.vala 2012-01-20 11:29:46 +0000
+++ test/vala/test-remote-scope.vala 2012-01-31 18:37:22 +0000
@@ -28,6 +28,7 @@
28 Test.add_data_func ("/Integration/Scope/Export", test_scope_export);28 Test.add_data_func ("/Integration/Scope/Export", test_scope_export);
29 Test.add_data_func ("/Integration/Scope/Search", test_scope_search);29 Test.add_data_func ("/Integration/Scope/Search", test_scope_search);
30 Test.add_data_func ("/Integration/Scope/Search2", test_scope_search2);30 Test.add_data_func ("/Integration/Scope/Search2", test_scope_search2);
31 Test.add_data_func ("/Integration/Scope/SuccessiveSearches", test_scope_successive_searches);
31 Test.add_data_func ("/Integration/Scope/TwoSearches", test_scope_two_searches);32 Test.add_data_func ("/Integration/Scope/TwoSearches", test_scope_two_searches);
32 Test.add_data_func ("/Integration/Scope/ModelSync", test_scope_model_sync);33 Test.add_data_func ("/Integration/Scope/ModelSync", test_scope_model_sync);
33 Test.add_data_func ("/Integration/Scope/ReplyHint", test_scope_reply_hint);34 Test.add_data_func ("/Integration/Scope/ReplyHint", test_scope_reply_hint);
@@ -113,6 +114,39 @@
113 bus.flush_sync ();114 bus.flush_sync ();
114 }115 }
115116
117 public static void test_scope_successive_searches ()
118 {
119 // we expect that the lens will call the search method
120 assert (exported_scope != null);
121
122 var ml = new MainLoop ();
123 bool got_search_changed = false;
124
125 ulong sig_id = exported_scope.search_changed.connect ((lens_search, search_type, cancellable) =>
126 {
127 assert (lens_search.search_string == "successive-searches");
128 got_search_changed = true;
129 // wait a while to emit the finished signal
130 Timeout.add (500, () =>
131 {
132 lens_search.finished ();
133 ml.quit ();
134 return false;
135 });
136 });
137
138 Timeout.add (2000, () => { ml.quit (); return false; });
139 ml.run ();
140
141 // earlier searches need to cancelled if there's a newer search
142 assert (got_search_changed == true);
143
144 SignalHandler.disconnect (exported_scope, sig_id);
145
146 var bus = Bus.get_sync (BusType.SESSION);
147 bus.flush_sync ();
148 }
149
116 public static void test_scope_two_searches ()150 public static void test_scope_two_searches ()
117 {151 {
118 // we expect that the lens will call the search method152 // we expect that the lens will call the search method

Subscribers

People subscribed via source and target branches