Merge lp:~charlesk/keeper/make-com.canonical.keeper.User.State-great-again into lp:keeper

Proposed by Charles Kerr
Status: Merged
Merge reported by: Xavi Garcia
Merged at revision: not available
Proposed branch: lp:~charlesk/keeper/make-com.canonical.keeper.User.State-great-again
Merge into: lp:keeper
Diff against target: 449 lines (+271/-76)
3 files modified
src/service/keeper-user.cpp (+1/-6)
src/service/keeper.cpp (+267/-70)
src/service/keeper.h (+3/-0)
To merge this branch: bzr merge lp:~charlesk/keeper/make-com.canonical.keeper.User.State-great-again
Reviewer Review Type Date Requested Status
Xavi Garcia (community) Approve
Review via email: mp+302603@code.launchpad.net

Commit message

First draft of returning meaningful values when com.canonical.keeper.User.State() is called.

Description of the change

First draft of returning meaningful values when com.canonical.keeper.User.State() is called.

To post a comment you must log in.
77. By Charles Kerr

in service/keeper.cpp, only rebuild the parts of state_ that change

78. By Charles Kerr

improve state notification

Revision history for this message
Xavi Garcia (xavi-garcia-mena) wrote :

Looks good

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/service/keeper-user.cpp'
2--- src/service/keeper-user.cpp 2016-08-08 06:06:49 +0000
3+++ src/service/keeper-user.cpp 2016-08-11 00:30:32 +0000
4@@ -96,10 +96,5 @@
5 QVariantDictMap
6 KeeperUser::get_state() const
7 {
8- // FIXME: writeme (the code below is junk 'hello world' data for testing in d-feet)
9-
10- QVariantDictMap ret;
11- for (const auto& item : keeper_.get_backup_choices())
12- ret[item.uuid()];
13- return ret;
14+ return keeper_.get_state();
15 }
16
17=== modified file 'src/service/keeper.cpp'
18--- src/service/keeper.cpp 2016-08-10 07:34:02 +0000
19+++ src/service/keeper.cpp 2016-08-11 00:30:32 +0000
20@@ -24,6 +24,7 @@
21 #include "service/metadata-provider.h"
22 #include "service/keeper.h"
23 #include "storage-framework/storage_framework_client.h"
24+#include "util/dbus-utils.h"
25
26 #include <QDebug>
27 #include <QDBusMessage>
28@@ -38,31 +39,32 @@
29
30 class KeeperPrivate
31 {
32+ enum class TaskType { BACKUP, RESTORE };
33+
34+ struct TaskData
35+ {
36+ QString action;
37+ QString error;
38+ TaskType type;
39+ Metadata metadata;
40+ float percent_done;
41+ };
42+
43 public:
44
45- Keeper * const q_ptr;
46- QSharedPointer<HelperRegistry> helper_registry_;
47- QSharedPointer<MetadataProvider> backup_choices_;
48- QSharedPointer<MetadataProvider> restore_choices_;
49 QScopedPointer<BackupHelper> backup_helper_;
50 QScopedPointer<StorageFrameworkClient> storage_;
51- QVector<Metadata> cached_backup_choices_;
52- QVector<Metadata> cached_restore_choices_;
53- QStringList remaining_tasks_;
54
55 KeeperPrivate(Keeper* keeper,
56 const QSharedPointer<HelperRegistry>& helper_registry,
57 const QSharedPointer<MetadataProvider>& backup_choices,
58 const QSharedPointer<MetadataProvider>& restore_choices)
59- : q_ptr(keeper)
60+ : backup_helper_(new BackupHelper(DEKKO_APP_ID))
61+ , storage_(new StorageFrameworkClient())
62+ , q_ptr(keeper)
63 , helper_registry_(helper_registry)
64 , backup_choices_(backup_choices)
65 , restore_choices_(restore_choices)
66- , backup_helper_(new BackupHelper(DEKKO_APP_ID))
67- , storage_(new StorageFrameworkClient())
68- , cached_backup_choices_()
69- , cached_restore_choices_()
70- , remaining_tasks_()
71 {
72 // listen for backup helper state changes
73 QObject::connect(backup_helper_.data(), &Helper::state_changed,
74@@ -79,44 +81,62 @@
75
76 Q_DISABLE_COPY(KeeperPrivate)
77
78- void start_task(QString const &uuid)
79+ void start_tasks(QStringList const& uuids)
80 {
81- qDebug() << "Starting task: " << uuid;
82- auto metadata = get_uuid_metadata(cached_backup_choices_, uuid);
83- if (metadata.uuid() == uuid)
84- {
85- qDebug() << "Task is a backup task";
86-
87- const auto urls = helper_registry_->get_backup_helper_urls(metadata);
88- if (urls.isEmpty())
89+ if (!remaining_tasks_.isEmpty())
90+ {
91+ // FIXME: return a dbus error here
92+ qWarning() << "keeper is already active";
93+ return;
94+ }
95+
96+ all_tasks_.clear();
97+ task_data_.clear();
98+ state_.clear();
99+
100+ for(auto const& uuid : uuids)
101+ {
102+ Metadata m;
103+ TaskType type;
104+ if (!find_task_metadata(uuid, m, type))
105 {
106- // TODO Report error to user
107- qWarning() << "ERROR: uuid: " << uuid << " has no url";
108- return;
109+ qCritical() << "uuid" << uuid << "not found; skipping";
110+ continue;
111 }
112
113- backup_helper_->start(urls);
114- }
115- }
116-
117- void start_tasks(QStringList const& tasks)
118- {
119- remaining_tasks_ = tasks;
120- start_remaining_tasks();
121- }
122-
123- void start_remaining_tasks()
124- {
125- if (remaining_tasks_.size())
126- {
127- auto task = remaining_tasks_.takeFirst();
128- start_task(task);
129- }
130- }
131-
132- void clear_remaining_taks()
133- {
134- remaining_tasks_.clear();
135+ all_tasks_ << uuid;
136+ remaining_tasks_ << uuid;
137+
138+ auto& td = task_data_[uuid];
139+ td.metadata = m;
140+ td.type = type;
141+ td.action = QStringLiteral("queued");
142+
143+ update_task_state(td);
144+ }
145+
146+ start_next_task();
147+ }
148+
149+ QVector<Metadata> get_backup_choices() const
150+ {
151+ if (cached_backup_choices_.isEmpty())
152+ cached_backup_choices_ = backup_choices_->get_backups();
153+
154+ return cached_backup_choices_;
155+ }
156+
157+ QVector<Metadata> get_restore_choices() const
158+ {
159+ if (cached_restore_choices_.isEmpty())
160+ cached_restore_choices_ = restore_choices_->get_backups();
161+
162+ return cached_restore_choices_;
163+ }
164+
165+ QVariantDictMap get_state() const
166+ {
167+ return state_;
168 }
169
170 private:
171@@ -133,14 +153,20 @@
172 break;
173
174 case Helper::State::CANCELLED:
175+ set_current_task_action(QStringLiteral("cancelled"));
176 qDebug() << "Backup helper cancelled... closing the socket.";
177 storage_->finish(false);
178 break;
179+
180 case Helper::State::FAILED:
181+ set_current_task_action(QStringLiteral("failed"));
182 qDebug() << "Backup helper failed... closing the socket.";
183 storage_->finish(false);
184 break;
185+
186 case Helper::State::COMPLETE:
187+ task_data_[current_task_].percent_done = 1;
188+ set_current_task_action(QStringLiteral("complete"));
189 qDebug() << "Backup helper finished... closing the socket.";
190 storage_->finish(true);
191 break;
192@@ -150,20 +176,191 @@
193 void on_storage_framework_finished()
194 {
195 qDebug() << "storage framework has finished for the current task";
196- start_remaining_tasks();
197- }
198-
199- Metadata get_uuid_metadata(QVector<Metadata> const &metadata, QString const & uuid)
200- {
201- for (auto item : metadata)
202- {
203- if (item.uuid() == uuid)
204+ start_next_task();
205+ }
206+
207+ /***
208+ **** Task Queueing
209+ ***/
210+
211+ void start_next_task()
212+ {
213+ current_task_.clear();
214+
215+ while (!remaining_tasks_.isEmpty())
216+ {
217+ auto uuid = remaining_tasks_.takeFirst();
218+
219+ if (start_task(uuid))
220+ break;
221+ }
222+ }
223+
224+ bool start_task(QString const& uuid)
225+ {
226+ if (!task_data_.contains(uuid))
227+ {
228+ qCritical() << "no task data found for" << uuid;
229+ return false;
230+ }
231+
232+ auto& td = task_data_[uuid];
233+ if (td.type == TaskType::BACKUP)
234+ {
235+ qDebug() << "Task is a backup task";
236+
237+ const auto urls = helper_registry_->get_backup_helper_urls(td.metadata);
238+ if (urls.isEmpty())
239 {
240- return item;
241- }
242- }
243- return Metadata();
244- }
245+ td.action = "failed";
246+ td.error = "no helper information in registry";
247+ qWarning() << "ERROR: uuid: " << uuid << " has no url";
248+ return false;
249+ }
250+
251+ current_task_ = uuid;
252+ set_current_task_action(QStringLiteral("saving"));
253+ backup_helper_->start(urls);
254+ return true;
255+ }
256+ else // RESTORE
257+ {
258+ current_task_ = uuid;
259+ set_current_task_action(QStringLiteral("restoring"));
260+ qWarning() << "restore not implemented yet";
261+ return false;
262+ }
263+ }
264+
265+ /***
266+ **** State
267+ ***/
268+
269+ void update_task_state(QString const& uuid)
270+ {
271+ auto it = task_data_.find(uuid);
272+ if (it == task_data_.end())
273+ {
274+ qCritical() << "no task data for" << uuid;
275+ return;
276+ }
277+
278+ update_task_state(it.value());
279+ }
280+
281+ void update_task_state(TaskData& td)
282+ {
283+ state_[td.metadata.uuid()] = calculate_task_state(td);
284+
285+#if 0
286+ // FIXME: we don't need this to work correctly for the sprint because Marcus is polling in a loop
287+ // but we will need this in order for him to stop doing that
288+
289+ // TODO: compare old and new and decide if it's worth emitting a PropertyChanged signal;
290+ // eg don't contribute to dbus noise for minor speed fluctuations
291+
292+ // TODO: this function is called inside a loop when initializing the state
293+ // after start_tasks(), so also ensure we don't have a notify flood here
294+
295+ DBusUtils::notifyPropertyChanged(
296+ QDBusConnection::sessionBus(),
297+ *q_ptr,
298+ DBusTypes::KEEPER_USER_PATH,
299+ DBusTypes::KEEPER_USER_INTERFACE,
300+ QStringList(QStringLiteral("State"))
301+ );
302+#endif
303+ }
304+
305+ QVariantMap calculate_task_state(TaskData& td) const
306+ {
307+ QVariantMap ret;
308+
309+ auto const uuid = td.metadata.uuid();
310+ bool const current = uuid == current_task_;
311+
312+ ret.insert(QStringLiteral("action"), td.action);
313+
314+ ret.insert(QStringLiteral("display-name"), td.metadata.display_name());
315+
316+ // FIXME: assuming backup_helper_ for now...
317+ int32_t speed {};
318+ if (current)
319+ speed = backup_helper_->speed();
320+ ret.insert(QStringLiteral("speed"), speed);
321+
322+ if (current)
323+ td.percent_done = backup_helper_->percent_done();
324+ ret.insert(QStringLiteral("percent-done"), td.percent_done);
325+
326+ if (td.action == "failed")
327+ ret.insert(QStringLiteral("error"), td.error);
328+
329+ ret.insert(QStringLiteral("uuid"), uuid);
330+
331+ return ret;
332+ }
333+
334+
335+ void set_current_task(QString const& uuid)
336+ {
337+ auto const prev = current_task_;
338+
339+ current_task_ = uuid;
340+
341+ if (!prev.isEmpty())
342+ update_task_state(prev);
343+
344+ if (!uuid.isEmpty())
345+ update_task_state(uuid);
346+ }
347+
348+ void set_current_task_action(QString const& action)
349+ {
350+ auto& td = task_data_[current_task_];
351+ td.action = action;
352+ update_task_state(td);
353+ }
354+
355+ /***
356+ **** Misc
357+ ***/
358+
359+ bool find_task_metadata(QString const& uuid, Metadata& setme_task, TaskType& setme_type) const
360+ {
361+ for (const auto& c : get_backup_choices()) {
362+ if (c.uuid() == uuid) {
363+ setme_task = c;
364+ setme_type = TaskType::BACKUP;
365+ return true;
366+ }
367+ }
368+ for (const auto& c : get_restore_choices()) {
369+ if (c.uuid() == uuid) {
370+ setme_task = c;
371+ setme_type = TaskType::RESTORE;
372+ return true;
373+ }
374+ }
375+ return false;
376+ }
377+
378+ /***
379+ ****
380+ ***/
381+
382+ Keeper * const q_ptr;
383+ QSharedPointer<HelperRegistry> helper_registry_;
384+ QSharedPointer<MetadataProvider> backup_choices_;
385+ QSharedPointer<MetadataProvider> restore_choices_;
386+ mutable QVector<Metadata> cached_backup_choices_;
387+ mutable QVector<Metadata> cached_restore_choices_;
388+ QStringList all_tasks_;
389+ QStringList remaining_tasks_;
390+ QString current_task_;
391+ QVariantDictMap state_;
392+
393+ mutable QMap<QString,TaskData> task_data_;
394 };
395
396
397@@ -222,11 +419,7 @@
398 {
399 Q_D(Keeper);
400
401- if (!d->cached_backup_choices_.size())
402- {
403- d->cached_backup_choices_ = d->backup_choices_->get_backups();
404- }
405- return d->cached_backup_choices_;
406+ return d->get_backup_choices();
407 }
408
409 QVector<Metadata>
410@@ -234,9 +427,13 @@
411 {
412 Q_D(Keeper);
413
414- if (!d->cached_restore_choices_.size())
415- {
416- d->cached_restore_choices_ = d->restore_choices_->get_backups();
417- }
418- return d->cached_restore_choices_;
419+ return d->get_restore_choices();
420+}
421+
422+QVariantDictMap
423+Keeper::get_state() const
424+{
425+ Q_D(const Keeper);
426+
427+ return d->get_state();
428 }
429
430=== modified file 'src/service/keeper.h'
431--- src/service/keeper.h 2016-08-10 06:44:47 +0000
432+++ src/service/keeper.h 2016-08-11 00:30:32 +0000
433@@ -18,6 +18,8 @@
434
435 #pragma once
436
437+#include "qdbus-stubs/dbus-types.h"
438+
439 #include <unity/storage/qt/client/client-api.h>
440
441 #include <QDBusContext>
442@@ -56,6 +58,7 @@
443 QDBusUnixFileDescriptor StartBackup(QDBusConnection, const QDBusMessage& message, quint64 nbytes);
444
445 void start_tasks(QStringList const & keys);
446+ QVariantDictMap get_state() const;
447
448 private:
449 QScopedPointer<KeeperPrivate> const d_ptr;

Subscribers

People subscribed via source and target branches

to all changes: