[evolution-data-server] Bug 595389 - Auto-vacuum Camel DB on expunge
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server] Bug 595389 - Auto-vacuum Camel DB on expunge
- Date: Wed, 3 Dec 2014 08:14:00 +0000 (UTC)
commit 00054cea4b6c3b5e8a05b5c03c8011bd54760cdd
Author: Milan Crha <mcrha redhat com>
Date: Wed Dec 3 09:10:59 2014 +0100
Bug 595389 - Auto-vacuum Camel DB on expunge
camel/camel-db.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++
camel/camel-db.h | 2 +
camel/camel-folder.c | 13 +++++++++++
camel/camel-store.c | 38 ++++++++++++++++++++++++++++++++++
camel/camel-store.h | 3 ++
5 files changed, 111 insertions(+), 0 deletions(-)
---
diff --git a/camel/camel-db.c b/camel/camel-db.c
index 7dfea0a..17edffc 100644
--- a/camel/camel-db.c
+++ b/camel/camel-db.c
@@ -2704,3 +2704,58 @@ camel_db_get_column_ident (GHashTable **hash,
return GPOINTER_TO_INT (value);
}
+
+static gint
+get_number_cb (gpointer data,
+ gint argc,
+ gchar **argv,
+ gchar **azColName)
+{
+ guint64 *pui64 = data;
+
+ if (argc == 1) {
+ *pui64 = argv[0] ? g_ascii_strtoull (argv[0], NULL, 10) : 0;
+ } else {
+ *pui64 = 0;
+ }
+
+ return 0;
+}
+
+/**
+ * camel_db_maybe_run_maintenance:
+ * @cdb: a #CamelDB instance
+ * @error: (allow none): a #GError or %NULL
+ *
+ * Runs a @cdb maintenance, which includes vacuum, if necessary.
+ *
+ * Returns: Whether succeeded.
+ *
+ * Since: 3.14
+ **/
+gboolean
+camel_db_maybe_run_maintenance (CamelDB *cdb,
+ GError **error)
+{
+ GError *local_error = NULL;
+ guint64 page_count = 0, freelist_count = 0;
+ gboolean success = FALSE;
+
+ g_return_val_if_fail (cdb != NULL, FALSE);
+
+ cdb_writer_lock (cdb);
+
+ if (cdb_sql_exec (cdb->db, "PRAGMA page_count;", get_number_cb, &page_count, &local_error) ==
SQLITE_OK &&
+ cdb_sql_exec (cdb->db, "PRAGMA freelist_count;", get_number_cb, &freelist_count, &local_error) ==
SQLITE_OK) {
+ /* Vacuum, if there's more than 5% of the free pages */
+ success = !page_count || !freelist_count || (freelist_count * 1000 / page_count > 50 &&
+ cdb_sql_exec (cdb->db, "vacuum;", NULL, NULL, &local_error) == SQLITE_OK);
+ }
+
+ cdb_writer_unlock (cdb);
+
+ if (local_error)
+ g_propagate_error (error, local_error);
+
+ return success;
+}
diff --git a/camel/camel-db.h b/camel/camel-db.h
index 4495ba4..ec5e2ea 100644
--- a/camel/camel-db.h
+++ b/camel/camel-db.h
@@ -339,6 +339,8 @@ gint camel_db_write_preview_record (CamelDB *db, const gchar *folder_name, const
gint
camel_db_reset_folder_version (CamelDB *cdb, const gchar *folder_name, gint reset_version, GError **error);
+gboolean camel_db_maybe_run_maintenance (CamelDB *cdb, GError **error);
+
G_END_DECLS
#endif
diff --git a/camel/camel-folder.c b/camel/camel-folder.c
index 567ea8a..9772019 100644
--- a/camel/camel-folder.c
+++ b/camel/camel-folder.c
@@ -2823,6 +2823,13 @@ camel_folder_append_message_finish (CamelFolder *folder,
return g_task_propagate_boolean (G_TASK (result), error);
}
+static gboolean
+camel_folder_maybe_run_db_maintenance (CamelFolder *folder,
+ GError **error)
+{
+ return camel_store_maybe_run_db_maintenance (camel_folder_get_parent_store (folder), error);
+}
+
/**
* camel_folder_expunge_sync:
* @folder: a #CamelFolder
@@ -2870,6 +2877,9 @@ camel_folder_expunge_sync (CamelFolder *folder,
if (!(folder->folder_flags & CAMEL_FOLDER_HAS_BEEN_DELETED)) {
success = class->expunge_sync (folder, cancellable, error);
CAMEL_CHECK_GERROR (folder, expunge_sync, success, error);
+
+ if (success)
+ success = camel_folder_maybe_run_db_maintenance (folder, error);
}
camel_operation_pop_message (cancellable);
@@ -3621,6 +3631,9 @@ camel_folder_synchronize_sync (CamelFolder *folder,
success = class->synchronize_sync (
folder, expunge, cancellable, error);
CAMEL_CHECK_GERROR (folder, synchronize_sync, success, error);
+
+ if (success && expunge)
+ success = camel_folder_maybe_run_db_maintenance (folder, error);
}
camel_folder_unlock (folder);
diff --git a/camel/camel-store.c b/camel/camel-store.c
index f770de6..ab75a96 100644
--- a/camel/camel-store.c
+++ b/camel/camel-store.c
@@ -55,6 +55,7 @@ typedef struct _SignalClosure SignalClosure;
struct _CamelStorePrivate {
GMutex signal_emission_lock;
gboolean folder_info_stale_scheduled;
+ volatile gint maintenance_lock;
};
struct _AsyncContext {
@@ -426,6 +427,8 @@ store_synchronize_sync (CamelStore *store,
/* ensure all folders are used when expunging */
CamelFolderInfo *root, *fi;
+ g_atomic_int_add (&store->priv->maintenance_lock, 1);
+
folders = g_ptr_array_new ();
root = camel_store_get_folder_info_sync (
store, NULL,
@@ -488,6 +491,14 @@ store_synchronize_sync (CamelStore *store,
g_object_unref (folder);
}
+ /* Unlock it before the call, thus it's actually done. */
+ if (expunge)
+ g_atomic_int_add (&store->priv->maintenance_lock, -1);
+
+ if (!local_error && expunge) {
+ camel_store_maybe_run_db_maintenance (store, &local_error);
+ }
+
if (local_error != NULL) {
g_propagate_error (error, local_error);
success = FALSE;
@@ -658,6 +669,7 @@ camel_store_init (CamelStore *store)
CAMEL_STORE_CAN_EDIT_FOLDERS;
store->mode = CAMEL_STORE_READ | CAMEL_STORE_WRITE;
+ store->priv->maintenance_lock = 0;
}
G_DEFINE_QUARK (camel-store-error-quark, camel_store_error)
@@ -2895,3 +2907,29 @@ camel_store_synchronize_finish (CamelStore *store,
return g_task_propagate_boolean (G_TASK (result), error);
}
+/**
+ * camel_store_maybe_run_db_maintenance:
+ * @store: a #CamelStore instance
+ * @error: (allow none): return location for a #GError, or %NULL
+ *
+ * Checks the state of the current CamelDB used for the @store and eventually
+ * runs maintenance routines on it.
+ *
+ * Returns: Whether succeeded.
+ *
+ * Since: 3.14
+ **/
+gboolean
+camel_store_maybe_run_db_maintenance (CamelStore *store,
+ GError **error)
+{
+ g_return_val_if_fail (CAMEL_IS_STORE (store), FALSE);
+
+ if (g_atomic_int_get (&store->priv->maintenance_lock) > 0)
+ return TRUE;
+
+ if (!store->cdb_w)
+ return TRUE;
+
+ return camel_db_maybe_run_maintenance (store->cdb_w, error);
+}
diff --git a/camel/camel-store.h b/camel/camel-store.h
index 9d02a9c..028ce28 100644
--- a/camel/camel-store.h
+++ b/camel/camel-store.h
@@ -355,6 +355,9 @@ void camel_store_synchronize (CamelStore *store,
gboolean camel_store_synchronize_finish (CamelStore *store,
GAsyncResult *result,
GError **error);
+gboolean camel_store_maybe_run_db_maintenance
+ (CamelStore *store,
+ GError **error);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]