socol 发表于 2013-1-26 13:34:42

GVFS monitor device change by gdu module

Summary:
  The device monitor flow looks like:
kernel                                                                                                                                                                ->
udev                       (use cdrom_id/usb_id/... to read HW)                                                                          ->
udisks                    (monitor device change and collect/map device property to dbus)                       ->
gnome-disk-utility(connect udisks dbus and map as libgdu)                                                                  ->
gvfs                         (monitor gdu_pool or mtab/fstab file to generate signal)                                         ->
GVolumeMonitor signal

  gvfs-gdu-volume-monitor can monitor drive/volume/mount change, it depend on libgdu which belong gnome-disk-utility rpm. The libgdu get disks property from dbus of "org.freedesktop.UDisks"(udisks rpm).
1. gdu-volume-monitor-daemon create gduvolumemonitor(real monitor device's status) instance
2. request dbus connection
3. connect gduvolumemonitor signal(drive-changed/volume-added...) dispatch to dbus signal
 
./monitor/gdu/gdu-volume-monitor-daemon.c:main(){return g_vfs_proxy_volume_monitor_daemon_main (argc,                                                 argv,                                                 "org.gtk.Private.GduVolumeMonitor",                                                 G_TYPE_GDU_VOLUME_MONITOR);}./monitor/proxy/gvfsproxyvolumemonitordaemon.c:g_vfs_proxy_volume_monitor_daemon_main (int argc,                                        char *argv[],                                        const char *dbus_name,                                        GType volume_monitor_type){monitor = G_VOLUME_MONITOR (g_object_new (volume_monitor_type, NULL));dbus_bus_request_name (connection,                         dbus_name,                         DBUS_NAME_FLAG_ALLOW_REPLACEMENT |                         DBUS_NAME_FLAG_DO_NOT_QUEUE |                         DBUS_NAME_FLAG_REPLACE_EXISTING,                         &dbus_error);g_signal_connect (monitor, "drive-changed", (GCallback) drive_changed, connection);g_signal_connect (monitor, "drive-connected", (GCallback) drive_connected, connection);g_signal_connect (monitor, "drive-disconnected", (GCallback) drive_disconnected, connection);g_signal_connect (monitor, "drive-eject-button", (GCallback) drive_eject_button, connection);g_signal_connect (monitor, "drive-stop-button", (GCallback) drive_stop_button, connection);g_signal_connect (monitor, "volume-changed", (GCallback) volume_changed, connection);g_signal_connect (monitor, "volume-added", (GCallback) volume_added, connection);g_signal_connect (monitor, "volume-removed", (GCallback) volume_removed, connection);g_signal_connect (monitor, "mount-changed", (GCallback) mount_changed, connection);g_signal_connect (monitor, "mount-added", (GCallback) mount_added, connection);g_signal_connect (monitor, "mount-pre-unmount", (GCallback) mount_pre_unmount, connection);g_signal_connect (monitor, "mount-removed", (GCallback) mount_removed, connection);}static voiddrive_disconnected (GVolumeMonitor *monitor, GDrive *drive, DBusConnection *connection){emit_signal (connection, "DriveDisconnected", drive, (AppendFunc) append_drive);} 
Trace gduvolumemonitor:
1. construct:
   a. init g_unix_mount_monitor instance to monitor mount change
   b. init gdu_pool instance to monitor device change
   c. connect "mounts_changed/presentable_added..." signal for invoke update_all()
2. update_all(drive for example, it's same as volume/mount):
   a. call update_drives() get the current drive list(previous store in monitor->drives)
   b. diff current list(monitor->drives) with the new list(real-time store in monitor->pool and ignor fstab)
   c. if diff list not null, list_emit change signal("drive_connected/drive_disconnected") to outside
   d. gdu-volume-monitor-daemon will catch the signal and send to dbus
g_gdu_volume_monitor_constructor (){monitor = G_GDU_VOLUME_MONITOR (object);monitor->mount_monitor = g_unix_mount_monitor_new ();g_signal_connect (monitor->mount_monitor,                  "mounts_changed",                  G_CALLBACK (mounts_changed),                  monitor);g_signal_connect (monitor->mount_monitor,                  "mountpoints_changed",                  G_CALLBACK (mountpoints_changed),                  monitor);monitor->pool = gdu_pool_new ();g_signal_connect (monitor->pool,                  "presentable_added",                  G_CALLBACK (presentable_added),                  monitor);g_signal_connect (monitor->pool,                  "presentable_removed",                  G_CALLBACK (presentable_removed),                  monitor);g_signal_connect (monitor->pool,                  "presentable_changed",                  G_CALLBACK (presentable_changed),                  monitor);g_signal_connect (monitor->pool,                  "presentable_job_changed",                  G_CALLBACK (presentable_job_changed),                  monitor);update_all (monitor, TRUE);}update_all (GGduVolumeMonitor *monitor,            gboolean emit_changes){GList *added_drives, *removed_drives;GList *added_volumes, *removed_volumes;GList *added_mounts, *removed_mounts;added_drives = NULL;removed_drives = NULL;added_volumes = NULL;removed_volumes = NULL;added_mounts = NULL;removed_mounts = NULL;update_drives (monitor, &added_drives, &removed_drives);update_volumes (monitor, &added_volumes, &removed_volumes);update_fstab_volumes (monitor, &added_volumes, &removed_volumes);update_mounts (monitor, &added_mounts, &removed_mounts);update_discs (monitor,                &added_volumes, &removed_volumes,                &added_mounts, &removed_mounts);if (emit_changes)    {      list_emit (monitor,               "drive_disconnected", NULL,               removed_drives);      list_emit (monitor,               "drive_connected", NULL,               added_drives);      list_emit (monitor,               "volume_removed", "removed",                added_volumes);      list_emit (monitor,               "mount_removed", "unmounted",               removed_mounts);      list_emit (monitor,               "mount_added", NULL,               added_mounts);    }}static voidupdate_drives (GGduVolumeMonitor *monitor,               GList **added_drives,               GList **removed_drives){cur_drives = NULL;for (l = monitor->drives; l != NULL; l = l->next)    cur_drives = g_list_prepend (cur_drives, g_gdu_drive_get_presentable (G_GDU_DRIVE (l->data)));new_drives = gdu_pool_get_presentables (monitor->pool);for (l = new_drives; l != NULL; l = ll)    {      GduPresentable *p = GDU_PRESENTABLE (l->data);      ll = l->next;      if (!GDU_IS_DRIVE (p) || should_drive_be_ignored (monitor->pool, GDU_DRIVE (p), fstab_mount_points))      {          g_object_unref (p);          new_drives = g_list_delete_link (new_drives, l);      }    }diff_sorted_lists (cur_drives,                     new_drives, (GCompareFunc) gdu_presentable_compare,                     &added, &removed);for (l = removed; l != NULL; l = l->next)    {      GduPresentable *p = GDU_PRESENTABLE (l->data);      drive = find_drive_by_presentable (monitor, p);      if (drive != NULL)      {          /*g_debug ("removing drive %s", gdu_presentable_get_id (p));*/          g_gdu_drive_disconnected (drive);          monitor->drives = g_list_remove (monitor->drives, drive);          *removed_drives = g_list_prepend (*removed_drives, drive);      }    }for (l = added; l != NULL; l = l->next)    {      GduPresentable *p = GDU_PRESENTABLE (l->data);      drive = find_drive_by_presentable (monitor, p);      if (drive == NULL)      {          /*g_debug ("adding drive %s", gdu_presentable_get_id (p));*/          drive = g_gdu_drive_new (G_VOLUME_MONITOR (monitor), p);          if (drive != NULL)            {            monitor->drives = g_list_prepend (monitor->drives, drive);            *added_drives = g_list_prepend (*added_drives, g_object_ref (drive));            }      }    }} Trace gdupool:
 
页: [1]
查看完整版本: GVFS monitor device change by gdu module