\documentclass[twoside,a4paper]{scrreprt}

\usepackage[T1]{fontenc}
\usepackage[full]{textcomp}
\usepackage[utf8]{inputenc}
\usepackage[final=true,raiselinks=false,colorlinks=false,pdfborder=0 0 0]{hyperref}
\usepackage{helvet}
\usepackage[scaled]{luximono}
%\usepackage[mdugm]{mathdesign}
%\usepackage[bitstream-charter]{mathdesign}
%\usepackage[adobe-utopia]{mathdesign}
%\usepackage{iwona}
%\usepackage[scaled=]{inconsolata}
%\usepackage[scaled]{ulgothic}
%\usepackage[scaled]{beramono}
\usepackage{typearea}
\usepackage[automark]{scrpage2}
\usepackage[table,dvipsnames]{xcolor}
\usepackage{tikz}
\usepackage{listings}
\usepackage{caption}
\usepackage[nottoc]{tocbibind}
\usepackage{tabularx}

\include{style-light}
%\include{style-book}
%\include{style-experimental}

\makeatletter
\@ifundefined{float@listhead}{}{%
  \renewcommand*{\lstlistoflistings}{%
    \begingroup
      \if@twocolumn
        \@restonecoltrue\onecolumn
      \else
        \@restonecolfalse
      \fi
      \float@listhead{\lstlistlistingname}%
      \setlength{\parskip}{\z@}%
      \setlength{\parindent}{\z@}%
      \setlength{\parfillskip}{\z@ \@plus 1fil}%
      \@starttoc{lol}%
      \if@restonecol\twocolumn\fi
    \endgroup
  }%
}
\makeatother


% TikZ configuration
\usetikzlibrary{scopes,backgrounds,decorations.pathmorphing,shapes}
%\tikzset{every picture/.style={show background rectangle,show background grid},background grid/.style={draw=gray!50,step=.25}}

%\renewcommand\contentsname{Table of Contents}
\renewcommand{\lstlistlistingname}{Listings}

% Use Garamond as the default roman font
\renewcommand{\rmdefault}{ugm}
%\renewcommand{\sfdefault}{ugm}

% Use Day Roman as the default roman font
%\renewcommand{\rmdefault}{dayrom}
%\renewcommand{\sfdefault}{dayrom}

% Use Iwona as the default sans-serif font
%\renewcommand{\sfdefault}{iwona}

%\renewcommand{\rmdefault}{jkp}
%\renewcommand{\sfdefault}{jkpss}

%\renewcommand{\sfdefault}{phv}

% Modify line height
\renewcommand{\baselinestretch}{1.2}

% Type area correction, using 7.5mm required by the folder clamp 
% and 0.75mm wasted when flipping pages
\KOMAoptions{BCOR=8.25mm}

% Draft mode for debugging artifacts
\KOMAoptions{draft=true}

% Font settings
%\KOMAoptions{fontsize=11pt}
\addtokomafont{subtitle}{\sffamily}
\addtokomafont{subject}{\sffamily}
\addtokomafont{title}{\sffamily}
%\addtokomafont{chapter}{\usefont{T1}{dayrom}{l}{n}}
%\addtokomafont{disposition}{\usefont{T1}{dayrom}{l}{n}}
%\addtokomafont{chapter}{\rmfamily\color{NavyBlue!90!white}}
\addtokomafont{descriptionlabel}{\rmfamily\mdseries\color{NavyBlue}}
\addtokomafont{disposition}{\rmfamily\color{NavyBlue!100!white}}

% Table of contents settings
\KOMAoptions{toc=graduated} 
\KOMAoptions{toc=bibliographynumbered}
\KOMAoptions{toc=listofnumbered}
\KOMAoptions{toc=index}
\KOMAoptions{listof=graduated}

% Page numbering settings
\KOMAoptions{cleardoublepage=empty}

% Hide subsections in the table of contents
%\KOMAoptions{tocdepth=1}

% Chapter settings
\KOMAoptions{headings=openright}
\KOMAoptions{headings=small}
\KOMAoptions{headings=onelineappendix}
\KOMAoptions{headings=onelinechapter}

% Paragraph settings
\KOMAoptions{parskip=false}

% Page style
\pagestyle{scrheadings}

