diff options
author | Milan Crha <mcrha@redhat.com> | 2015-08-13 11:20:59 +0200 |
---|---|---|
committer | Milan Crha <mcrha@redhat.com> | 2015-08-13 11:20:59 +0200 |
commit | 6668200ca90db865ca610037e4a9aa1e81d46787 (patch) | |
tree | 6f5662085a56a4abef8a4366f2cbd76092e8e4c2 /modules | |
parent | e9f93a44cf6bb3c5ffb788d52640e7360fc8e811 (diff) | |
download | evolution-data-server-6668200ca90db865ca610037e4a9aa1e81d46787.tar.gz |
Bug 752197 - Teach cache-reaper of 3rd-party private directories ][
Make the ECacheReaper more public accessible, thus the modules can
link to it easily.
Diffstat (limited to 'modules')
-rw-r--r-- | modules/cache-reaper/Makefile.am | 6 | ||||
-rw-r--r-- | modules/cache-reaper/e-cache-reaper-utils.c | 207 | ||||
-rw-r--r-- | modules/cache-reaper/e-cache-reaper-utils.h | 42 | ||||
-rw-r--r-- | modules/cache-reaper/e-cache-reaper.h | 47 | ||||
-rw-r--r-- | modules/cache-reaper/module-cache-reaper.c | 702 |
5 files changed, 4 insertions, 1000 deletions
diff --git a/modules/cache-reaper/Makefile.am b/modules/cache-reaper/Makefile.am index 1fdc10ede..8af088da5 100644 --- a/modules/cache-reaper/Makefile.am +++ b/modules/cache-reaper/Makefile.am @@ -12,8 +12,6 @@ module_cache_reaper_la_CPPFLAGS = \ module_cache_reaper_la_SOURCES = \ module-cache-reaper.c \ - e-cache-reaper-utils.c \ - e-cache-reaper-utils.h \ $(NULL) module_cache_reaper_la_LIBADD = \ @@ -27,8 +25,4 @@ module_cache_reaper_la_LDFLAGS = \ -module -avoid-version $(NO_UNDEFINED) \ $(NULL) -cachereaperincludedir = $(privincludedir)/cache-reaper - -cachereaperinclude_HEADERS = e-cache-reaper.h - -include $(top_srcdir)/git.mk diff --git a/modules/cache-reaper/e-cache-reaper-utils.c b/modules/cache-reaper/e-cache-reaper-utils.c deleted file mode 100644 index 954d7d1d9..000000000 --- a/modules/cache-reaper/e-cache-reaper-utils.c +++ /dev/null @@ -1,207 +0,0 @@ -/* - * e-cache-reaper-utils.c - * - * This library is free software: you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library. If not, see <http://www.gnu.org/licenses/>. - * - */ - -#include "e-cache-reaper-utils.h" - -#include <libedataserver/libedataserver.h> - -#define REAPING_DIRECTORY_NAME ".reaping" - -/* Helper for e_reap_trash_directory() */ -static void -reap_trash_directory_thread (GSimpleAsyncResult *simple, - GObject *object, - GCancellable *cancellable) -{ - gssize expiry_in_days; - GError *error = NULL; - - expiry_in_days = g_simple_async_result_get_op_res_gssize (simple); - - e_reap_trash_directory_sync ( - G_FILE (object), - (gint) expiry_in_days, - cancellable, &error); - - if (error != NULL) - g_simple_async_result_take_error (simple, error); -} - -gboolean -e_reap_trash_directory_sync (GFile *trash_directory, - gint expiry_in_days, - GCancellable *cancellable, - GError **error) -{ - GFileEnumerator *file_enumerator; - GQueue directories = G_QUEUE_INIT; - GFile *reaping_directory; - GFileInfo *file_info; - const gchar *attributes; - gboolean success = TRUE; - GError *local_error = NULL; - - g_return_val_if_fail (G_IS_FILE (trash_directory), FALSE); - g_return_val_if_fail (expiry_in_days > 0, FALSE); - - reaping_directory = g_file_get_child ( - trash_directory, REAPING_DIRECTORY_NAME); - - attributes = - G_FILE_ATTRIBUTE_STANDARD_NAME "," - G_FILE_ATTRIBUTE_STANDARD_TYPE "," - G_FILE_ATTRIBUTE_TIME_MODIFIED; - - file_enumerator = g_file_enumerate_children ( - trash_directory, attributes, - G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - cancellable, error); - - if (file_enumerator == NULL) - return FALSE; - - file_info = g_file_enumerator_next_file ( - file_enumerator, cancellable, &local_error); - - while (file_info != NULL) { - GFileType file_type; - GTimeVal mtime; - GDate *date_now; - GDate *date_mtime; - const gchar *name; - gboolean reap_it; - gint days_old; - - name = g_file_info_get_name (file_info); - file_type = g_file_info_get_file_type (file_info); - g_file_info_get_modification_time (file_info, &mtime); - - /* Calculate how many days ago the file was modified. */ - date_now = g_date_new (); - g_date_set_time_t (date_now, time (NULL)); - date_mtime = g_date_new (); - g_date_set_time_val (date_mtime, &mtime); - days_old = g_date_days_between (date_mtime, date_now); - g_date_free (date_mtime); - g_date_free (date_now); - - reap_it = - (file_type == G_FILE_TYPE_DIRECTORY) && - (days_old >= expiry_in_days); - - if (reap_it) { - GFile *child; - - child = g_file_get_child (trash_directory, name); - - /* If we find an unfinished reaping directory, put - * it on the head of the queue so we reap it first. */ - if (g_file_equal (child, reaping_directory)) - g_queue_push_head (&directories, child); - else - g_queue_push_tail (&directories, child); - } - - g_object_unref (file_info); - - file_info = g_file_enumerator_next_file ( - file_enumerator, cancellable, &local_error); - } - - if (local_error != NULL) { - g_propagate_error (error, local_error); - success = FALSE; - } - - g_object_unref (file_enumerator); - - /* Now delete the directories we've queued up. */ - while (success && !g_queue_is_empty (&directories)) { - GFile *directory; - - directory = g_queue_pop_head (&directories); - - /* First we rename the directory to prevent it - * from being recovered while being deleted. */ - if (!g_file_equal (directory, reaping_directory)) - success = g_file_move ( - directory, reaping_directory, - G_FILE_COPY_NONE, cancellable, - NULL, NULL, error); - - if (success) - success = e_file_recursive_delete_sync ( - reaping_directory, cancellable, error); - - g_object_unref (directory); - } - - /* Flush the queue in case we aborted on an error. */ - while (!g_queue_is_empty (&directories)) - g_object_unref (g_queue_pop_head (&directories)); - - g_object_unref (reaping_directory); - - return success; -} - -void -e_reap_trash_directory (GFile *trash_directory, - gint expiry_in_days, - gint io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GSimpleAsyncResult *simple; - - g_return_if_fail (G_IS_FILE (trash_directory)); - g_return_if_fail (expiry_in_days > 0); - - simple = g_simple_async_result_new ( - G_OBJECT (trash_directory), callback, - user_data, e_reap_trash_directory); - - g_simple_async_result_set_check_cancellable (simple, cancellable); - - g_simple_async_result_set_op_res_gssize (simple, expiry_in_days); - - g_simple_async_result_run_in_thread ( - simple, reap_trash_directory_thread, - io_priority, cancellable); - - g_object_unref (simple); -} - -gboolean -e_reap_trash_directory_finish (GFile *trash_directory, - GAsyncResult *result, - GError **error) -{ - GSimpleAsyncResult *simple; - - g_return_val_if_fail ( - g_simple_async_result_is_valid ( - result, G_OBJECT (trash_directory), - e_reap_trash_directory), FALSE); - - simple = G_SIMPLE_ASYNC_RESULT (result); - - /* Assume success unless a GError is set. */ - return !g_simple_async_result_propagate_error (simple, error); -} - diff --git a/modules/cache-reaper/e-cache-reaper-utils.h b/modules/cache-reaper/e-cache-reaper-utils.h deleted file mode 100644 index 01ca3691b..000000000 --- a/modules/cache-reaper/e-cache-reaper-utils.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * e-cache-reaper-utils.h - * - * This library is free software: you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library. If not, see <http://www.gnu.org/licenses/>. - * - */ - -#ifndef E_CACHE_REAPER_UTILS_H -#define E_CACHE_REAPER_UTILS_H - -#include <gio/gio.h> - -G_BEGIN_DECLS - -gboolean e_reap_trash_directory_sync (GFile *trash_directory, - gint expiry_in_days, - GCancellable *cancellable, - GError **error); -void e_reap_trash_directory (GFile *trash_directory, - gint expiry_in_days, - gint io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean e_reap_trash_directory_finish (GFile *trash_directory, - GAsyncResult *result, - GError **error); - -G_END_DECLS - -#endif /* E_CACHE_REAPER_UTILS_H */ - diff --git a/modules/cache-reaper/e-cache-reaper.h b/modules/cache-reaper/e-cache-reaper.h deleted file mode 100644 index 3177bda89..000000000 --- a/modules/cache-reaper/e-cache-reaper.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * e-cache-reaper.h - * - * This library is free software: you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library. If not, see <http://www.gnu.org/licenses/>. - * - */ - -#ifndef E_CACHE_REAPER_H -#define E_CACHE_REAPER_H - -#include <libedataserver/libedataserver.h> - -/* Standard GObject macros */ -#define E_TYPE_CACHE_REAPER \ - (e_cache_reaper_get_type ()) -#define E_CACHE_REAPER(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST \ - ((obj), E_TYPE_CACHE_REAPER, ECacheReaper)) -#define E_IS_CACHE_REAPER(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE \ - ((obj), E_TYPE_CACHE_REAPER)) - -G_BEGIN_DECLS - -typedef struct _ECacheReaper ECacheReaper; -typedef struct _ECacheReaperClass ECacheReaperClass; - -GType e_cache_reaper_get_type (void); - -void e_cache_reaper_add_private_directory (ECacheReaper *cache_reaper, - const gchar *name); -void e_cache_reaper_remove_private_directory (ECacheReaper *cache_reaper, - const gchar *name); - -G_END_DECLS - -#endif /* E_CACHE_REAPER_H */ diff --git a/modules/cache-reaper/module-cache-reaper.c b/modules/cache-reaper/module-cache-reaper.c index a6ef49a4a..2d15b50f5 100644 --- a/modules/cache-reaper/module-cache-reaper.c +++ b/modules/cache-reaper/module-cache-reaper.c @@ -15,714 +15,20 @@ * */ -#include <errno.h> -#include <time.h> -#include <glib/gstdio.h> +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif #include <libebackend/libebackend.h> -#include "e-cache-reaper.h" -#include "e-cache-reaper-utils.h" - -/* Where abandoned directories go to die. */ -#define TRASH_DIRECTORY_NAME "trash" - -/* XXX These intervals are rather arbitrary and prone to bikeshedding. - * It's just what I decided on. On startup we wait an hour to reap - * abandoned directories, and thereafter repeat every 24 hours. */ -#define INITIAL_INTERVAL_SECONDS ( 1 * (60 * 60)) -#define REGULAR_INTERVAL_SECONDS (24 * (60 * 60)) - -/* XXX Similarly, these expiry times are rather arbitrary and prone to - * bikeshedding. Most importantly, the expiry for data directories - * should be far more conservative (longer) than cache directories. - * Cache directories are disposable, data directories are not, so - * we want to let abandoned data directories linger longer. */ - -/* Minimum days for a data directory - * to live in trash before reaping it. */ -#define DATA_EXPIRY_IN_DAYS 28 - -/* Minimum days for a cache directory - * to live in trash before reaping it. */ -#define CACHE_EXPIRY_IN_DAYS 7 - -struct _ECacheReaper { - EExtension parent; - - guint n_data_directories; - GFile **data_directories; - GFile **data_trash_directories; - - guint n_cache_directories; - GFile **cache_directories; - GFile **cache_trash_directories; - - guint reaping_timeout_id; - - GSList *private_directories; -}; - -struct _ECacheReaperClass { - EExtensionClass parent_class; -}; - /* Module Entry Points */ void e_module_load (GTypeModule *type_module); void e_module_unload (GTypeModule *type_module); -G_DEFINE_DYNAMIC_TYPE_EXTENDED (ECacheReaper, e_cache_reaper, E_TYPE_EXTENSION, 0, - G_IMPLEMENT_INTERFACE_DYNAMIC (E_TYPE_EXTENSIBLE, NULL)) - -static ESourceRegistryServer * -cache_reaper_get_server (ECacheReaper *extension) -{ - EExtensible *extensible; - - extensible = e_extension_get_extensible (E_EXTENSION (extension)); - - return E_SOURCE_REGISTRY_SERVER (extensible); -} - -static gboolean -cache_reaper_make_directory_and_parents (GFile *directory, - GCancellable *cancellable, - GError **error) -{ - gboolean success; - GError *local_error = NULL; - - /* XXX Maybe add some function like this to libedataserver. - * It's annoying to always have to check for and clear - * G_IO_ERROR_EXISTS when ensuring a directory exists. */ - - success = g_file_make_directory_with_parents ( - directory, cancellable, &local_error); - - if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_EXISTS)) - g_clear_error (&local_error); - - if (local_error != NULL) { - gchar *path; - - g_propagate_error (error, local_error); - - path = g_file_get_path (directory); - g_prefix_error ( - error, "Failed to make directory '%s': ", path); - g_free (path); - } - - return success; -} - -static void -cache_reaper_trash_directory_reaped (GObject *source_object, - GAsyncResult *result, - gpointer unused) -{ - GFile *trash_directory; - GError *error = NULL; - - trash_directory = G_FILE (source_object); - - e_reap_trash_directory_finish (trash_directory, result, &error); - - /* Ignore cancellations. */ - if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { - /* do nothing */ - - } else if (error != NULL) { - gchar *path; - - path = g_file_get_path (trash_directory); - g_warning ("Failed to reap '%s': %s", path, error->message); - g_free (path); - } - - g_clear_error (&error); -} - -static gboolean -cache_reaper_reap_trash_directories (gpointer user_data) -{ - ECacheReaper *extension = E_CACHE_REAPER (user_data); - guint ii; - - g_debug ("Reaping abandoned data directories"); - - for (ii = 0; ii < extension->n_data_directories; ii++) - e_reap_trash_directory ( - extension->data_trash_directories[ii], - DATA_EXPIRY_IN_DAYS, - G_PRIORITY_LOW, NULL, - cache_reaper_trash_directory_reaped, - NULL); - - g_debug ("Reaping abandoned cache directories"); - - for (ii = 0; ii < extension->n_cache_directories; ii++) - e_reap_trash_directory ( - extension->cache_trash_directories[ii], - CACHE_EXPIRY_IN_DAYS, - G_PRIORITY_LOW, NULL, - cache_reaper_trash_directory_reaped, - NULL); - - /* Always explicitly reschedule since the initial - * interval is different than the regular interval. */ - extension->reaping_timeout_id = - e_named_timeout_add_seconds ( - REGULAR_INTERVAL_SECONDS, - cache_reaper_reap_trash_directories, - extension); - - return FALSE; -} - -static void -cache_reaper_move_directory (GFile *source_directory, - GFile *target_directory) -{ - GFileType file_type; - GError *error = NULL; - - /* Make sure the source directory is really a directory. */ - - file_type = g_file_query_file_type ( - source_directory, - G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL); - - if (file_type == G_FILE_TYPE_DIRECTORY) { - g_file_move ( - source_directory, - target_directory, - G_FILE_COPY_NOFOLLOW_SYMLINKS, - NULL, NULL, NULL, &error); - - /* Update the target directory's modification time. - * This step is not critical, do not set the GError. */ - if (error == NULL) { - time_t now = time (NULL); - - g_file_set_attribute ( - target_directory, - G_FILE_ATTRIBUTE_TIME_MODIFIED, - G_FILE_ATTRIBUTE_TYPE_UINT64, - &now, G_FILE_QUERY_INFO_NONE, - NULL, NULL); - } - } - - if (error != NULL) { - gchar *path; - - path = g_file_get_path (source_directory); - g_warning ("Failed to move '%s': %s", path, error->message); - g_free (path); - - g_error_free (error); - } -} - -static gboolean -cache_reaper_skip_directory (ECacheReaper *cache_reaper, - const gchar *name) -{ - GSList *link; - - /* Skip the trash directory, obviously. */ - if (g_strcmp0 (name, TRASH_DIRECTORY_NAME) == 0) - return TRUE; - - /* Also skip directories named "system". For backward - * compatibility, data directories for built-in sources - * are named "system" instead of "system-address-book" - * or "system-calendar" or what have you. */ - if (g_strcmp0 (name, "system") == 0) - return TRUE; - - for (link = cache_reaper->private_directories; link; link = g_slist_next (link)) { - if (g_strcmp0 (name, link->data) == 0) { - return TRUE; - } - } - - return FALSE; -} - -static void -cache_reaper_scan_directory (ECacheReaper *extension, - GFile *base_directory, - GFile *trash_directory) -{ - GFileEnumerator *file_enumerator; - ESourceRegistryServer *server; - GFileInfo *file_info; - GError *error = NULL; - - server = cache_reaper_get_server (extension); - - file_enumerator = g_file_enumerate_children ( - base_directory, - G_FILE_ATTRIBUTE_STANDARD_NAME, - G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - NULL, &error); - - if (error != NULL) { - g_warn_if_fail (file_enumerator == NULL); - goto exit; - } - - g_return_if_fail (G_IS_FILE_ENUMERATOR (file_enumerator)); - - file_info = g_file_enumerator_next_file ( - file_enumerator, NULL, &error); - - while (file_info != NULL) { - ESource *source; - const gchar *name; - - name = g_file_info_get_name (file_info); - - if (cache_reaper_skip_directory (extension, name)) - goto next; - - source = e_source_registry_server_ref_source (server, name); - - if (source == NULL) { - GFile *source_directory; - GFile *target_directory; - - source_directory = g_file_get_child ( - base_directory, name); - target_directory = g_file_get_child ( - trash_directory, name); - - cache_reaper_move_directory ( - source_directory, target_directory); - - g_object_unref (source_directory); - g_object_unref (target_directory); - } else { - g_object_unref (source); - } - -next: - g_object_unref (file_info); - - file_info = g_file_enumerator_next_file ( - file_enumerator, NULL, &error); - } - - g_object_unref (file_enumerator); - -exit: - if (error != NULL) { - gchar *path; - - path = g_file_get_path (base_directory); - g_warning ("Failed to scan '%s': %s", path, error->message); - g_free (path); - - g_error_free (error); - } -} - -static void -cache_reaper_scan_data_directories (ECacheReaper *extension) -{ - guint ii; - - /* Scan the base data directories for unrecognized subdirectories. - * The subdirectories are named after data source UIDs, so compare - * their names to registered data sources and move any unrecognized - * subdirectories to the "trash" subdirectory to be reaped later. */ - - g_debug ("Scanning data directories"); - - for (ii = 0; ii < extension->n_data_directories; ii++) - cache_reaper_scan_directory ( - extension, - extension->data_directories[ii], - extension->data_trash_directories[ii]); -} - -static void -cache_reaper_scan_cache_directories (ECacheReaper *extension) -{ - guint ii; - - /* Scan the base cache directories for unrecognized subdirectories. - * The subdirectories are named after data source UIDs, so compare - * their names to registered data sources and move any unrecognized - * subdirectories to the "trash" subdirectory to be reaped later. */ - - g_debug ("Scanning cache directories"); - - for (ii = 0; ii < extension->n_cache_directories; ii++) - cache_reaper_scan_directory ( - extension, - extension->cache_directories[ii], - extension->cache_trash_directories[ii]); -} - -static void -cache_reaper_move_to_trash (ECacheReaper *extension, - ESource *source, - GFile *base_directory, - GFile *trash_directory) -{ - GFile *source_directory; - GFile *target_directory; - const gchar *uid; - - uid = e_source_get_uid (source); - - source_directory = g_file_get_child (base_directory, uid); - target_directory = g_file_get_child (trash_directory, uid); - - /* This is a no-op if the source directory does not exist. */ - cache_reaper_move_directory (source_directory, target_directory); - - g_object_unref (source_directory); - g_object_unref (target_directory); -} - -static void -cache_reaper_recover_from_trash (ECacheReaper *extension, - ESource *source, - GFile *base_directory, - GFile *trash_directory) -{ - GFile *source_directory; - GFile *target_directory; - const gchar *uid; - - uid = e_source_get_uid (source); - - source_directory = g_file_get_child (trash_directory, uid); - target_directory = g_file_get_child (base_directory, uid); - - /* This is a no-op if the source directory does not exist. */ - cache_reaper_move_directory (source_directory, target_directory); - - g_object_unref (source_directory); - g_object_unref (target_directory); -} - -static void -cache_reaper_files_loaded_cb (ESourceRegistryServer *server, - ECacheReaper *extension) -{ - cache_reaper_scan_data_directories (extension); - cache_reaper_scan_cache_directories (extension); - - /* Schedule the initial reaping. */ - if (extension->reaping_timeout_id == 0) { - extension->reaping_timeout_id = - e_named_timeout_add_seconds ( - INITIAL_INTERVAL_SECONDS, - cache_reaper_reap_trash_directories, - extension); - } -} - -static void -cache_reaper_source_added_cb (ESourceRegistryServer *server, - ESource *source, - ECacheReaper *extension) -{ - guint ii; - - /* The Cache Reaper is not too proud to dig through the - * trash on the off chance the newly-added source has a - * recoverable data or cache directory. */ - - for (ii = 0; ii < extension->n_data_directories; ii++) - cache_reaper_recover_from_trash ( - extension, source, - extension->data_directories[ii], - extension->data_trash_directories[ii]); - - for (ii = 0; ii < extension->n_cache_directories; ii++) - cache_reaper_recover_from_trash ( - extension, source, - extension->cache_directories[ii], - extension->cache_trash_directories[ii]); -} - -static void -cache_reaper_source_removed_cb (ESourceRegistryServer *server, - ESource *source, - ECacheReaper *extension) -{ - guint ii; - - /* Stage the removed source's cache directory for reaping - * by moving it to the "trash" directory. - * - * Do NOT do this for data directories. Cache directories - * are disposable and can be regenerated from the canonical - * data source, but data directories ARE the canonical data - * source so we want to be more conservative with them. If - * the removed source has a data directory, we will move it - * to the "trash" directory on next registry startup, which - * may correspond with the next desktop session startup. */ - - for (ii = 0; ii < extension->n_cache_directories; ii++) - cache_reaper_move_to_trash ( - extension, source, - extension->cache_directories[ii], - extension->cache_trash_directories[ii]); -} - -static void -cache_reaper_finalize (GObject *object) -{ - ECacheReaper *extension; - guint ii; - - extension = E_CACHE_REAPER (object); - - for (ii = 0; ii < extension->n_data_directories; ii++) { - g_object_unref (extension->data_directories[ii]); - g_object_unref (extension->data_trash_directories[ii]); - } - - g_free (extension->data_directories); - g_free (extension->data_trash_directories); - - for (ii = 0; ii < extension->n_cache_directories; ii++) { - g_object_unref (extension->cache_directories[ii]); - g_object_unref (extension->cache_trash_directories[ii]); - } - - g_free (extension->cache_directories); - g_free (extension->cache_trash_directories); - - if (extension->reaping_timeout_id > 0) - g_source_remove (extension->reaping_timeout_id); - - g_slist_free_full (extension->private_directories, g_free); - extension->private_directories = NULL; - - /* Chain up to parent's finalize() method. */ - G_OBJECT_CLASS (e_cache_reaper_parent_class)->finalize (object); -} - -static void -cache_reaper_constructed (GObject *object) -{ - EExtension *extension; - EExtensible *extensible; - - extension = E_EXTENSION (object); - extensible = e_extension_get_extensible (extension); - - g_signal_connect ( - extensible, "files-loaded", - G_CALLBACK (cache_reaper_files_loaded_cb), extension); - - g_signal_connect ( - extensible, "source-added", - G_CALLBACK (cache_reaper_source_added_cb), extension); - - g_signal_connect ( - extensible, "source-removed", - G_CALLBACK (cache_reaper_source_removed_cb), extension); - - e_extensible_load_extensions (E_EXTENSIBLE (object)); - - /* Chain up to parent's constructed() method. */ - G_OBJECT_CLASS (e_cache_reaper_parent_class)->constructed (object); -} - -static void -e_cache_reaper_class_init (ECacheReaperClass *class) -{ - GObjectClass *object_class; - EExtensionClass *extension_class; - - object_class = G_OBJECT_CLASS (class); - object_class->finalize = cache_reaper_finalize; - object_class->constructed = cache_reaper_constructed; - - extension_class = E_EXTENSION_CLASS (class); - extension_class->extensible_type = E_TYPE_SOURCE_REGISTRY_SERVER; -} - -static void -e_cache_reaper_class_finalize (ECacheReaperClass *class) -{ -} - -static void -e_cache_reaper_init (ECacheReaper *extension) -{ - GFile *base_directory; - const gchar *user_data_dir; - const gchar *user_cache_dir; - guint n_directories, ii; - - /* These are component names from which - * the data directory arrays are built. */ - const gchar *data_component_names[] = { - "addressbook", - "calendar", - "mail", - "memos", - "tasks" - }; - - /* These are component names from which - * the cache directory arrays are built. */ - const gchar *cache_component_names[] = { - "addressbook", - "calendar", - "mail", - "memos", - "sources", - "tasks" - }; - - extension->private_directories = NULL; - - /* Setup base directories for data. */ - - n_directories = G_N_ELEMENTS (data_component_names); - - extension->n_data_directories = n_directories; - extension->data_directories = g_new0 (GFile *, n_directories); - extension->data_trash_directories = g_new0 (GFile *, n_directories); - - user_data_dir = e_get_user_data_dir (); - base_directory = g_file_new_for_path (user_data_dir); - - for (ii = 0; ii < n_directories; ii++) { - GFile *data_directory; - GFile *trash_directory; - GError *error = NULL; - - data_directory = g_file_get_child ( - base_directory, data_component_names[ii]); - trash_directory = g_file_get_child ( - data_directory, TRASH_DIRECTORY_NAME); - - /* Data directory is a parent of the trash - * directory so this is sufficient for both. */ - cache_reaper_make_directory_and_parents ( - trash_directory, NULL, &error); - - if (error != NULL) { - g_warning ("%s: %s", G_STRFUNC, error->message); - g_error_free (error); - } - - extension->data_directories[ii] = data_directory; - extension->data_trash_directories[ii] = trash_directory; - } - - g_object_unref (base_directory); - - /* Setup base directories for cache. */ - - n_directories = G_N_ELEMENTS (cache_component_names); - - extension->n_cache_directories = n_directories; - extension->cache_directories = g_new0 (GFile *, n_directories); - extension->cache_trash_directories = g_new0 (GFile *, n_directories); - - user_cache_dir = e_get_user_cache_dir (); - base_directory = g_file_new_for_path (user_cache_dir); - - for (ii = 0; ii < n_directories; ii++) { - GFile *cache_directory; - GFile *trash_directory; - GError *error = NULL; - - cache_directory = g_file_get_child ( - base_directory, cache_component_names[ii]); - trash_directory = g_file_get_child ( - cache_directory, TRASH_DIRECTORY_NAME); - - /* Cache directory is a parent of the trash - * directory so this is sufficient for both. */ - cache_reaper_make_directory_and_parents ( - trash_directory, NULL, &error); - - if (error != NULL) { - g_warning ("%s: %s", G_STRFUNC, error->message); - g_error_free (error); - } - - extension->cache_directories[ii] = cache_directory; - extension->cache_trash_directories[ii] = trash_directory; - } - - g_object_unref (base_directory); -} - -/** - * e_cache_reaper_add_private_directory: - * @cache_reaper: an #ECacheReaper - * @name: directory name - * - * Let's the @cache_reaper know about a private directory named @name, - * thus it won't delete it from cache or data directories. The @name - * is just a directory name, not a path. - * - * Since 3.18 - **/ -void -e_cache_reaper_add_private_directory (ECacheReaper *cache_reaper, - const gchar *name) -{ - g_return_if_fail (E_IS_CACHE_REAPER (cache_reaper)); - g_return_if_fail (name != NULL); - - if (g_slist_find_custom (cache_reaper->private_directories, name, (GCompareFunc) g_strcmp0)) - return; - - cache_reaper->private_directories = g_slist_prepend (cache_reaper->private_directories, g_strdup (name)); -} - -/** - * e_cache_reaper_remove_private_directory: - * @cache_reaper: an #ECacheReaper - * @name: directory name - * - * Remove private directory named @name from the list of private - * directories in the @cache_reaper, previously added with - * e_cache_reaper_add_private_directory(). - * - * Since 3.18 - **/ -void -e_cache_reaper_remove_private_directory (ECacheReaper *cache_reaper, - const gchar *name) -{ - GSList *link; - gchar *saved_name; - - g_return_if_fail (E_IS_CACHE_REAPER (cache_reaper)); - g_return_if_fail (name != NULL); - - link = g_slist_find_custom (cache_reaper->private_directories, name, (GCompareFunc) g_strcmp0); - if (!link) - return; - - saved_name = link->data; - - cache_reaper->private_directories = g_slist_remove (cache_reaper->private_directories, saved_name); - - g_free (saved_name); -} - G_MODULE_EXPORT void e_module_load (GTypeModule *type_module) { - e_cache_reaper_register_type (type_module); + e_cache_reaper_type_register (type_module); } G_MODULE_EXPORT void |