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
1=== modified file 'src/unity-lens-private.vala'
2--- src/unity-lens-private.vala 2012-01-09 17:40:45 +0000
3+++ src/unity-lens-private.vala 2012-01-31 18:37:22 +0000
4@@ -516,7 +516,7 @@
5 // wait for the results from all scopes - yield will wait for
6 // search.callback to resume execution, and that will be called once all
7 // scopes finish search (thanks to closure magic)
8- yield;
9+ if (num_scopes > 0) yield;
10
11 result.insert ("model-seqnum", new Variant.uint64 (_results_model.get_seqnum ()));
12
13@@ -572,7 +572,7 @@
14 // wait for the results from all scopes - yield will wait for
15 // search.callback to resume execution, and that will be called once all
16 // scopes finish search (thanks to closure magic)
17- yield;
18+ if (num_scopes > 0) yield;
19
20 var result = new HashTable<string, Variant> (str_hash, str_equal);
21 result.insert ("model-seqnum", new Variant.uint64 (_global_results_model.get_seqnum ()));
22
23=== modified file 'src/unity-lens-search.vala'
24--- src/unity-lens-search.vala 2011-12-09 09:23:25 +0000
25+++ src/unity-lens-search.vala 2012-01-31 18:37:22 +0000
26@@ -49,6 +49,18 @@
27 results_model:results_model);
28 }
29
30+ private bool got_finished = false;
31+
32+ construct
33+ {
34+ this.finished.connect (() => { got_finished = true; });
35+ }
36+
37+ internal bool was_finished ()
38+ {
39+ return got_finished;
40+ }
41+
42 public bool equals (LensSearch? other)
43 {
44 if (other == null ||
45
46=== modified file 'src/unity-lens-tools.vala'
47--- src/unity-lens-tools.vala 2012-01-05 10:29:50 +0000
48+++ src/unity-lens-tools.vala 2012-01-31 18:37:22 +0000
49@@ -203,7 +203,8 @@
50 }
51 else
52 {
53- warning (@"Could not find row to remove: $(provider.get_string (iter, 0))");
54+ /* this can easily happen now that we support custom merge strategies */
55+ debug (@"Could not find row to remove: $(provider.get_string (iter, 0))");
56 }
57 }
58
59
60=== modified file 'src/unity-scope-private.vala'
61--- src/unity-scope-private.vala 2012-01-17 20:38:42 +0000
62+++ src/unity-scope-private.vala 2012-01-31 18:37:22 +0000
63@@ -395,6 +395,9 @@
64 search_internal.callback ();
65 });
66
67+ LensSearch? last_search = null;
68+ ulong ls_sig_id = 0;
69+
70 string search_key = get_search_key (s, search_type);
71 if ((search_key != null && search_key != search_keys[search_type]) ||
72 (search_key == null && !s.equals (_owner.get_last_search (search_type))))
73@@ -406,8 +409,28 @@
74 }
75 else
76 {
77- // returning empty HashTable in this case (search_key didn't change)
78- return result;
79+ // search key didn't change, but the last search might not have finished
80+ // yet, let's wait for it if that's the case
81+ last_search = _owner.get_last_search (search_type);
82+ if (last_search != null && !last_search.was_finished ())
83+ {
84+ // wait for the last search to finish
85+ ls_sig_id = last_search.finished.connect (() =>
86+ {
87+ s.finished ();
88+ });
89+
90+ // update view_type if necessary, because schedule_search_changed
91+ // might be waiting for it
92+ ViewType current_view = is_global_search ?
93+ ViewType.HOME_VIEW : ViewType.LENS_VIEW;
94+ if (view_type != current_view) set_view_type (current_view);
95+ }
96+ else
97+ {
98+ // returning empty HashTable in this case (search_key didn't change)
99+ return result;
100+ }
101 }
102
103 // now we have a Cancellable associated with this search
104@@ -425,6 +448,7 @@
105 yield;
106 // we just got finished signal, or the cancellable was cancelled
107
108+ if (ls_sig_id != 0) SignalHandler.disconnect (last_search, ls_sig_id);
109 SignalHandler.disconnect (s, sig_id);
110 cancellable.disconnect (canc_id);
111
112@@ -441,6 +465,7 @@
113 string search_string, HashTable<string, Variant> hints) throws Error
114 {
115 HashTable<string, Variant> result;
116+
117 result = yield search_internal (search_string, hints, SearchType.DEFAULT);
118
119 return result;
120@@ -450,6 +475,7 @@
121 string search_string, HashTable<string, Variant> hints) throws Error
122 {
123 HashTable<string, Variant> result;
124+
125 result = yield search_internal (search_string, hints, SearchType.GLOBAL);
126
127 return result;
128
129=== modified file 'test/vala/test-lens.vala'
130--- test/vala/test-lens.vala 2012-01-20 11:29:46 +0000
131+++ test/vala/test-lens.vala 2012-01-31 18:37:22 +0000
132@@ -47,6 +47,7 @@
133 Test.add_data_func ("/Unit/LocalScope/SearchChanged", test_local_scope_search);
134 Test.add_data_func ("/Unit/LocalScope/MergeStrategy", test_merge_strategy);
135 Test.add_data_func ("/Unit/Lens/ReturnAfterScopeFinish", test_lens_return_after_scope_finish);
136+ Test.add_data_func ("/Unit/Lens/SuccessiveSearches", test_lens_successive_searches);
137 Test.add_data_func ("/Unit/Lens/TwoSearches", test_lens_two_searches);
138 Test.add_data_func ("/Unit/Lens/ModelSync", test_lens_model_sync);
139 Test.add_data_func ("/Unit/Lens/ReplyHint", test_lens_reply_hint);
140@@ -237,6 +238,7 @@
141 /* Since test cases are not completely isolated we need
142 * to instantate the default merge strategy when done */
143 var old_merge_strategy = exported_lens.merge_strategy;
144+ local_scope.results_model.clear ();
145
146 var merge_strategy = new TestMergeStrategy ();
147 exported_lens.merge_strategy = merge_strategy;
148@@ -296,6 +298,51 @@
149 SignalHandler.disconnect (local_scope, sig_id);
150 }
151
152+ public static void test_lens_successive_searches ()
153+ {
154+ assert (local_scope != null);
155+
156+ var ml = new MainLoop ();
157+ bool got_search_changed = false;
158+ bool finish_called = false;
159+
160+ ulong sig_id = local_scope.search_changed.connect ((lens_search) =>
161+ {
162+ got_search_changed = true;
163+ Timeout.add (750, () =>
164+ {
165+ lens_search.results_model.clear ();
166+ lens_search.results_model.append ("", "", 0, "", "", "", "");
167+ lens_search.finished ();
168+ finish_called = true;
169+ return false;
170+ });
171+ });
172+
173+ // we want to make sure the Search DBus call doesn't return before we
174+ // call finished on the LensSearch instance
175+ Variant? result1 = null;
176+ Variant? result2 = null;
177+ call_lens_search ("successive-searches", (result) =>
178+ {
179+ result1 = result;
180+ });
181+ // and another search with the same search string, it shouldn't return first
182+ call_lens_search ("successive-searches", (result) =>
183+ {
184+ result2 = result;
185+ ml.quit ();
186+ });
187+
188+ run_with_timeout (ml, 5000);
189+
190+ assert (got_search_changed == true);
191+ assert (finish_called == true);
192+ assert (result1.equal (result2));
193+
194+ SignalHandler.disconnect (local_scope, sig_id);
195+ }
196+
197 public static void test_lens_two_searches ()
198 {
199 assert (local_scope != null);
200@@ -460,7 +507,6 @@
201 {
202 assert (local_scope != null);
203
204- bool got_search_changed = false;
205 local_scope.sources.add_option ("id1", "Source1", null);
206 local_scope.sources.add_option ("id2", "Source2", null);
207
208
209=== modified file 'test/vala/test-remote-scope.vala'
210--- test/vala/test-remote-scope.vala 2012-01-20 11:29:46 +0000
211+++ test/vala/test-remote-scope.vala 2012-01-31 18:37:22 +0000
212@@ -28,6 +28,7 @@
213 Test.add_data_func ("/Integration/Scope/Export", test_scope_export);
214 Test.add_data_func ("/Integration/Scope/Search", test_scope_search);
215 Test.add_data_func ("/Integration/Scope/Search2", test_scope_search2);
216+ Test.add_data_func ("/Integration/Scope/SuccessiveSearches", test_scope_successive_searches);
217 Test.add_data_func ("/Integration/Scope/TwoSearches", test_scope_two_searches);
218 Test.add_data_func ("/Integration/Scope/ModelSync", test_scope_model_sync);
219 Test.add_data_func ("/Integration/Scope/ReplyHint", test_scope_reply_hint);
220@@ -113,6 +114,39 @@
221 bus.flush_sync ();
222 }
223
224+ public static void test_scope_successive_searches ()
225+ {
226+ // we expect that the lens will call the search method
227+ assert (exported_scope != null);
228+
229+ var ml = new MainLoop ();
230+ bool got_search_changed = false;
231+
232+ ulong sig_id = exported_scope.search_changed.connect ((lens_search, search_type, cancellable) =>
233+ {
234+ assert (lens_search.search_string == "successive-searches");
235+ got_search_changed = true;
236+ // wait a while to emit the finished signal
237+ Timeout.add (500, () =>
238+ {
239+ lens_search.finished ();
240+ ml.quit ();
241+ return false;
242+ });
243+ });
244+
245+ Timeout.add (2000, () => { ml.quit (); return false; });
246+ ml.run ();
247+
248+ // earlier searches need to cancelled if there's a newer search
249+ assert (got_search_changed == true);
250+
251+ SignalHandler.disconnect (exported_scope, sig_id);
252+
253+ var bus = Bus.get_sync (BusType.SESSION);
254+ bus.flush_sync ();
255+ }
256+
257 public static void test_scope_two_searches ()
258 {
259 // we expect that the lens will call the search method

Subscribers

People subscribed via source and target branches