[evolution-data-server] [SQLite VFS] Track pending sync requests



commit 3e6fee16429f642655c429e85abfd4927bc413c2
Author: Milan Crha <mcrha redhat com>
Date:   Fri Dec 5 12:22:05 2014 +0100

    [SQLite VFS] Track pending sync requests
    
    The sync request are done asynchronously, in a dedicated thread,
    which means that the database file can be closed meanwhile. The
    database has no reference counting, thus it's required to track
    whether there are any pending sync requests, to not free the
    structure too early.

 camel/camel-db.c            |   29 +++++++++++++++++++++++++++++
 libebackend/e-sqlite3-vfs.c |   36 ++++++++++++++++++++++++++++++++++++
 2 files changed, 65 insertions(+), 0 deletions(-)
---
diff --git a/camel/camel-db.c b/camel/camel-db.c
index 17edffc..5ef932e 100644
--- a/camel/camel-db.c
+++ b/camel/camel-db.c
@@ -45,6 +45,12 @@ typedef struct {
        GRecMutex sync_mutex;
        guint timeout_id;
        gint flags;
+
+       /* Do know how many syncs are pending, to not close
+          the file before the last sync is over */
+       guint pending_syncs;
+       GMutex pending_syncs_lock;
+       GCond pending_syncs_cond;
 } CamelSqlite3File;
 
 static gint
@@ -83,6 +89,13 @@ sync_request_thread_cb (gpointer task_data,
 
        call_old_file_Sync (sync_data->cFile, sync_data->flags);
 
+       g_mutex_lock (&sync_data->cFile->pending_syncs_lock);
+       g_warn_if_fail (sync_data->cFile->pending_syncs > 0);
+       sync_data->cFile->pending_syncs--;
+       if (!sync_data->cFile->pending_syncs)
+               g_cond_signal (&sync_data->cFile->pending_syncs_cond);
+       g_mutex_unlock (&sync_data->cFile->pending_syncs_lock);
+
        done = sync_data->done;
        g_free (sync_data);
 
@@ -128,6 +141,10 @@ sync_push_request (CamelSqlite3File *cFile,
 
        cFile->flags = 0;
 
+       g_mutex_lock (&cFile->pending_syncs_lock);
+       cFile->pending_syncs++;
+       g_mutex_unlock (&cFile->pending_syncs_lock);
+
        g_rec_mutex_unlock (&cFile->sync_mutex);
 
        g_thread_pool_push (sync_pool, data, &error);
@@ -261,6 +278,12 @@ camel_sqlite3_file_xClose (sqlite3_file *pFile)
        /* Make the last sync. */
        sync_push_request (cFile, TRUE);
 
+       g_mutex_lock (&cFile->pending_syncs_lock);
+       while (cFile->pending_syncs > 0) {
+               g_cond_wait (&cFile->pending_syncs_cond, &cFile->pending_syncs_lock);
+       }
+       g_mutex_unlock (&cFile->pending_syncs_lock);
+
        if (cFile->old_vfs_file->pMethods)
                res = cFile->old_vfs_file->pMethods->xClose (cFile->old_vfs_file);
        else
@@ -270,6 +293,8 @@ camel_sqlite3_file_xClose (sqlite3_file *pFile)
        cFile->old_vfs_file = NULL;
 
        g_rec_mutex_clear (&cFile->sync_mutex);
+       g_mutex_clear (&cFile->pending_syncs_lock);
+       g_cond_clear (&cFile->pending_syncs_cond);
 
        return res;
 }
@@ -332,6 +357,10 @@ camel_sqlite3_vfs_xOpen (sqlite3_vfs *pVfs,
        }
 
        g_rec_mutex_init (&cFile->sync_mutex);
+       g_mutex_init (&cFile->pending_syncs_lock);
+       g_cond_init (&cFile->pending_syncs_cond);
+
+       cFile->pending_syncs = 0;
 
        g_rec_mutex_lock (&only_once_lock);
 
diff --git a/libebackend/e-sqlite3-vfs.c b/libebackend/e-sqlite3-vfs.c
index bc1182d..1980a33 100644
--- a/libebackend/e-sqlite3-vfs.c
+++ b/libebackend/e-sqlite3-vfs.c
@@ -40,6 +40,12 @@ typedef struct {
        GRecMutex sync_mutex;
        guint timeout_id;
        gint flags;
+
+       /* Do know how many syncs are pending, to not close
+          the file before the last sync is over */
+       guint pending_syncs;
+       GMutex pending_syncs_lock;
+       GCond pending_syncs_cond;
 } ESqlite3File;
 
 static gint
@@ -72,6 +78,13 @@ sync_request_thread_cb (gpointer task_data,
 
        call_old_file_Sync (sync_data->cFile, sync_data->flags);
 
+       g_mutex_lock (&sync_data->cFile->pending_syncs_lock);
+       g_warn_if_fail (sync_data->cFile->pending_syncs > 0);
+       sync_data->cFile->pending_syncs--;
+       if (!sync_data->cFile->pending_syncs)
+               g_cond_signal (&sync_data->cFile->pending_syncs_cond);
+       g_mutex_unlock (&sync_data->cFile->pending_syncs_lock);
+
        sync_op = sync_data->sync_op;
        g_free (sync_data);
 
@@ -92,6 +105,13 @@ sync_push_request (ESqlite3File *cFile,
 
        g_rec_mutex_lock (&cFile->sync_mutex);
 
+       if (!cFile->flags) {
+               /* nothing to sync, might be when xClose is called
+                  without any pending xSync request */
+               g_rec_mutex_unlock (&cFile->sync_mutex);
+               return;
+       }
+
        if (wait_for_finish)
                sync_op = e_flag_new ();
 
@@ -102,6 +122,10 @@ sync_push_request (ESqlite3File *cFile,
 
        cFile->flags = 0;
 
+       g_mutex_lock (&cFile->pending_syncs_lock);
+       cFile->pending_syncs++;
+       g_mutex_unlock (&cFile->pending_syncs_lock);
+
        g_rec_mutex_unlock (&cFile->sync_mutex);
 
        g_thread_pool_push (sync_pool, data, &error);
@@ -227,6 +251,12 @@ e_sqlite3_file_xClose (sqlite3_file *pFile)
        /* Make the last sync. */
        sync_push_request (cFile, TRUE);
 
+       g_mutex_lock (&cFile->pending_syncs_lock);
+       while (cFile->pending_syncs > 0) {
+               g_cond_wait (&cFile->pending_syncs_cond, &cFile->pending_syncs_lock);
+       }
+       g_mutex_unlock (&cFile->pending_syncs_lock);
+
        if (cFile->old_vfs_file->pMethods)
                res = cFile->old_vfs_file->pMethods->xClose (cFile->old_vfs_file);
        else
@@ -236,6 +266,8 @@ e_sqlite3_file_xClose (sqlite3_file *pFile)
        cFile->old_vfs_file = NULL;
 
        g_rec_mutex_clear (&cFile->sync_mutex);
+       g_mutex_clear (&cFile->pending_syncs_lock);
+       g_cond_clear (&cFile->pending_syncs_cond);
 
        return res;
 }
@@ -294,6 +326,10 @@ e_sqlite3_vfs_xOpen (sqlite3_vfs *pVfs,
        }
 
        g_rec_mutex_init (&cFile->sync_mutex);
+       g_mutex_init (&cFile->pending_syncs_lock);
+       g_cond_init (&cFile->pending_syncs_cond);
+
+       cFile->pending_syncs = 0;
 
        g_rec_mutex_lock (&only_once_lock);
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]