diff --git a/sql/meson.build b/sql/meson.build index 126f2982..9a629380 100644 --- a/sql/meson.build +++ b/sql/meson.build @@ -24,6 +24,7 @@ sql_files = [ 'version-023.sql', 'version-024.sql', 'version-025.sql', + 'version-026.sql', ] install_data(sql_files, diff --git a/sql/version-026.sql b/sql/version-026.sql new file mode 100644 index 00000000..55ab4fb0 --- /dev/null +++ b/sql/version-026.sql @@ -0,0 +1,4 @@ +-- +-- Track when account storage was last cleaned. +-- +ALTER TABLE GarbageCollectionTable ADD COLUMN last_cleanup_time_t INTEGER DEFAULT NULL; diff --git a/src/engine/api/geary-account.vala b/src/engine/api/geary-account.vala index 628a14ec..432fa364 100644 --- a/src/engine/api/geary-account.vala +++ b/src/engine/api/geary-account.vala @@ -155,7 +155,14 @@ public abstract class Geary.Account : BaseObject, Logging.Source { * (in ImapDB.GC) has past, a GC reap is performed * 3. GC vacuum is run if recommended */ - public DateTime? last_storage_cleanup { get; set; default = null; } + public GLib.DateTime? last_storage_cleanup { + get { return this._last_storage_cleanup; } + set { + this._last_storage_cleanup = value; + this.last_storage_cleanup_changed(value); + } + } + private GLib.DateTime? _last_storage_cleanup = null; public signal void opened(); @@ -272,6 +279,11 @@ public abstract class Geary.Account : BaseObject, Logging.Source { public signal void email_flags_changed(Geary.Folder folder, Gee.Map map); + /** + * Fired when last_storage_cleanup changes. + */ + public signal void last_storage_cleanup_changed(GLib.DateTime? new_value); + /** {@inheritDoc} */ public Logging.Flag logging_flags { get; protected set; default = Logging.Flag.ALL; diff --git a/src/engine/imap-db/imap-db-account.vala b/src/engine/imap-db/imap-db-account.vala index 2439df06..602b4c2d 100644 --- a/src/engine/imap-db/imap-db-account.vala +++ b/src/engine/imap-db/imap-db-account.vala @@ -382,6 +382,57 @@ private class Geary.ImapDB.Account : BaseObject { return create_local_folder(path, folder_id, properties); } + /** + * Fetch the last time the account cleanup was run. + */ + public async GLib.DateTime? fetch_last_cleanup_async(Cancellable? cancellable) + throws Error { + check_open(); + + int64 last_cleanup_time_t = -1; + yield db.exec_transaction_async(Db.TransactionType.RO, (cx) => { + Db.Result result = cx.query(""" + SELECT last_cleanup_time_t + FROM GarbageCollectionTable + WHERE id = 0 + """); + + if (result.finished) + return Db.TransactionOutcome.FAILURE; + + last_cleanup_time_t = !result.is_null_at(0) ? result.int64_at(0) : -1; + + return Db.TransactionOutcome.SUCCESS; + }, cancellable); + + return (last_cleanup_time_t >= 0) ? new DateTime.from_unix_local(last_cleanup_time_t) : null; + } + + /** + * Set the last time the account cleanup was run. + */ + public async void set_last_cleanup_async(GLib.DateTime? dt, Cancellable? cancellable) + throws Error { + check_open(); + + yield db.exec_transaction_async(Db.TransactionType.WO, (cx) => { + Db.Statement stmt = cx.prepare(""" + UPDATE GarbageCollectionTable + SET last_cleanup_time_t = ? + WHERE id = 0 + """); + if (dt != null) { + stmt.bind_int64(0, dt.to_unix()); + } else { + stmt.bind_null(0); + } + + stmt.exec(cancellable); + + return Db.TransactionOutcome.COMMIT; + }, cancellable); + } + private Geary.ImapDB.Folder? get_local_folder(Geary.FolderPath path) { FolderReference? folder_ref = folder_refs.get(path); if (folder_ref == null) diff --git a/src/engine/imap-engine/imap-engine-generic-account.vala b/src/engine/imap-engine/imap-engine-generic-account.vala index 75adcb10..89881c9b 100644 --- a/src/engine/imap-engine/imap-engine-generic-account.vala +++ b/src/engine/imap-engine/imap-engine-generic-account.vala @@ -140,6 +140,11 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.Account { throw err; } + this.last_storage_cleanup = yield this.local.fetch_last_cleanup_async(cancellable); + this.last_storage_cleanup_changed.connect ((dt) => { + this.local.set_last_cleanup_async.begin(dt, cancellable); + }); + this.open = true; notify_opened();