六狼论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博账号登陆

只需一步,快速开始

搜索
查看: 40|回复: 0

GVFS monitor device change by gdu module

[复制链接]

升级  72.33%

125

主题

125

主题

125

主题

举人

Rank: 3Rank: 3

积分
417
 楼主| 发表于 2013-1-26 13:34:42 | 显示全部楼层 |阅读模式
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:
 
您需要登录后才可以回帖 登录 | 立即注册 新浪微博账号登陆

本版积分规则

快速回复 返回顶部 返回列表