[gnome-disk-utility] Create virtual GduHub objects for various virtual devices



commit 6d165318d15f45e5d3c6073a88b22262559a0aa4
Author: David Zeuthen <davidz redhat com>
Date:   Tue Jan 26 15:23:17 2010 -0500

    Create virtual GduHub objects for various virtual devices
    
    including
    
     - Multi-disk devices: RAID, LVM
     - Multipath devices

 src/gdu/gdu-drive.c                |    7 +-
 src/gdu/gdu-hub.c                  |   70 ++++++++++++++++----
 src/gdu/gdu-hub.h                  |    1 +
 src/gdu/gdu-pool.c                 |  124 +++++++++++++++++++++++++++++++++---
 src/gdu/gdu-private.h              |    4 +
 src/gdu/gdu-types.h                |   10 +++
 src/palimpsest/gdu-section-drive.c |   21 +++++--
 src/palimpsest/gdu-section-hub.c   |   34 ++++++----
 8 files changed, 223 insertions(+), 48 deletions(-)
---
diff --git a/src/gdu/gdu-drive.c b/src/gdu/gdu-drive.c
index 228fb22..74d9363 100644
--- a/src/gdu/gdu-drive.c
+++ b/src/gdu/gdu-drive.c
@@ -724,11 +724,10 @@ gdu_drive_get_name (GduPresentable *presentable)
                 } else {
                         if (is_rotational) {
                                 if (strsize != NULL) {
-                                        /* Translators: This string is used to describe a hard disk. The first %s is
-                                         * the size of the drive e.g. '45 GB'.
+                                        /* Translators: This string is used to describe a hard disk.
+                                         * The first %s is the size of the drive e.g. '45 GB'.
                                          */
-                                        g_string_append_printf (result, _("%s Hard Disk"),
-                                                                strsize);
+                                        g_string_append_printf (result, _("%s Hard Disk"), strsize);
                                 } else {
                                         /* Translators: This string is used to describe a hard disk where the size
                                          * is not known.
diff --git a/src/gdu/gdu-hub.c b/src/gdu/gdu-hub.c
index 60247df..a93b77d 100644
--- a/src/gdu/gdu-hub.c
+++ b/src/gdu/gdu-hub.c
@@ -48,11 +48,16 @@
 
 struct _GduHubPrivate
 {
+        GduHubUsage usage;
         GduAdapter *adapter;
         GduExpander *expander;
         GduPool *pool;
         GduPresentable *enclosing_presentable;
         gchar *id;
+
+        gchar *given_name;
+        gchar *given_vpd_name;
+        GIcon *given_icon;
 };
 
 static GObjectClass *parent_class = NULL;
@@ -91,6 +96,11 @@ gdu_hub_finalize (GObject *object)
 
         g_free (hub->priv->id);
 
+        g_free (hub->priv->given_name);
+        g_free (hub->priv->given_vpd_name);
+        if (hub->priv->given_icon != NULL)
+                g_object_unref (hub->priv->given_icon);
+
         if (G_OBJECT_CLASS (parent_class)->finalize != NULL)
                 (* G_OBJECT_CLASS (parent_class)->finalize) (object);
 }
@@ -129,17 +139,26 @@ expander_changed (GduExpander *expander, gpointer user_data)
         g_signal_emit_by_name (hub->priv->pool, "presentable-changed", hub);
 }
 
-/* expander may be NULL */
+/**
+ *
+ * If @usage is %GDU_HUB_USAGE_ADAPTER the @adapter must not be %NULL and @expander, @name, @vpd_name and @icon must all be %NULL.
+ * If @usage is %GDU_HUB_USAGE_EXPANDER the @adapter and @expander must not be %NULL and @name, @vpd_name and @icon must all be %NULL.
+ * Otherwise @adapter and @expander must be %NULL and @name, @vpd_name and @icon must not not %NULL.
+ */
 GduHub *
 _gdu_hub_new (GduPool        *pool,
+              GduHubUsage     usage,
               GduAdapter     *adapter,
               GduExpander    *expander,
+              const gchar    *name,
+              const gchar    *vpd_name,
+              GIcon          *icon,
               GduPresentable *enclosing_presentable)
 {
         GduHub *hub;
 
         hub = GDU_HUB (g_object_new (GDU_TYPE_HUB, NULL));
-        hub->priv->adapter = g_object_ref (adapter);
+        hub->priv->adapter = adapter != NULL ? g_object_ref (adapter) : NULL;
         hub->priv->expander = expander != NULL ? g_object_ref (expander) : NULL;
         hub->priv->pool = g_object_ref (pool);
         hub->priv->enclosing_presentable =
@@ -148,14 +167,25 @@ _gdu_hub_new (GduPool        *pool,
                 hub->priv->id = g_strdup_printf ("%s__enclosed_by_%s",
                                                  gdu_expander_get_native_path (hub->priv->expander),
                                                  enclosing_presentable != NULL ? gdu_presentable_get_id (enclosing_presentable) : "(none)");
-        } else {
+        } else if (adapter != NULL) {
                 hub->priv->id = g_strdup_printf ("%s__enclosed_by_%s",
                                                  gdu_adapter_get_native_path (hub->priv->adapter),
                                                  enclosing_presentable != NULL ? gdu_presentable_get_id (enclosing_presentable) : "(none)");
+        } else {
+                hub->priv->id = g_strdup_printf ("%s__enclosed_by_%s",
+                                                 name,
+                                                 enclosing_presentable != NULL ? gdu_presentable_get_id (enclosing_presentable) : "(none)");
         }
-        g_signal_connect (adapter, "changed", (GCallback) adapter_changed, hub);
+        if (adapter != NULL)
+                g_signal_connect (adapter, "changed", (GCallback) adapter_changed, hub);
         if (expander != NULL)
                 g_signal_connect (expander, "changed", (GCallback) expander_changed, hub);
+
+        hub->priv->usage = usage;
+        hub->priv->given_name = g_strdup (name);
+        hub->priv->given_vpd_name = g_strdup (vpd_name);
+        hub->priv->given_icon = icon != NULL ? g_object_ref (icon) : NULL;
+
         return hub;
 }
 
@@ -187,8 +217,11 @@ gdu_hub_get_name (GduPresentable *presentable)
         GduHub *hub = GDU_HUB (presentable);
         gchar *ret;
 
-        /* TODO: include type e.g. SATA Port Multiplier, SAS Expander etc */
-        if (hub->priv->expander == NULL) {
+        if (hub->priv->expander != NULL) {
+                /* TODO: include type e.g. SATA Port Multiplier, SAS Expander etc */
+                ret = g_strdup (_("SAS Expander"));
+
+        } else if (hub->priv->adapter != NULL) {
                 const gchar *fabric;
 
                 fabric = gdu_adapter_get_fabric (hub->priv->adapter);
@@ -208,7 +241,7 @@ gdu_hub_get_name (GduPresentable *presentable)
                 }
 
         } else {
-                ret = g_strdup (_("SAS Expander"));
+                ret = g_strdup (hub->priv->given_name);
         }
 
         return ret;
@@ -222,15 +255,17 @@ gdu_hub_get_vpd_name (GduPresentable *presentable)
         const gchar *vendor;
         const gchar *model;
 
-        if (hub->priv->expander == NULL) {
+        if (hub->priv->expander != NULL) {
+                vendor = gdu_expander_get_vendor (hub->priv->expander);
+                model = gdu_expander_get_model (hub->priv->expander);
+                s = g_strdup_printf ("%s %s", vendor, model);
+        } else if (hub->priv->adapter != NULL) {
                 vendor = gdu_adapter_get_vendor (hub->priv->adapter);
                 model = gdu_adapter_get_model (hub->priv->adapter);
                 //s = g_strdup_printf ("%s %s", vendor, model);
                 s = g_strdup (model);
         } else {
-                vendor = gdu_expander_get_vendor (hub->priv->expander);
-                model = gdu_expander_get_model (hub->priv->expander);
-                s = g_strdup_printf ("%s %s", vendor, model);
+                s = g_strdup (hub->priv->given_vpd_name);
         }
 
         return s;
@@ -247,7 +282,14 @@ static GIcon *
 gdu_hub_get_icon (GduPresentable *presentable)
 {
         GIcon *icon;
-        icon = g_themed_icon_new_with_default_fallbacks ("gdu-hba"); /* TODO */
+        GduHub *hub = GDU_HUB (presentable);
+
+        if (hub->priv->given_icon != NULL) {
+                icon = g_object_ref (hub->priv->given_icon);
+        } else {
+                icon = g_themed_icon_new_with_default_fallbacks ("gdu-hba"); /* TODO */
+        }
+
         return icon;
 }
 
@@ -267,7 +309,7 @@ static GduPool *
 gdu_hub_get_pool (GduPresentable *presentable)
 {
         GduHub *hub = GDU_HUB (presentable);
-        return gdu_adapter_get_pool (hub->priv->adapter);
+        return g_object_ref (hub->priv->pool);
 }
 
 static gboolean
@@ -285,7 +327,7 @@ gdu_hub_is_recognized (GduPresentable *presentable)
 GduAdapter *
 gdu_hub_get_adapter (GduHub *hub)
 {
-        return g_object_ref (hub->priv->adapter);
+        return hub->priv->adapter != NULL ? g_object_ref (hub->priv->adapter) : NULL;
 }
 
 GduExpander *
diff --git a/src/gdu/gdu-hub.h b/src/gdu/gdu-hub.h
index 180e4cb..60905db 100644
--- a/src/gdu/gdu-hub.h
+++ b/src/gdu/gdu-hub.h
@@ -56,6 +56,7 @@ struct _GduHubClass
 GType        gdu_hub_get_type     (void);
 GduAdapter  *gdu_hub_get_adapter  (GduHub *hub);
 GduExpander *gdu_hub_get_expander (GduHub *hub);
+GduHubUsage  gdu_hub_get_usage    (GduHub *hub);
 
 G_END_DECLS
 
diff --git a/src/gdu/gdu-pool.c b/src/gdu/gdu-pool.c
index 1e516b3..c9c2b92 100644
--- a/src/gdu/gdu-pool.c
+++ b/src/gdu/gdu-pool.c
@@ -841,6 +841,73 @@ get_holes_for_drive (GduPool   *pool,
         return ret;
 }
 
+static GduPresentable *
+ensure_hub (GduPool *pool,
+            GduPresentable **hub,
+            GList **presentables,
+            const gchar *name,
+            const gchar *vpd_name,
+            const gchar *icon_name)
+{
+        GIcon *icon;
+        GduPresentable *ret;
+
+        g_assert (hub != NULL);
+        g_assert (presentables != NULL);
+
+        if (*hub != NULL)
+                goto out;
+
+        icon = g_themed_icon_new_with_default_fallbacks (icon_name);
+        ret = GDU_PRESENTABLE (_gdu_hub_new (pool,
+                                             GDU_HUB_USAGE_MULTI_DISK_DEVICES,
+                                             NULL,                    /* adapter */
+                                             NULL,                    /* expander */
+                                             name,
+                                             vpd_name,
+                                             icon,
+                                             pool->priv->machine));
+        g_object_unref (icon);
+
+        *presentables = g_list_prepend (*presentables, ret);
+
+        *hub = ret;
+ out:
+        return *hub;
+}
+
+static GduPresentable *
+ensure_hub_multipath (GduPool *pool,
+                      GduPresentable **hub,
+                      GList **presentables)
+{
+        return ensure_hub (pool, hub, presentables,
+                           _("Multipath Devices"),
+                           _("Drives with multiple I/O paths"),
+                           "gdu-hba");
+}
+
+static GduPresentable *
+ensure_hub_raid_lvm (GduPool *pool,
+                     GduPresentable **hub,
+                     GList **presentables)
+{
+        return ensure_hub (pool, hub, presentables,
+                           _("Multi-disk Devices"),
+                           _("RAID, LVM and other logical drives"),
+                           "gdu-hba");
+}
+
+static GduPresentable *
+ensure_hub_peripheral (GduPool *pool,
+                       GduPresentable **hub,
+                       GList **presentables)
+{
+        return ensure_hub (pool, hub, presentables,
+                           _("Peripheral Devices"),
+                           _("USB, Firewire and other peripherals"),
+                           "gdu-hba");
+}
 
 static void
 recompute_presentables (GduPool *pool)
@@ -858,6 +925,9 @@ recompute_presentables (GduPool *pool)
         GHashTable *hash_map_from_linux_lvm2_group_uuid_to_vg;
         GHashTable *hash_map_from_adapter_objpath_to_hub;
         GHashTable *hash_map_from_expander_objpath_to_hub;
+        GduPresentable *hub_raid_lvm;
+        GduPresentable *hub_multipath;
+        GduPresentable *hub_peripheral;
 
         /* The general strategy for (re-)computing presentables is rather brute force; we
          * compute the complete set of presentables every time and diff it against the
@@ -899,6 +969,10 @@ recompute_presentables (GduPool *pool)
                                                                        NULL,
                                                                        NULL);
 
+        hub_raid_lvm = NULL;
+        hub_multipath = NULL;
+        hub_peripheral = NULL;
+
         /* First add all HBAs as Hub objects */
         adapters = gdu_pool_get_adapters (pool);
         for (l = adapters; l != NULL; l = l->next) {
@@ -906,8 +980,12 @@ recompute_presentables (GduPool *pool)
                 GduHub *hub;
 
                 hub = _gdu_hub_new (pool,
+                                    GDU_HUB_USAGE_ADAPTER,
                                     adapter,
                                     NULL,      /* expander */
+                                    NULL,      /* name */
+                                    NULL,      /* vpd_name */
+                                    NULL,      /* icon */
                                     pool->priv->machine);  /* enclosing_presentable */
 
                 g_hash_table_insert (hash_map_from_adapter_objpath_to_hub,
@@ -952,7 +1030,14 @@ recompute_presentables (GduPool *pool)
                 g_warn_if_fail (expander_parent != NULL);
                 g_warn_if_fail (adapter != NULL);
 
-                hub = _gdu_hub_new (pool, adapter, expander, expander_parent);
+                hub = _gdu_hub_new (pool,
+                                    GDU_HUB_USAGE_EXPANDER,
+                                    adapter,
+                                    expander,
+                                    NULL,      /* name */
+                                    NULL,      /* vpd_name */
+                                    NULL,      /* icon */
+                                    expander_parent);
                 g_object_unref (adapter);
 
                 g_hash_table_insert (hash_map_from_expander_objpath_to_hub,
@@ -994,7 +1079,9 @@ recompute_presentables (GduPool *pool)
                                         uuid = NULL;
 
                                 /* TODO: Create transient GduHub object for all RAID arrays? */
-                                linux_md_parent = pool->priv->machine;
+                                linux_md_parent = ensure_hub_raid_lvm (pool,
+                                                                       &hub_raid_lvm,
+                                                                       &new_presentables);
 
                                 if (uuid != NULL) {
                                         drive = GDU_DRIVE (_gdu_linux_md_drive_new (pool, uuid, NULL, linux_md_parent));
@@ -1046,12 +1133,24 @@ recompute_presentables (GduPool *pool)
                                         }
                                 }
 
+                                /* Group all Multipath devices in the virtual "Multi-path Devices" Hub */
+                                if (gdu_device_is_linux_dmmp (device)) {
+                                        g_warn_if_fail (drive_parent == NULL);
+                                        drive_parent = ensure_hub_multipath (pool,
+                                                                             &hub_multipath,
+                                                                             &new_presentables);
+                                }
+
+                                /* If there's no parent it could be because the device is connected via
+                                 * USB, Firewire or SDIO and udisks doesn't generate Adapter or Expander
+                                 * objects for it.
+                                 *
+                                 * We group these devices in the virtual "Peripheral Devices" Hub
+                                 */
                                 if (drive_parent == NULL) {
-                                        /* TODO: Create transient GduHub object for
-                                         *
-                                         *   - USB/Firewire/SDIO connected drives
-                                         */
-                                        drive_parent = pool->priv->machine;
+                                        drive_parent = ensure_hub_peripheral (pool,
+                                                                              &hub_peripheral,
+                                                                              &new_presentables);
                                 }
 
                                 drive = _gdu_drive_new_from_device (pool, device, drive_parent);
@@ -1168,7 +1267,11 @@ recompute_presentables (GduPool *pool)
                                 guint64 unallocated_size;
 
                                 /* otherwise create one */
-                                vg = _gdu_linux_lvm2_volume_group_new (pool, vg_uuid, pool->priv->machine);
+                                vg = _gdu_linux_lvm2_volume_group_new (pool,
+                                                                       vg_uuid,
+                                                                       ensure_hub_raid_lvm (pool,
+                                                                                            &hub_raid_lvm,
+                                                                                            &new_presentables));
                                 g_hash_table_insert (hash_map_from_linux_lvm2_group_uuid_to_vg, (gpointer) vg_uuid, vg);
                                 new_presentables = g_list_prepend (new_presentables, vg);
 
@@ -1239,8 +1342,9 @@ recompute_presentables (GduPool *pool)
                                 GduDrive *drive;
                                 GduPresentable *linux_md_parent;
 
-                                /* TODO: Create transient GduHub object for all RAID arrays? */
-                                linux_md_parent = pool->priv->machine;
+                                linux_md_parent = ensure_hub_raid_lvm (pool,
+                                                                       &hub_raid_lvm,
+                                                                       &new_presentables);
 
                                 drive = GDU_DRIVE (_gdu_linux_md_drive_new (pool, uuid, NULL, linux_md_parent));
                                 new_presentables = g_list_prepend (new_presentables, drive);
diff --git a/src/gdu/gdu-private.h b/src/gdu/gdu-private.h
index 594d1a8..0ace4d6 100644
--- a/src/gdu/gdu-private.h
+++ b/src/gdu/gdu-private.h
@@ -114,8 +114,12 @@ GduExpander *_gdu_expander_new_from_object_path (GduPool *pool, const char *obje
 gboolean    _gdu_expander_changed               (GduExpander   *expander);
 
 GduHub     *_gdu_hub_new                        (GduPool        *pool,
+                                                 GduHubUsage     usage,
                                                  GduAdapter     *adapter,
                                                  GduExpander    *expander,
+                                                 const gchar    *name,
+                                                 const gchar    *vpd_name,
+                                                 GIcon          *icon,
                                                  GduPresentable *enclosing_presentable);
 
 GduPort    *_gdu_port_new_from_object_path (GduPool *pool, const char *object_path);
diff --git a/src/gdu/gdu-types.h b/src/gdu/gdu-types.h
index 7a768f4..e4488e5 100644
--- a/src/gdu/gdu-types.h
+++ b/src/gdu/gdu-types.h
@@ -31,6 +31,16 @@
 
 G_BEGIN_DECLS
 
+/* TODO: should have enum type files etc */
+
+typedef enum {
+        GDU_HUB_USAGE_ADAPTER,
+        GDU_HUB_USAGE_EXPANDER,
+        GDU_HUB_USAGE_MULTI_DISK_DEVICES,
+        GDU_HUB_USAGE_MULTI_PATH_DEVICES,
+} GduHubUsage;
+
+
 /* forward type definitions */
 
 typedef struct _GduPool                   GduPool;
diff --git a/src/palimpsest/gdu-section-drive.c b/src/palimpsest/gdu-section-drive.c
index 2630648..af7033e 100644
--- a/src/palimpsest/gdu-section-drive.c
+++ b/src/palimpsest/gdu-section-drive.c
@@ -35,6 +35,8 @@ struct _GduSectionDrivePrivate
 {
         GtkWidget *multipath_warning_info_bar;
 
+        GtkWidget *drive_label;
+
         GduDetailsElement *model_element;
         GduDetailsElement *firmware_element;
         GduDetailsElement *serial_element;
@@ -136,6 +138,14 @@ gdu_section_drive_update (GduSection *_section)
         if (d == NULL)
                 goto out;
 
+        if (gdu_device_is_linux_dmmp (d)) {
+                s = g_strconcat ("<b>", _("Multipath Drive"), "</b>", NULL);
+        } else {
+                s = g_strconcat ("<b>", _("Drive"), "</b>", NULL);
+        }
+        gtk_label_set_markup (GTK_LABEL (section->priv->drive_label), s);
+        g_free (s);
+
         /* TODO: handle multiple ports */
         port_object_paths = gdu_device_drive_get_ports (d);
         if (port_object_paths != NULL && port_object_paths[0] != NULL) {
@@ -209,7 +219,11 @@ gdu_section_drive_update (GduSection *_section)
                              vendor != NULL ? vendor : "",
                              vendor != NULL ? " " : "",
                              model != NULL ? model : "");
-        gdu_details_element_set_text (section->priv->model_element, s);
+        if (strlen (s) == 0) {
+                gdu_details_element_set_text (section->priv->model_element, "â??");
+        } else {
+                gdu_details_element_set_text (section->priv->model_element, s);
+        }
         g_free (s);
 
         firmware = gdu_device_drive_get_revision (d);
@@ -722,7 +736,6 @@ gdu_section_drive_constructed (GObject *object)
         GtkWidget *vbox;
         GtkWidget *hbox;
         GtkWidget *image;
-        gchar *s;
         GduPresentable *p;
         GduDevice *d;
         GPtrArray *elements;
@@ -762,10 +775,8 @@ gdu_section_drive_constructed (GObject *object)
 
         label = gtk_label_new (NULL);
         gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
-        s = g_strconcat ("<b>", _("Drive"), "</b>", NULL);
-        gtk_label_set_markup (GTK_LABEL (label), s);
-        g_free (s);
         gtk_box_pack_start (GTK_BOX (section), label, FALSE, FALSE, 0);
+        section->priv->drive_label = label;
 
         align = gtk_alignment_new (0.5, 0.5, 1.0, 1.0);
         gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, 12, 0);
diff --git a/src/palimpsest/gdu-section-hub.c b/src/palimpsest/gdu-section-hub.c
index 2709284..9eb0150 100644
--- a/src/palimpsest/gdu-section-hub.c
+++ b/src/palimpsest/gdu-section-hub.c
@@ -85,24 +85,13 @@ gdu_section_hub_update (GduSection *_section)
         a = gdu_hub_get_adapter (GDU_HUB (p));
         e = gdu_hub_get_expander (GDU_HUB (p));
 
-        pool = gdu_adapter_get_pool (a);
-        if (pool == NULL)
-                goto out;
+        pool = gdu_presentable_get_pool (p);
 
-        if (e == NULL) {
-
-                vendor = gdu_adapter_get_vendor (a);
-                model = gdu_adapter_get_model (a);
-                driver = gdu_adapter_get_driver (a);
-                fabric = gdu_adapter_get_fabric (a);
-                num_ports = gdu_adapter_get_num_ports (a);
-
-                revision = "â??";
-        } else {
+        fabric = "";
+        if (e != NULL) {
                 vendor = gdu_expander_get_vendor (e);
                 model = gdu_expander_get_model (e);
                 revision = gdu_expander_get_revision (e);
-                fabric = NULL;
                 if (a != NULL)
                         fabric = gdu_adapter_get_fabric (a);
                 num_ports = gdu_expander_get_num_ports (e);
@@ -126,6 +115,22 @@ gdu_section_hub_update (GduSection *_section)
                         revision = "â??";
 
                 driver = "â??";
+        } else if (a != NULL) {
+
+                vendor = gdu_adapter_get_vendor (a);
+                model = gdu_adapter_get_model (a);
+                driver = gdu_adapter_get_driver (a);
+                fabric = gdu_adapter_get_fabric (a);
+                num_ports = gdu_adapter_get_num_ports (a);
+
+                revision = "â??";
+        } else {
+                vendor = "â??";
+                model = "â??";
+                driver = "â??";
+                fabric = "â??";
+                revision = "â??";
+                num_ports = 0;
         }
 
         if (g_str_has_prefix (fabric, "ata_pata")) {
@@ -168,7 +173,6 @@ gdu_section_hub_update (GduSection *_section)
         gdu_details_element_set_text (section->priv->fabric_element, fabric_str);
         gdu_details_element_set_text (section->priv->num_ports_element, num_ports_str);
 
- out:
         g_free (num_ports_str);
         if (pool != NULL)
                 g_object_unref (pool);



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