\newcommand{\covertext}[1]{\textmd{\textsf{#1}}}

% Title page contents
\titlehead{\centering \covertext{Lübeck University\\Institute for Theoretical Computer Science}}
\subject{\covertext{Studienarbeit}}
\title{\covertext{Migrating the Thunar File Manager to the Extensible Asynchronous\\Virtual File System Layer GIO}}
\author{\covertext{Jannis Pohlmann}}
\date{\covertext\today}
\publishers{
  \covertext{
    Supervised by \\
    Prof. Dr. Till Tantau
  }
}

% Statutory declaration
%\dedication{}

% Bibliography settings
\bibliographystyle{plain}
\KOMAoptions{bibliography=oldstyle}
\KOMAoptions{bibliography=totoc}
\renewcommand\bibname{Literature}

% Semantic markup
\newcommand{\component}[1]{{#1}}
\newcommand{\Thunar}{{\component{Thunar}}}
\newcommand{\Thunarx}{{\component{Thunarx}}}
\newcommand{\ThunarVFS}{{\component{ThunarVFS}}}
\newcommand{\GIO}{{\component{GIO}}}
\newcommand{\GVfs}{{\component{GVfs}}}
\newcommand{\GTK}{{\component{GTK+}}}
\newcommand{\GLib}{{\component{GLib}}}
\newcommand{\Xfce}{{\component{Xfce}}}
\newcommand{\GObject}{{\component{GObject}}}
\newcommand{\GType}{{\component{GType}}}
\newcommand{\DBus}{{\component{D-Bus}}}
\newcommand{\DeviceKit}{{\component{DeviceKit}}}
\newcommand{\DeviceKitDisks}{{\component{DeviceKit-disks}}}
\newcommand{\HAL}{{\component{HAL}}}
\newcommand{\GnomeDiskUtility}{{\component{gnome-disk-utility}}}
\newcommand{\GdkPixbuf}{{\component{Gdk\-Pixbuf}}}
\newcommand{\GNOME}{{\component{GNOME}}}
\newcommand{\GnomeVFS}{{\component{GnomeVFS}}}
\newcommand{\thunarvolman}{{\component{thunar-volman}}}
\newcommand{\thunarthumbnailers}{{\component{thunar-thumbnailers}}}
\newcommand{\xfdesktop}{{\component{xfdesktop}}}
\newcommand{\xfcepanel}{{\component{xfce4-panel}}}
\newcommand{\libgnomeui}{{\component{libgnomeui}}}
\newcommand{\GIMP}{{\component{GIMP}}}
\newcommand{\exo}{{\component{exo}}}
\newcommand{\KDE}{{\component{KDE}}}
\newcommand{\Maemo}{{\component{Maemo}}}
\newcommand{\Hildon}{{\component{Hildon}}}
\newcommand{\hildonthumbnail}{{\component{hildon-thumbnail}}}

% Change paragraph indentation
\parindent 1.5em

\begin{document}

\pagenumbering{roman}

\maketitle

\begin{abstract}

  \minisec{Abstract}

\end{abstract}

\tableofcontents
\thispagestyle{empty}
\cleardoublepage

\begingroup
%  \tocsection
%  \tocfile{\listfigurename}{lof}
%
%  \let\cleardoublepage\relax  % book
%  \let\clearpage\relax        % report

  \tocsection
  \tocfile{\lstlistlistingname}{lol}
\endgroup

\cleardoublepage
\pagenumbering{arabic}

\chapter{Introduction}

  Virtual file systems allow applications to access different types of file 
  systems in a uniform way. They are responsible for providing the following to 
  other libraries and applications:
  
    \begin{itemize}
      \item a uniform way to access different (virtual) file systems;
      \item detailed information about files and directories;
      \item high-level APIs for operations like copy, move, rename, trash or delete;
      \item ways to monitor files and directories for changes;
      \item an association of files with applications installed on the system; and
      \item storage device handling, also referred to as volume management.
    \end{itemize}

  Among the various applications which mostly use virtual file systems to open
  files from and write them to as many different locations as possible, file managers 
  are probably the most extensive and complex example for their use.

  This thesis describes the migration of the open source file manager \Thunar\ 
  from its original virtual file system (VFS) implementation \ThunarVFS\ to an asynchronous
  and extensible implementation called \GIO. Various migration and implementation
  problems are covered in more detail as they might be of wider interest when
  writing file managers or desktop applications or when dealing with asynchronous 
  application programming interfaces (APIs) in general.

  This chapter introduces \Thunar\ and \GIO\ by describing their origin and context
  as well as the design of the file manager in section~\ref{sec:thunar-and-gio}. For a 
  better understanding of the general purpose and architecture of \ThunarVFS\ and \GIO\, a 
  basic comparison is given in section~\ref{sec:brief-thunar-vfs-gio-comparison}. An in-depth 
  comparison with special focus on technical aspects can be found in 
  chapter~\ref{chapter:main}. The chapter closes with section~\ref{sec:overview} by
  providing a quick overview of the migration and the topics selected for this thesis.

  \section{Thunar and GIO in a Nutshell}\label{sec:thunar-and-gio}

    \Thunar\ is a file manager written and maintained as part of the
    open source desktop environment \Xfce. Originally started by Benedikt 
    Meurer in 2005, it has been around since the 4.4 release of \Xfce\ in late 2007.
    \Thunar\ was designed from the ground up to be fast and intuitive to use. 
    It can be used with assistive technologies and implements the most relevant 
    freedesktop.org specifications to ensure compatibility with other desktops and 
    applications.

    As a file manager its main task is to enable users to browse and manage 
    files and folders on their computers. This includes everything from folder
    listings, copy, move and delete operations, opening files with applications 
    installed on the system up to generating preview images and handling storage 
    devices, often referred to as volume management. In a modern desktop 
    scenario, the file manager is also responsible for supporting other 
    applications in accessing the file system.

    Like in all other components of \Xfce, the \GTK\ toolkit is 
    used to build the graphical user interface of \Thunar. Even though being
    written in C, \Thunar\ follows the object-oriented programming paradigm 
    by making heavy use of \GObject\ and the \GType\ type system, 
    both of which are part of \GLib, a utility library that is also 
    used by \GTK\ and the rest of \Xfce.

    \begin{figure}[h]
      \centering
      \pgfimage[width=8cm,interpolate=true]{images/thunar.pdf}
      \caption{Thunar using different views and toolbars}
    \end{figure}

    \Thunar\ is split up into three components, as can be seen in figure
    \ref{fig:thunar-components}. As mentioned in the introduction, \ThunarVFS\ is a file 
    system abstraction layer which was developed together with \Thunar. Being the
    library to be migrated away from, it plays a major role in this thesis.
    \ThunarVFS\ is described in more detail in sections~\ref{sec:brief-thunar-vfs-gio-comparison} and 
    \ref{sec:detailed-thunar-vfs-gio-comparison}. \Thunarx\ is an extension framework
    which allows plugins to be written for the file manager. Finally,
    \Thunar\ itself describes the application written on top of these
    libraries, which aside from the graphical user interface also provides
    a \DBus\ (a widely used inter-process communication system) service for other 
    desktop applications.

    \GIO\ (the GLib Input, Output and Streaming Library) was, along with \GVfs, developed by 
    Alexander Larsson with the goal to eventually replace \GnomeVFS, a VFS layer previously
    used inside the \GNOME\ desktop environment. \GnomeVFS\ had numerous shortcomings which
    were discussed broadly~\cite{plans-for-gnome-vfs-replacement}. \GIO\ avoids these
    limitations by providing a high-level asynchronous API that is heavily extensible. It 
    was merged into \GLib\ in late 2007 and was first released as part of \GLib~2.16.0 in
    March 2008.

    \begin{figure}[h]
      \centering
      \begin{tikzpicture}[every path/.style={rounded corners=.2em},every node/.style={rounded corners=.2em,transform shape,font=\large},scale=.63]
        \node[fill=NavyBlue!60,draw=NavyBlue!70,minimum height=1.5cm,minimum width=10cm,text width=4cm] at (5,10) { Thunar };
        \node[fill=NavyBlue!50,draw=NavyBlue!60,minimum height=1.5cm,minimum width=3cm] at (8.5,10) { D-Bus Service };

        \path[shape=coordinate]
          ( 0.000, 9.000) coordinate(Thunarx1) 
          ( 4.000, 9.000) coordinate(Thunarx2) 
          ( 4.000, 8.250) coordinate(Thunarx3)
          ( 3.250, 8.250) coordinate(Thunarx4)
          ( 3.250, 6.250) coordinate(Thunarx5)
          ( 4.000, 6.250) coordinate(Thunarx6)
          ( 4.000, 5.500) coordinate(Thunarx7)
          ( 0.000, 5.500) coordinate(Thunarx8);

        \filldraw[fill=NavyBlue!40,draw=NavyBlue!50] 
          (Thunarx1) -- (Thunarx2) -- (Thunarx3) -- (Thunarx4) -- 
          (Thunarx5) -- (Thunarx6) -- (Thunarx7) -- (Thunarx8) -- cycle;

        \node at (1.625,7.125) { Thunarx };

        \path[shape=coordinate]
          ( 4.250, 9.000) coordinate(ThunarVfs1)
          (10.000, 9.000) coordinate(ThunarVfs2)
          (10.000, 5.500) coordinate(ThunarVfs3)
          ( 4.250, 5.500) coordinate(ThunarVfs4)
          ( 4.250, 6.500) coordinate(ThunarVfs5)
          ( 3.500, 6.500) coordinate(ThunarVfs6)
          ( 3.500, 8.000) coordinate(ThunarVfs7)
          ( 4.250, 8.000) coordinate(ThunarVfs8);

        \filldraw[fill=NavyBlue!20,draw=NavyBlue!30] 
          (ThunarVfs1) -- (ThunarVfs2) -- (ThunarVfs3) -- (ThunarVfs4) -- 
          (ThunarVfs5) -- (ThunarVfs6) -- (ThunarVfs7) -- (ThunarVfs8) -- cycle;
        
        \node at (7,7.125) { ThunarVFS };

        \node[fill=yellow!40,draw=yellow!100!orange,minimum height=1.5cm,minimum width=4cm] at (2,4) { Plugins };
        \node[fill=orange!40,draw=orange!40,minimum height=1.5cm,minimum width=5.75cm] at (7.125,4) { Thumbnailers };
        \node[fill=red!30,draw=red!40,minimum height=1.5cm,minimum width=5.25cm,rotate=-90] at (11.5,8.125) { Other Applications };
      \end{tikzpicture}
      \caption{Basic architecture of Thunar}\label{fig:thunar-components}
    \end{figure}

    The reason for moving it to the lower bottom of the \GTK\ software stack was to enable
    all applications and also \GTK\ itself to take advantage of it. To lower the impact on
    applications less concerned with virtual file systems, \GIO\ by itself only implements 
    a small part of what can be achieved with it: access to local files. 
    Designed for extensibility, it mainly serves as a uniform wrapper for various VFS
    backends. These can be loaded on demand, typically run in separate processes and
    communicate with \GIO\ over \DBus. They can thus be easily shared among all applications 
    in the current desktop session---something from which the user experience greatly benefits. 
    Several such implementations are available as part of \GVfs, the most accepted set of 
    \GIO\ extensions to date.

  \section{A Brief Comparison of ThunarVFS and GIO}\label{sec:brief-thunar-vfs-gio-comparison}

    Both, \ThunarVFS\ and \GIO\ are implementations of a virtual file system. As such
    they provide roughly the same set of features that was already mentioned earlier in
    the introduction. In file managers virtual file systems like \ThunarVFS\ and \GIO\ play 
    a key role. Every piece of information is retrieved and all operations
    on the real file system are performed through them.

    The main differences between \ThunarVFS\ and \GIO\ are the extensibility and
    asynchronous API design of \GIO. Unlike \ThunarVFS, which was written especially for
    being used in \Thunar, \GIO\ takes a much more generic approach and leaves a lot of
    implementation details open to extensions. Extension points are available for virtual file 
    systems such as the SSH File Transfer Protocol or Windows network shares, volume management, 
    file monitoring and the association of file types with applications. This makes it much 
    more flexible and powerful than \ThunarVFS. 
    
    \GIO\ provides asynchronous APIs for all operations that may run for a long time, and,
    if performed synchronously, may freeze the user interface of an application. This 
    includes everything from querying file information up to mounting volumes. Asynchronous 
    functions are very important when dealing with slow drives and remote file systems. Since
    \ThunarVFS\ only supports local files, it is only logical that most of its APIs are 
    synchronous.

  \section{Overview of the Migration to GIO}\label{sec:overview}

    Abandoning a virtual file system layer in favor of another in a file manager and
    an entire desktop environment is nothing short of a complex undertaking. As can be
    deduced from the comparison in section \ref{sec:brief-thunar-vfs-gio-comparison}, everything
    a file manager does is based on the information it requests from and the operations
    it performs on the virtual file system. Other desktop applications depend on the
    file manager as a service for common routines and graphical user interface elements
    like file information dialogs. Changes made to the foundations of a file manager not
    necessarily but often affect its behaviour and thus, have implications on other
    applications as well. This especially holds when modifications introduce gaps
    in functionality. Finally, abandoning a virtual file system layer that is directly 
    used in other applications also involves migrating these applications.

    The migration of \Thunar\ to \GIO\ is based on several arguments.
    First of all, Xfce is a very small open source project with only about half a 
    dozen core developers. Every new component introduces a new maintenance 
    burden. Like many companies that are trying to outsource development and
    maintenance into communities, like Nokia does with parts of their \Maemo\ platform 
    for instance, one of the goals of Xfce is to reduce the overall 
    maintenance overhead in order to concentrate on the core of the desktop by
    to reusing components developed and maintained by others---especially when 
    they are already part of the software stack being used, as is the case with 
    \GIO. Being part of \GLib\ and thereby widely used and tested in \GTK\ and 
    \GNOME, \GIO\ is very likely to be maintained for a long time. Thus, it is 
    reasonable to adopt it and only maintain the pieces missing due to gaps in 
    functionality compared to \ThunarVFS.

    If maintenance by itself already is a high burden, as is the case with \ThunarVFS, 
    this holds even more for the development of new features. 
    \ThunarVFS, except for thumbnailers, is not extensible at all. As a consequence 
    its range of features is limited by the amount of direct contributors to 
    \ThunarVFS. \GIO\ on the other hand provides many extension points which makes
    it possible to incorporate features written by other parties without having to 
    maintain them. 
    The most important extension point is the one for \code{GFileInfo}, allowing
    virtual file system backends for arbitrary URI schemes such as \code{sftp://} or
    \code{computer://}. This is one of features most desired and requested by users.
    With the availability of extension bundles like \GVfs, \GIO\ introduces
    a number of new features, such as a better integration into Windows networks,
    eventually leading to a better user experience.
    
    The migration is also personally motivated. Performing such a complex migration---the
    \Thunar\ application (figure \ref{fig:thunar-components}) alone is worth about 52,000 
    physical lines of code---is a real challenge. Keeping the entire application in a 
    working state throughout the entire step-by-step process introduces additional 
    difficulties. Last but not least, basing one's work on an existing and complex code base 
    trains software development skills and helps in learning more about software design 
    and refactoring.

    The following chapters describe the migration process as well as its results and
    consequences. The most interesting and universal topics of the migration are
    covered in more detail. The results are briefly evaluated in 
    chapter~\ref{chapter:evaluation} by summing up what new features and regressions 
    were introduced and how other applications are affected by the changes made. Finally, an
    outlook is given in chapter~\ref{chapter:outlook} with a special focus on how the 
    situation after the migration can be further improved.
 
\chapter{Migration Process and Selected Topics}\label{chapter:main}

  \section{Planning Phase and Migration Strategy}\label{sec:planning-phase}

    A migration as complex as this has to be planned thoroughly. In this particular case, the 
    first thing to investigate was which components were directly involved in or affected by
    the migration of \Thunar\ to \GIO.

    \begin{description}
      \item[\Thunar] The file manager itself. Uses \ThunarVFS\ for almost everything. Needs a 
        few fundamental changes to work with \GIO.
      \item[\Thunarx] The \Thunar\ extension library. Overlaps with \ThunarVFS\ only in a 
        single function. Easy to migrate.
      \item[\ThunarVFS] The current VFS layer used by \Thunar. Ideally moved into its own package
        for other applications to depend on it until they have been migrated.
      \item[\Thunar\ Volume Monitor] An application to perform actions when devices are plugged or 
        unplugged. Integral part of the user experience concept of \Thunar. Uses \ThunarVFS\ 
        only for monitoring its configuration file. 
      \item[\Thunar\ Extensions] There are 6 extension packages for \Thunar, plus a few plugins shipped 
        with \Thunar\ itself. Most of them use \ThunarVFS\ for querying file information and will
        have to be migrated.
      \item[\Thunar\ Thumbnailers] A set of scripts called by \ThunarVFS\ to generate preview images 
        for files. As \GIO\ does not implement thumbnailing itself, it would be nice to provide
        a solution that works without \ThunarVFS\ but still supports these scripts.
      \item[\Xfce\ Desktop Manager] An \Xfce\ core component responsible for managing the desktop,
        including file and device icons. Relies on \Thunar\ for file operations and \ThunarVFS\ 
        for thumbnailing and file information. Has to be migrated to \GIO. Ideally, the \DBus\
        service API provided by \Thunar\ would be extended to re-use \Thunar\ widgets like the
        file properties dialog.
      \item[\GIO] The future replacement for \ThunarVFS. Its differences compared to \ThunarVFS, 
        including advantages and shortcomings, are discussed broadly in 
        sections~\ref{sec:brief-thunar-vfs-gio-comparison} and 
        \ref{sec:detailed-thunar-vfs-gio-comparison}.
      \item[\GVfs] Besides shipping VFS backends for various URI schemes, also provides
        a volume management implementation which is not part of \GIO itself. Unfortunately 
        depends on several \GNOME\ modules. To maintain feature parity before and after
        the migration without drastically increased dependencies, a separate volume management
        implementation would have to be written.

    \end{description}

    Some of these components, including several of the extensions and the \Xfce\ desktop 
    manager, are out of the scope of this thesis, as they are maintained by other people.
    The focus is thus set on replacing all occurrences of \ThunarVFS\ inside the \Thunar\ and 
    \Thunarx\ source code with (hopefully) equivalent code based on \GIO. As a step-by-step
    documentation of this process would make for a very long and tedious piece of paper, 
    section~\ref{sec:detailed-thunar-vfs-gio-comparison} instead concentrates on explaining the 
    implementation and API differences of \ThunarVFS\ and \GIO. Descriptions of the resulting 
    search-and-replace work and minor refectorings are left out for obvious reasons.

    As we will see, some of the differences of \ThunarVFS\ and \GIO\ raise more problems
    than others. Selected differences that might have a wider impact on the desktop as 
    a whole are highlighted in sections~\ref{sec:job-framework}, \ref{sec:tumbler} and
    \ref{sec:network-browsing-requirements}.

  \section{A Detailed Comparison of ThunarVFS and GIO}\label{sec:detailed-thunar-vfs-gio-comparison}

    In the following, \ThunarVFS\ and \GIO\ are compared by describing how they implement
    the VFS-typical features listed in section~\ref{sec:brief-thunar-vfs-gio-comparison}, and 
    also how they differ from one another, both from a technical and a user point of view. 
    The implications on the migration---or to be more specific, the
    modifications required to port the majority of the \Thunar\ source code to \GIO---are not 
    explained in detail. As we will see, most of the differences presented here are of minor 
    scale, and thus, almost trivially resolvable. The ones which have a major impact are 
    described later in this chapter.

    \subsection*{Accessing Different File Systems}

      Files on supported file systems are addressed either by local paths or
      URIs. \ThunarVFS\ only implements the \code{file://} and \code{trash://} URI 
      schemes. \GIO\ by default only supports \code{file://} but can be extended
      to support arbitrary schemes. Through \GVfs, \code{trash://}, \code{sftp://}, 
      \code{ftp://}, \code{network://} and several others are available.

      Since path or URI strings are rather inconvenient to work with, both, 
      \ThunarVFS\ and \GIO\ provide the \code{ThunarVfsPath} and \code{GFile} wrapper
      classes for defining and working with URIs. They provide about the same 
      functionality and thus, one can easily replace the other. Their
      most important features include parsing local paths, URIs and command line 
      arguments and computing how two files are related to each other in the file 
      system hierarchy (e.g. via an ancestor--descendant relationship).

    \subsection*{Querying File Information}

      For loading information about files and directories, again, \ThunarVFS\ and
      \GIO\ have two very similar classes called \code{ThunarVfsInfo} and 
      \code{GFileInfo} of which the latter is actually an interface that can be
      implemented by extensions in order to add support for other virtual file 
      systems. They are created from a \code{ThunarVfsPath} and \code{GFile} with 
      the main difference being that \code{GFileInfo} allows to select which bits 
      of the overall file information are loaded. Other than that they are more or less 
      equivalent, as demonstrated in listings \ref{code:thunar-vfs-info} and 
      \ref{code:gio-file-info}. Listing~\ref{code:gio-file-info} also shows how 
      only certain attribute names like \code{standard::size} or attribute 
      namespaces like \code{standard::*} can be filtered and selected.

      \begin{lstlisting}[caption=Querying the size of a file with \ThunarVFS.,label=code:thunar-vfs-info]
ThunarVfsPath *path = thunar_vfs_path_new (uri);
ThunarVfsInfo *info = thunar_vfs_info_new_for_path (path, &error);
ThunarVfsFileSize size = info->size;
      \end{lstlisting}

      \begin{lstlisting}[caption=Querying the size of a file with \GIO.,label=code:gio-file-info]
GFile *file = g_file_new_for_uri (uri);
GFileInfo *info = g_file_query_info (file, "standard::*", cancellable, &error);
guint64 size = g_file_info_get_attribute_uint64 (info, "standard::size");
      \end{lstlisting}

      Filtering attributes can have positive impacts on the performance when dealing
      with slow drives or remote file systems. However, due to the internal design of 
      \Thunar, information about a file is usually only queried once. Thus, being 
      able to filter means to make a decision on \textit{what} to filter. This decision
      would be easy if it only affected the file manager itself. Unfortunately,
      plugins written based on \Thunarx\ by default only have access to the same
      information \Thunar\ is loading. They can query their own file attributes but the
      the information which attributes and namespaces are initially available to 
      plugins has to be defined somewhere in the \Thunarx\ API. Listing~\ref{code:namespaces}
      shows which namespaces are being used at the time of writing. They are split
      up into file and file system namespaces, as information about the file system
      can only be retrieved with the \code{g\_file\_query\_filesystem\_info} method.

      \begin{lstlisting}[caption=Default file information namespaces used in \Thunar\ and \Thunarx,label=code:namespaces]
#define THUNARX_FILE_INFO_NAMESPACE "access::*,id::*,mountable::*,preview::*," \
  "standard::*,time::*,thumbnail::*,unix::*"
#define THUNARX_FILESYSTEM_INFO_NAMESPACE "filesystem::*"
      \end{lstlisting}

    \subsection*{File Operations}

      File operations like copy, move, rename, trash or delete are handled
      differently in \ThunarVFS\ and \GIO. \GIO\ provides one synchronous and 
      asynchronous method per operation to which a finish and sometimes a progress 
      callback can be passed. In addition, these methods optionally take a 
      \code{GCancellable} parameter in case the operation can be cancelled. This is 
      demonstrated in listing~\ref{code:gio-copy}. These operations only work
      on individual files and are non-recursive. For this purpose the API is
      decent. However, it is insufficient for complex operations like recursive 
      copies or moves.

      \begin{lstlisting}[caption=Copying a file with \GIO.,label=code:gio-copy]
GFile *source, *destination;
...
g_file_copy_async (source, destination, G_FILE_COPY_NONE, 0, cancellable, 
                   progress_callback, user_data, finish_callback, user_data);
      \end{lstlisting}

      \ThunarVFS\ on the other hand provides a generic and much more versatile
      framework for asynchronous and possibly interactive operations,
      which is implemented via several \GObject\ classes called
      \code{ThunarVfsJob}, \code{ThunarVfsSimpleJob} and 
      \code{ThunarVfsTransferJob}. Instead of passing callbacks to a function,
      one can create a \code{ThunarVfsJob} object and connect to signals with
      different meaning. This is a concept that is used everywhere in
      \Thunar, \GTK, and basically everything based on \GObject, and thus, fits
      well into the design of many applications.

      \begin{lstlisting}[caption=Recursively copying a directory with \ThunarVFS.,label=code:thunar-vfs-copy]
ThunarVfsPath *source, *destination;
...
ThunarVfsjob *job = thunar_vfs_copy_file (source, destination, &error);
g_signal_connect (job, "percent", G_CALLBACK (progress_callback), user_data);
g_signal_connect (job, "finished", G_CALLBACK (finish_callback), user_data);
g_signal_connect (job, "ask-replace", G_CALLBACK (ask_callback), user_data);
      \end{lstlisting}

      \ThunarVFS\ also offers very powerful functions for performing recursive
      and non-recursive file operations such as directory listings, copying, moving, 
      deleting files and directories and others like changing permissions recursively, 
      all based on \code{ThunarVfsJob}. An example usage of this can be seen in 
      listing~\ref{code:thunar-vfs-copy}. While this looks more complicated and 
      verbose than the \GIO\ snippet on the first sight, it is much more flexible 
      and in line with the coding style being used in the rest of \Thunar.

      Due to its important role inside \Thunar\ and also in the migration,
      the job framework is covered in more detail in section~\ref{sec:job-framework}.

    \subsection*{File Monitoring}

      \ThunarVFS\ and \GIO\ allow individual files and directories to be monitored
      for changes using dedicated classes. In \ThunarVFS\ there is a singleton class
      called \code{ThunarVfsMonitor} with \code{thunar\_vfs\_monitor\_add\_file} and 
      \code{thunar\_vfs\_monitor\_add\_directory} functions to set up monitoring. These 
      functions take a \code{ThunarVfsPath} and a monitor callback and return a 
      unique identifier with which the monitoring can be cancelled again later.

      \GIO\ has an interface similar to this called \code{GFileMonitor}. Its 
      implementation may vary depending on the platform but unlike \code{ThunarVfsMonitor} 
      it is not necessarily implemented as a singleton. File or 
      directory monitoring can be set up with the \code{g\_file\_monitor} function which 
      takes a \code{GFile} and returns an instance of \code{GFileMonitor}. One can then
      connect to a change signal of this instance to be notified of changes made to the 
      file.
      
      Once monitoring is set up the way described above, the workflow resulting from
      the two APIs is again very much the same.

    \subsection*{Association of Files With Applications}

      On the Linux desktop files are, by tradition, associated with applications via 
      their MIME type, a two-part identifier for file formats originating from 
      Multipurpose Internet Mail Extensions standard for non-ASCII character sets 
      in emails, non-text attachments and multi-part message bodies~\cite{rfc2046}.

      The problems how to determine the MIME type of a file and how to register an 
      application as a possible MIME type handler are addressed by two freedesktop.org
      specifications~\cite{shared-mime-info-spec}~\cite{desktop-entry-spec}. In addition
      to storing MIME types supported by an application in its desktop entry, the file
      \code{\$XDG\_DATA\_DIRS/applications/mimeinfo.cache} can be used to define 
      additional MIME types for an application. The association of MIME types with
      default applications aare then defined using the files
      \code{\$XDG\_DATA\_DIRS/applications/defaults.list} (global) and 
      \code{\$XDG\_DATA\_DIRS/applications/mimeapps.list} (individual users). 
      It is noteworthy that \code{mimeinfo.cache} and \code{defaults.list} are not part
      of any freedesktop.org specifications and, for instance, not used by the \KDE\ 
      desktop environment.
      
      Based on this information, \ThunarVFS\ and \GIO\ implement various classes and 
      functions to determine the MIME type of a file, query applications capable of 
      opening a file, get and set the default application for a type and
      launch files with applications.

      In \ThunarVFS, each file is associated with a \code{ThunarVfsMimeInfo}, which
      is a simple wrapper around its MIME type string. Using this information, applications
      able to handle the file can be queried from a singleton \code{ThunarVfsMimeDatabase}.
      Apart from the class \code{ThunarVfsMimeApplication} which represents applications, \ThunarVFS\
      also supports a deprecated but very useful part of the desktop entry 
      specification~\cite{desktop-entry-spec} called desktop actions. They allow desktop 
      entries to include a number of actions in addition to the information about the 
      application itself. These actions, `Burn image' for instance, too can be connected to 
      MIME types and then be used in context menus. In \ThunarVFS, they are implemented via the
      \code{ThunarVfsMimeAction} class. To unify the workflow with these two classes, 
      there is an interface called \code{ThunarVfsMimeHandler} which both classes
      implement. Listing \ref{thunar-vfs-default-app} demonstrates how these APIs can 
      be used to determine the default application for a file.

      \begin{lstlisting}[caption=Querying the default application for a file with \ThunarVFS.,label=thunar-vfs-default-app]
ThunarVfsInfo *info = thunar_vfs_info_new_for_path (path);
ThunarVfsMimeDatabase *db = thunar_vfs_mime_database_get_default ();
ThunarVfsMimeApplication *app =
  thunar_vfs_mime_database_get_default_application (db, info->mime_info);
      \end{lstlisting}

      \begin{lstlisting}[caption=Querying the default application for a file with \GIO.,label=gio-default-app]
GFileInfo *info = g_file_query_info (file, ...);
const gchar *type;
type = g_file_info_get_attribute_string (info, "standard::content-type");
GAppInfo *app = g_app_info_get_default_for_type (content_type, FALSE);
      \end{lstlisting}

      \GIO\ drastically simplifies this. There is no wrapper for MIME types. Instead, each
      \code{GFileInfo} has a \code{standard::content-type} string attribute. There is a number
      of utility functions to work with these strings, like \code{g\_content\_type\_equals}. To
      represent applications in the code an interface called \code{GAppInfo} is used. It is not
      limited to the aforementioned specifications but has an implementation based on 
      desktop entries built in. \code{GAppInfo} can be used in a similar fashion as the
      APIs from \ThunarVFS, as is shown in listing~\ref{gio-default-app}.

    \subsection*{Volume Management}

      Storage device handling, also known as volume management or volume monitoring, is 
      implemented very differently in \ThunarVFS\ and \GIO. Traditionally, volume management 
      implementations on Linux are written on top of a hardware abstraction layer creatively 
      called \HAL. Since 2008 the trend is to abandon \HAL\ in favor of \DeviceKit, a modular 
      system service with \DBus\ interfaces for storage devices, power management and more. 
      \DeviceKitDisks\ provides the \DBus\ interface for volume management. Like \HAL, 
      \DeviceKit\ was first written for Linux and is now slowly being ported to other Unixes.

      \ThunarVFS\ has two different volume management implementations built in:\\
      \code{ThunarVfsVolumeFreeBSD} and \code{ThunarVfsVolumeHal}. With \HAL\ undergoing 
      deprecation, this would soon require a rewrite based on \DeviceKitDisks. Overall, the
      API presented to users of the library is very simple. There are only two classes, of
      which the first one, \code{ThunarVfsVolumeManager} provides methods to query available
      volumes. The returned volumes are instances of \code{ThunarVfsVolume} and can be used
      to get information about a CD-ROM drive, floppy disk, USB stick, memory card or
      partition. \code{ThunarVfsVolume} also offers methods to eject, mount and unmount
      a volume and signals for when a volume is mounted or unmounted. All of these methods
      are synchronous and very straightforward.

      The equivalent \GIO\ API is once again a collection of interfaces which can easily
      be implemented in the form of \GIO\ extensions. Implementations based on \HAL\ and
      \GnomeDiskUtility, which is an abstraction layer on top of \DeviceKitDisks, are available 
      as part of \GVfs. \GIO\ exposes much more of the underlying hardware. In addition to 
      the \code{GVolume} interface which represents user-visible partitions, there are 
      separate interfaces for physical drives and user-visible mounts called \code{GDrive}
      and \code{GMount}. \code{GDrive} and \code{GMount} are only really needed for
      checking whether a partition is already mounted or not. \code{GVolume} is the
      main interface used to query information about partitions and to mount and unmount
      them. A list of all available volumes can be retrieved through \code{GVolumeMonitor} 
      which is equivalent to \code{ThunarVfsVolumeManager} in that regard.

      Another difference between \ThunarVFS\ and \GIO\ here is that, once again, all possibly
      long-running or interactive operations like mounting or ejecting are asynchronous
      and care has to be taken of side effects like race conditions when using them. 

    \subsection*{Other Notable Differences}

      File managers, desktop managers, image viewers and a lot of other applications often
      require preview images of files, also referred to as thumbnails, to make them more easily
      distinguishable or to add a visual aspect to the usually mostly textual file information.
      Files for which thumbnails are often required include image files, videos, PDF or 
      word documents and fonts. What thumbnail formats are generated and how and where they 
      are stored is defined by the thumbnail managing standard~\cite{thumbnail-spec}, another
      freedesktop.org specification.

      \GIO\ only has rudimentary support for thumbnailing. When a \code{GFileInfo} is
      queried with the \code{thumbnail::path} attribute enabled it checks whether a valid thumbnail 
      file exists and if so, sets the attribute value to the path of the thumbnail. There is
      no API to create or manage thumbnails.

      \ThunarVFS\ on the other hand not only provides methods to query, generate and
      store thumbnails via the \code{ThunarVfsThumbFactory} class. For once, it also 
      offers an extension point for custom thumbnailer scripts. Thumbnailers are 
      defined using desktop entries~\cite{desktop-entry-spec} and can be used to 
      generate thumbnails for literally any MIME type. \ThunarVFS\ itself ships
      thumbnailers for JPEG, image formats supported by \GdkPixbuf, an imaging library used
      by \GTK, as well as fonts. 
      Thumbnailers for PDF, videos and more are provided by a separate component 
      called \thunarthumbnailers.

      The lack of thumbnailing support in \GIO\ raises the problem how to deal with
      the thumbnailing code from \ThunarVFS\ with the ultimate goal to maintain the
      same feature in \Thunar\ even after the migration. Section~\ref{sec:tumbler}
      discusses possible solutions and the final implementation in detail.

  \section{Framework for Time-Consuming Operations}\label{sec:job-framework}

    Many of the things a file manager does require multi-threading or at least
    asynchronous processing in order for the graphical user interface to remain
    responsive. When dealing with slow drives or files on other machines connected
    over the local network or the internet, this includes everything down to the
    very atomic operations. If, for instance, the network connection is interrupted
    or even lost, and the application waits for the result of a synchronous file 
    information query, the usual network timeout is certainly not an acceptable
    response time for the user interface. 
    
    Refactoring an existing application that was not designed to be event-driven 
    in all possible situations is challenge on its own. Thus, this section focuses 
    on less atomic operations like copying files or listing the contents of a folder,
    which were already performed asynchronously in \Thunar\ before the migration.
    In section~\ref{sec:detailed-thunar-vfs-gio-comparison} the major differences
    of the file operation APIs of \GIO\ and \ThunarVFS\ were discussed. It was 
    concluded that the more generic high-level API of \ThunarVFS\ is a much better
    approach, especially for recursive operations which are simply not present
    in \GIO\ itself.

    For the migration this means that the code for \code{ThunarVfsJob}, 
    \code{ThunarVfsTransferJob}, and \code{ThunarVfsSimpleJob} either has to be
    integrated into the source code of \Thunar\ itself, or into one of the 
    libraries \Thunar already depends on. Listing~\ref{fig:thunar-vfs-job} shows 
    that, aside from the \code{infos-ready} and \code{ask-replace} signals, 
    \code{ThunarVfsJob} as well as \code{ThunarVfsSimpleJob} are not limited to 
    to file operations at all. In fact, they can be seen as general-purpose classes 
    to ease the implementation of \textit{any} threaded or asynchronous operation. 
    They provide basic features to create jobs based on a subclass of \code{ThunarVfsJob} 
    or simply a delegate (which traditionally is a function pointer). Subclasses of 
    \code{ThunarVfsJob} can override the \code{execute} method which is processed 
    in a separate thread once \code{launch} has been called. Delegates are like the 
    \code{execute} method and allow less complex jobs to be defined without subclassing.

    Some of the signals, like \code{info-message} or \code{percent} or can be emitted 
    from within the \code{execute} function or the delegate. Others, like 
    \code{error} or \code{finished} are emitted by \code{ThunarVfsJob} depending
    on the success of the job. The signals \code{ask} and \code{ask-replace} can
    be used in case user interaction is needed. It should be noted that \code{ThunarVfsJob}
    takes care of synchronizing threads when emitting signals, which makes life much
    easier for developers.
    
    \begin{lstlisting}[caption=Declarations of \code{ThunarVfsJob} and \code{ThunarVfsSimpleJob} in simplified Vala syntax.,label=fig:thunar-vfs-job]
enum ThunarVfsJobResponse {
  YES, YES_ALL, NO, NO_ALL, CANCEL, SKIP
}

class ThunarVfsJob : GLib.Object {
  ThunarVfsJob launch ();
  void cancel ();
  bool cancelled ();

  abstract void execute ();

  signal void error (GError error);
  signal void finished ();
  signal void percent (double percent);
  signal void info-message (string message);
  signal void infos-ready (List<ThunarVfsInfo> thunar_vfs_infos);
  signal ThunarVfsJobResponse ask (string message, ThunarVfsJobResponse choices);
  signal ThunarVfsJobResponse ask_replace (ThunarVfsInfo src_info, 
                                           ThunarVfsInfo dst_info);
}

delegate bool ThunarVfsSimpleJobFunc (Job job, GValue[] values) throws GLib.Error;

class ThunarVfsSimpleJob : ThunarVfsJob {
  ThunarVfsJob launch (ThunarVfsSimpleJobFunc job_function, 
                       unsigned int           n_values, ...);
}
    \end{lstlisting}

    Threads are rather difficult to work with, especially in a language like C which 
    lacks built-in synchronization features. The \ThunarVFS\ job classes provide a 
    convenient and easy-to-use alternative to manual synchronization and low-level 
    thread management. The demonstrated flexibility of \code{ThunarVfsJob} and
    \code{ThunarVfsSimpleJob} thus makes them good candidates for inclusion in a 
    library called \exo\ (the \Xfce\ extension library) which is already being used by
    many \Xfce\ core applications like \Thunar, \xfdesktop\ and \xfcepanel. By moving
    the two classes into this library, everything written for \Xfce\ could benefit
    from them.

    Unsurprisingly, this is what happened during the migration. The classes were not
    only renamed to \code{ExoJob} and \code{ExoSimpleJob}, they were also rewritten
    from scratch. Instead of synchronizing threads manually based on \code{GThread}, 
    the threading subsystem of \GLib, as was done in \code{ThunarVfsJob}, 
    \code{ExoJob} was implemented using \code{GIOScheduler}, a scheduler for
    asynchronous (input/output) operations with integration into the \GLib\ main 
    event loop, mainly used inside \GIO. Both, the \code{execute} function and the
    \code{ThunarVfsSimpleJobFunc} delegate also gained an additional \code{GCancellable}
    parameter to replace the boolean cancel flag previously being used.

    The last remaining class, \code{ThunarVfsTransferJob}, and all convenience functions
    such as \code{thunar\_vfs\_copy\_file} and \code{thunar\_vfs\_list\_directory} were
    renamed and moved into \Thunar\ itself, again not without being rewritten almost
    in their entirety. Naturally, all file operations were implemented on top of
    lower-level \ThunarVFS\ functions before, and had to be migrated to \GIO. Even
    though not quite as simple as a search and replace task, this is not 
    covered here.

  \section{Thumbnail Generation Using the Tumbler D-Bus Service}\label{sec:tumbler}

    Generating and managing preview images for files, also called thumbnails, turns
    out to be more complex than it first sounds. The thumbnail managing 
    standard~\cite{thumbnail-spec}, a widely adopted freedesktop.org specification, 
    defines how and where thumbnails are stored.

    As discussed in section~\ref{sec:brief-thunar-vfs-gio-comparison}, \GIO\ supports
    this standard in only one direction---loading thumbnail information. There are no functions
    for generating and storing thumbnails, most likely because the means by which thumbnails
    are generated usually vary between different applications. \GNOME\ applications traditionally
    use \code{GnomeThumbnailFactory} from a library called \libgnomeui, the image editor \GIMP\ 
    has its own built-in thumbnailing code and \Thunar\ has always been using \ThunarVFS\ for 
    generating thumbnails.
    
    \ThunarVFS\ provides an implementation for generating thumbnails and saving them in 
    compliance with the thumbnail managing standard~\cite{thumbnail-spec} called
    \code{ThunarVfsThumbFactory}. Its design is very similar to \code{GnomeThumbnailFactory} in
    many regards. Its API design is shown in listing~\ref{code:thunar-vfs-thumb-factory}.
    
    %As is shown in listing~\ref{code:thunar-vfs-thumb-factory}, it has a synchronous
    %API, which means that it is usually wrapped in a threaded class in order to avoid user interface
    %freezes due to high numbers of thumbnail requests.

    In addition to built-in thumbnailing code for several image formats based on \GdkPixbuf, 
    JPEG and fonts, \ThunarVFS\ also allows for custom thumbnailers to be written. These are 
    defined using desktop entries including information such as supported MIME types and shell 
    command, as demonstrated in listing~\ref{code:thunar-vfs-thumbnailer}.

    \begin{lstlisting}[caption=API of \code{ThunarVfsThumbFactory} in simplified Vala syntax.,label=code:thunar-vfs-thumb-factory]
enum ThunarVfsThumbSize {
  NORMAL, LARGE
}

class ThunarVfsThumbFactory : GLib.Object {
  ThunarVfsThumbFactory   (ThunarVfsThumbSize size); // Constructor
  
  string lookup_thumbnail (ThunarVfsInfo info);
  bool can_thumbnail (ThunarVfsInfo info);
  bool has_failed_thumbnail (ThunarVfsInfo info);
  Gdk.Pixbuf generate_thumbnail (ThunarVfsInfo info);
  bool store_thumbnail (Gdk.Pixbuf pixbuf, ThunarVfsInfo info) throws GLib.Error;
}

string thunar_vfs_thumbnail_for_path (ThunarVfsPath path, ThunarVfsThumbSize size);
bool thunar_vfs_thumbnail_is_valid (string thumbnail, string uri, 
                                    ThunarVfsFileTime mtime);
    \end{lstlisting}

    \begin{lstlisting}[caption=Example of a custom \ThunarVFS\ thumbnailer definition.,label=code:thunar-vfs-thumbnailer]
[Desktop Entry]
Version=1.0
Encoding=UTF-8
Type=X-Thumbnailer
Name=Ogg Thumbnailer
TryExec=ffmpegthumbnailer
MimeType=application/ogg;
X-Thumbnailer-Exec=/usr/libexec/ogg-thumbnailer %i %o %s     
    \end{lstlisting}
    
%    As a consequence of the migration away from \ThunarVFS, its thumbnailing code faces
%    the same situation as the job classes covered in the previous section. Three alternatives
%    could be considered reasonable approaches to deal with this. Like \code{ThunarVfsJob} and
%    \code{ThunarVfsSimpleJob}, \code{ThunarVfsThumbFactory} could be moved into \exo\ and 
%    thereby be made available to other applications inside \Xfce. This argument is important
%    since \ThunarVFS\ is also used outside \Thunar, which also makes the second alternative, 
%    moving the code into \Thunar\ itself, less realistic. There is also a third option which, 
%    in the following, is discussed in detail.
%
%    It was mentioned earlier that not only file manager require thumbnails to be generated.
%    Image viewers and desktop managers are other examples of applications that rely on this
%    feature. 

%    Creating thumbnails in a file manager is an expensive feature. Browsing large directories
%    tends to generate a high number of thumbnail requests, depending on the file types 
%    supported. To keep the user interface responsive while these requests are processed, 
%    thumbnails are usually created in the background using one or more worker threads.

    As a consequence of the migration away from \ThunarVFS, the thumbnailing code faces
    the same situation as the job classes covered in the previous section. There are several
    alternatives for dealing with this. Like \code{ThunarVfsJob} and \code{ThunarVfsSimpleJob},
    \code{ThunarVfsThumbFactory} could be moved into \exo, and thereby made available to
    other applications like image viewers or desktop managers. This argument is somewhat important
    and thus, makes second alternative, moving thumbnailing into the \Thunar\ source code itself,
    less realistic. 

    An approach very popular nowadays is to implement features required by multiple applications 
    as \DBus\ services, thus making them globally available and loadable on demand. A specification
    called the thumbnail management \DBus\ specification~\cite{thumbnailer-spec} was recently 
    drafted in an attempt to standardize the way thumbnails are generated across all desktop
    environments and applications. This specification not only defines the public interface for 
    separate \DBus\ services for generating and managing thumbnails as well as querying supported 
    MIME types. It also specifies how custom thumbnailer 
    scripts are installed in order to be recognized by these services. The specification has been 
    adopted by Nokia for their \Hildon\ application framework which is was the foundation of the 
    \Maemo\ platform for mobile devices until Nokia announced the move from GTK+ towards Qt, 
    another GUI framework popular for powering the \KDE\ desktop environment, in July~2009.

    An investigation of the details of the specification including discussions with its
    authors revealed that the specified services would generally be powerful enough to serve as a 
    replacement for the \ThunarVFS\ thumbnailing code. The most important \DBus\ interface
    it defines, \code{org.freedesktop.thumbnails.Thumbnailer}, shown in 
    listing~\ref{code:org.freedesktop.thumbnails.Thumbnailer}, provides methods for
    queuing (\code{Queue}) and cancelling (\code{Unqueue}) thumbnail request as well as signals 
    for when a request is started, finished or some URIs cannot be processed (\code{Error}). 
    There is also a signal to notify clients of successfully created thumbnails (\code{Ready}),
    thus leaving the decision how many \code{Ready} signals per request are emitted up to the
    service implementation. Overall, this API is even more flexible than \code{ThunarVfsThumbFactory}, 
    as it allows batch processing of thumbnails as an alternative to requesting thumbnails for 
    individual files.


    
%    It was also mentioned that Nokia 
%    might be interested in a community-driven implementation of the specification for the
%    \Maemo\ platform.

    The specification was written for album artwork and similar features on mobile devices in
    the beginning. As a file manager, \Thunar\ of course has very different requirements. High
    throughput is required for directories with a lot of files. As an inter-process communication 
    system, \DBus\ has performance drawbacks as messages sent between applications obviously are 
    not delivered as quickly as data passed between threads. Thus, the decision wether or not the 
    thumbnail management \DBus\ specification is applicable in the context of a file manager can 
    only be made based on testing. Notable delays and system lags would speak against an adoption 
    of the specification.

    \begin{lstlisting}[caption=\DBus\ interface definition for the thumbnailer service.,label=code:org.freedesktop.thumbnails.Thumbnailer]
<?xml version="1.0" encoding="UTF-8"?>
<node name="/org/freedesktop/thumbnails/Thumbnailer">
  <interface name="org.freedesktop.thumbnails.Thumbnailer">
    <method name="Queue">
      <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/>
      <arg type="as" name="uris" direction="in" />
      <arg type="as" name="mime_hints" direction="in" />
      <arg type="u" name="handle_to_unqueue" direction="in" />
      <arg type="u" name="handle" direction="out" />
    </method>

    <method name="Unqueue">
      <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/>
      <arg type="u" name="handle" direction="in" />
    </method>

    <signal name="Started">
      <arg type="u" name="handle" />
    </signal>

    <signal name="Finished">
      <arg type="u" name="handle" />
    </signal>

    <signal name="Ready">
      <arg type="as" name="uris" />
    </signal>

    <signal name="Error">
      <arg type="u" name="handle" />
      <arg type="as" name="failed_uris" />
      <arg type="i" name="error_code" />
      <arg type="s" name="message" />
    </signal>
  </interface>
</node>
    \end{lstlisting}

    Fortunately, a centralized \DBus\ service also has certain advantages. \DBus\ generally 
    induces a loose coupling among different applications and libraries. While the interface
    is standardized, implementations may change without the applications noticing. Memory 
    usage can be reduced as information about custom (or specialized) thumbnailer scripts is only 
    stored in memory once. A centralized service also allows for fine-tuning and the employment 
    of clever scheduling algorithms for a higher throughput.

    Along with the migration of \Thunar\ to \GIO, an implementation of this specification
    was implemented and later integrated into \Thunar. Like \Thunar, it is written in C
    based on \GObject. Inspired by \Hildon's \hildonthumbnail, it takes the concept one
    step further by being designed in a more object-oriented fashion, supporting different 
    schedulers as well as plugins in addition to the specialized \DBus\ thumbnailers defined 
    in the specification. It also adds an abstraction layer to the thumbnail cache so that
    in theory, thumbnails could be stored deviating from the thumbnail managing 
    standard~\cite{thumbnail-spec}, without affecting applications. Different thumbnail
    caches and specialized thumbnailers can be implemented as plugins, although the preferred
    way for thumbnailers to be written in adherence of the thumbnail management 
    \DBus\ specification. 

    \begin{lstlisting}[caption=Example thumbnailer client written in Vala.,label=code:thumbnailer-client]
using GLib; using DBus;

public class ThumbnailerClient : GLib.Object {
  private DBus.Connection connection;
  private dynamic DBus.Object proxy;

  public ThumbnailerClient() {
    connection = DBus.Bus.get (DBus.BusType.SESSION);
    proxy = connection.get_object ("org.freedesktop.thumbnails.Thumbnailer",
                                   "/org/freedesktop/thumbnails/Thumbnailer",
                                   "org.freedesktop.thumbnails.Thumbnailer");
    proxy.Started += started;
    proxy.Finished += finished;
    proxy.Ready += ready;
    proxy.Error += error;
  }

  private void started (dynamic DBus.Object proxy, uint32 handle) {
    stdout.printf ("signal received: Started (handle=%ld)\n", handle);
  }

  private void finished (dynamic DBus.Object proxy, uint32 handle) {
    stdout.printf ("signal received: Finished (handle=%ld)\n", handle);
  }

  private void ready (dynamic DBus.Object proxy, string[] uris) {
    stdout.printf ("signal received: Ready (uris[0]=%s)\n", uris[0]);
  }

  private void error (dynamic DBus.Object proxy, uint32 handle,
                      string[] failed_uris, int32 code, string msg)
  {
    stdout.printf ("Signal: Error (handle=%ld, failed_uris[0]=%s, code=%d, "
                   "msg=%s)\n", handle, failed_uris[0], code, msg);
  }

  public void run () {
    uint32 handle;

    proxy.Queue(new string[] { "file:///tmp/0016.png" },
                new string[] { "image/png" }, (uint32) 0, out handle);
    stdout.printf ("request queued: handle=%ld\n", handle);

    proxy.Queue(new string[] { "file:///tmp/idontexist.png" },
                new string[] { "image/png" }, (uint32) 0, out handle);
    stdout.printf ("request queued: handle=%ld\n", handle);

    proxy.Queue(new string[] { "file:///tmp/0016.png" },
                new string[] { "invalid/mime-type" }, (uint32) 0, out handle);
    stdout.printf ("request queued: handle=%ld\n", handle);
  }

  public static int main (string[] args) {
    var loop = new MainLoop (null, false);
    var client = new ThumbnailerClient ();
    client.run ();
    loop.run ();
    return 0;
  }
}
    \end{lstlisting}

    \begin{lstlisting}[caption=Output of the example thumbnailer client.,label=code:thumbnailer-client-output]
request queued: handle=52
request queued: handle=53
request queued: handle=54
signal received: Started (handle=52)
signal received: Ready (uris[0]=file:///tmp/0016.png)
signal received: Finished (handle=52)
signal received: Started (handle=53)
signal received: Error (handle=53, failed_uris[0]=file:///tmp/idontexist.png,
  code=1, msg=Error stating file '/tmp/idontexist.png': No such file or directory)
signal received: Finished (handle=53)
signal received: Started (handle=54)
signal received: Error (handle=54, failed_uris[0]=file:///tmp/0016.png,
  code=1, msg=No thumbnailer available for 'file:///tmp/0016.png')
signal received: Finished (handle=54)
    \end{lstlisting}

    The name of this implementation is \textit{Tumbler}. Taken from the tank-like
    Batmobile appearing in Christopher Nolan's Batman movies, it coincidentally derives all its
    seven letters from the word "thumbnailer" in exactly the same order they appear in it.


  \section{Special Requirements for Network Browsing}\label{sec:network-browsing-requirements}

\chapter{Summary and Evaluation}\label{chapter:evaluation}

  As described in section \ref{sec:thunar-vfs-gio-comparison}, there are quite a 
  number of differences in \ThunarVFS\ and \GIO. This has both positive and negative
  implications. Certainly the most enjoyable aspect is that \GIO\ brings a lot of
  new features which are described in section \ref{sec:new-features}. Unfortunately,
  \GIO\ is less powerful in some areas. Regressions resulting from the migration
  are analyzed in section \ref{sec:regressions}. Section \ref{sec:consequences}
  explains the consequences the migration has for applications which depend
  on Thunar as a desktop service.

  \section{Benefit and New Features}\label{sec:new-features}

  \section{List of Regressions}\label{sec:regressions}

  \section{Consequences for Other Applications}\label{sec:consequences}

\chapter{Outlook}\label{chapter:outlook}

  \section{Additional Thumbnailers}

  \section{Volume Management Without GVfs}

  \section{User Interface Improvements for Network Browsing}

\bibliography{literature}

\end{document}
