[gnome-boxes] os-database: Load database asynchronously



commit eafcdfdded36a8e88eebfaf02fcc310babbd9ba4
Author: Zeeshan Ali (Khattak) <zeeshanak gnome org>
Date:   Thu Nov 1 18:29:47 2012 +0200

    os-database: Load database asynchronously
    
    Load database in a separate thread so the rest of the Application
    (especially the UI) can load faster.
    
    In my limited testing, I saw a visible difference in load time.
    Christophe did a more systematic analysis and found out it takes about
    300ms with a hot cache on his machine to load the DB.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=687357

 src/installer-media.vala |    6 +++---
 src/media-manager.vala   |    4 ++--
 src/os-database.vala     |   37 +++++++++++++++++++++++++++++++------
 3 files changed, 36 insertions(+), 11 deletions(-)
---
diff --git a/src/installer-media.vala b/src/installer-media.vala
index 9973753..fde8cc0 100644
--- a/src/installer-media.vala
+++ b/src/installer-media.vala
@@ -55,7 +55,7 @@ private class Boxes.InstallerMedia : GLib.Object {
         var device = yield get_device_from_path (path, media_manager.client, cancellable);
 
         if (device != null)
-            get_media_info_from_device (device, media_manager.os_db);
+            yield get_media_info_from_device (device, media_manager.os_db);
         else {
             from_image = true;
             os = yield media_manager.os_db.guess_os_from_install_media (device_file, out os_media, cancellable);
@@ -133,7 +133,7 @@ private class Boxes.InstallerMedia : GLib.Object {
         return client.query_by_device_file (device_file);
     }
 
-    private void get_media_info_from_device (GUdev.Device device, OSDatabase os_db) throws OSDatabaseError {
+    private async void get_media_info_from_device (GUdev.Device device, OSDatabase os_db) throws OSDatabaseError {
         if (!device.get_property_as_boolean ("OSINFO_BOOTABLE"))
             throw new OSDatabaseError.NON_BOOTABLE ("Media %s is not bootable.", device_file);
 
@@ -142,7 +142,7 @@ private class Boxes.InstallerMedia : GLib.Object {
         var os_id = device.get_property ("OSINFO_INSTALLER") ?? device.get_property ("OSINFO_LIVE");
 
         if (os_id != null) {
-            os = os_db.get_os_by_id (os_id);
+            os = yield os_db.get_os_by_id (os_id);
 
             var media_id = device.get_property ("OSINFO_MEDIA");
             if (media_id != null)
diff --git a/src/media-manager.vala b/src/media-manager.vala
index 08c56ba..601ed4c 100644
--- a/src/media-manager.vala
+++ b/src/media-manager.vala
@@ -16,7 +16,7 @@ private class Boxes.MediaManager : Object {
     public MediaManager () {
         client = new GUdev.Client ({"block"});
         os_db = new OSDatabase ();
-        os_db.load ();
+        os_db.load.begin ();
         try {
             connection = Sparql.Connection.get ();
         } catch (GLib.Error error) {
@@ -94,7 +94,7 @@ private class Boxes.MediaManager : Object {
         if (label == null || os_id == null || media_id == null)
             return yield create_installer_media_for_path (path, null);
 
-        var os = os_db.get_os_by_id (os_id);
+        var os = yield os_db.get_os_by_id (os_id);
         var os_media = os_db.get_media_by_id (os, media_id);
         var resources = os_db.get_resources_for_os (os, os_media.architecture);
         var media = new InstallerMedia.from_iso_info (path, label, os, os_media, resources);
diff --git a/src/os-database.vala b/src/os-database.vala
index 54d1fad..18a9f97 100644
--- a/src/os-database.vala
+++ b/src/os-database.vala
@@ -18,6 +18,10 @@ private class Boxes.OSDatabase : GLib.Object {
 
     private Db? db;
 
+    private bool db_loading;
+
+    private signal void db_loaded ();
+
     private static Resources get_default_resources () {
         var resources = new Resources ("whatever", "x86_64");
 
@@ -28,19 +32,22 @@ private class Boxes.OSDatabase : GLib.Object {
         return resources;
     }
 
-    public void load () {
+    public async void load () {
+        db_loading = true;
         var loader = new Loader ();
         try {
-            loader.process_default_path ();
+            yield run_in_thread (() => { loader.process_default_path (); });
         } catch (GLib.Error e) {
             warning ("Error loading default libosinfo database: %s", e.message);
         }
         try {
-            loader.process_path (get_logos_db ()); // Load our custom database
+            yield run_in_thread (() => { loader.process_path (get_logos_db ()); }); // Load our custom database
         } catch (GLib.Error e) {
             warning ("Error loading GNOME Boxes libosinfo database: %s", e.message);
         }
         db = loader.get_db ();
+        db_loading = false;
+        db_loaded ();
     }
 
     public async Os? guess_os_from_install_media (string media_path,
@@ -48,7 +55,7 @@ private class Boxes.OSDatabase : GLib.Object {
                                                   Cancellable? cancellable) throws GLib.Error {
         os_media = null;
 
-        if (db == null)
+        if (!yield ensure_db_loaded ())
             return null;
 
         var media = yield Media.create_from_location_async (media_path, Priority.DEFAULT, cancellable);
@@ -56,8 +63,8 @@ private class Boxes.OSDatabase : GLib.Object {
         return db.guess_os_from_media (media, out os_media);
     }
 
-    public Os get_os_by_id (string id) throws OSDatabaseError {
-        if (db == null)
+    public async Os get_os_by_id (string id) throws OSDatabaseError {
+        if (!yield ensure_db_loaded ())
             throw new OSDatabaseError.UNKNOWN_OS_ID ("Unknown OS ID '%s'", id);
 
         var os = db.get_os (id);
@@ -142,4 +149,22 @@ private class Boxes.OSDatabase : GLib.Object {
             // (minimum/recommended) of each architecture for each OS.
             return filtered.get_nth (0) as Resources;
     }
+
+    private async bool ensure_db_loaded () {
+        if (db != null)
+            return true;
+
+        if (db_loading) { // Wait for the DB to load..
+            ulong db_loaded_id = 0;
+
+            db_loaded_id = db_loaded.connect (() => {
+                ensure_db_loaded.callback ();
+                disconnect (db_loaded_id);
+            });
+
+            yield;
+        }
+
+        return (db != null);
+    }
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]