1
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2
/* camel-imap-folder.c: class for an imap folder */
6
* Sankar P <psankar@novell.com>
7
* Srinivasa Ragavan <sragavan@novell.com>
9
3
* Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
11
* This library is free software you can redistribute it and/or modify it
5
* This library is free software: you can redistribute it and/or modify it
12
6
* under the terms of the GNU Lesser General Public License as published by
13
7
* the Free Software Foundation.
15
9
* This library is distributed in the hope that it will be useful, but
16
10
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
20
14
* You should have received a copy of the GNU Lesser General Public License
21
* along with this program; if not, see <http://www.gnu.org/licenses/>.
15
* along with this library. If not, see <http://www.gnu.org/licenses/>.
17
* Authors: Sankar P <psankar@novell.com>
18
* Srinivasa Ragavan <sragavan@novell.com>
24
21
#include "camel-db.h"
39
36
/* how long to wait before invoking sync on the file */
40
37
#define SYNC_TIMEOUT_SECONDS 5
42
#define READER_LOCK(cdb) g_rw_lock_reader_lock (&cdb->priv->rwlock)
43
#define READER_UNLOCK(cdb) g_rw_lock_reader_unlock (&cdb->priv->rwlock)
44
#define WRITER_LOCK(cdb) g_rw_lock_writer_lock (&cdb->priv->rwlock)
45
#define WRITER_UNLOCK(cdb) g_rw_lock_writer_unlock (&cdb->priv->rwlock)
47
39
static sqlite3_vfs *old_vfs = NULL;
48
40
static GThreadPool *sync_pool = NULL;
591
585
sqlite3_result_int (ctx, matches ? 1 : 0);
589
cdb_writer_lock (CamelDB *cdb)
591
g_return_if_fail (cdb != NULL);
593
g_mutex_lock (&cdb->priv->transaction_lock);
594
if (cdb->priv->transaction_thread != g_thread_self ()) {
595
g_mutex_unlock (&cdb->priv->transaction_lock);
597
g_rw_lock_writer_lock (&cdb->priv->rwlock);
599
g_mutex_lock (&cdb->priv->transaction_lock);
601
g_warn_if_fail (cdb->priv->transaction_thread == NULL);
602
g_warn_if_fail (cdb->priv->transaction_level == 0);
604
cdb->priv->transaction_thread = g_thread_self ();
607
cdb->priv->transaction_level++;
609
g_mutex_unlock (&cdb->priv->transaction_lock);
613
cdb_writer_unlock (CamelDB *cdb)
615
g_return_if_fail (cdb != NULL);
617
g_mutex_lock (&cdb->priv->transaction_lock);
619
g_warn_if_fail (cdb->priv->transaction_thread == g_thread_self ());
620
g_warn_if_fail (cdb->priv->transaction_level > 0);
622
cdb->priv->transaction_level--;
624
if (!cdb->priv->transaction_level) {
625
cdb->priv->transaction_thread = NULL;
626
g_mutex_unlock (&cdb->priv->transaction_lock);
628
g_rw_lock_writer_unlock (&cdb->priv->rwlock);
630
g_mutex_unlock (&cdb->priv->transaction_lock);
635
cdb_reader_lock (CamelDB *cdb)
637
g_return_if_fail (cdb != NULL);
639
g_mutex_lock (&cdb->priv->transaction_lock);
640
if (cdb->priv->transaction_thread == g_thread_self ()) {
641
/* already holding write lock */
642
g_mutex_unlock (&cdb->priv->transaction_lock);
644
g_mutex_unlock (&cdb->priv->transaction_lock);
646
g_rw_lock_reader_lock (&cdb->priv->rwlock);
651
cdb_reader_unlock (CamelDB *cdb)
653
g_return_if_fail (cdb != NULL);
655
g_mutex_lock (&cdb->priv->transaction_lock);
656
if (cdb->priv->transaction_thread == g_thread_self ()) {
657
/* already holding write lock */
658
g_mutex_unlock (&cdb->priv->transaction_lock);
660
g_mutex_unlock (&cdb->priv->transaction_lock);
662
g_rw_lock_reader_unlock (&cdb->priv->rwlock);
667
cdb_is_in_transaction (CamelDB *cdb)
671
g_return_val_if_fail (cdb != NULL, FALSE);
673
g_mutex_lock (&cdb->priv->transaction_lock);
674
res = cdb->priv->transaction_level > 0 && cdb->priv->transaction_thread == g_thread_self ();
675
g_mutex_unlock (&cdb->priv->transaction_lock);
681
cdb_construct_transaction_stmt (CamelDB *cdb,
686
g_return_val_if_fail (cdb != NULL, NULL);
688
g_mutex_lock (&cdb->priv->transaction_lock);
689
g_warn_if_fail (cdb->priv->transaction_thread == g_thread_self ());
690
name = g_strdup_printf ("%sTN%d", prefix ? prefix : "", cdb->priv->transaction_level);
691
g_mutex_unlock (&cdb->priv->transaction_lock);
632
734
cdb = g_new (CamelDB, 1);
634
cdb->priv = g_new (CamelDBPrivate, 1);
736
cdb->priv = g_new0 (CamelDBPrivate, 1);
635
737
cdb->priv->file_name = g_strdup (path);
636
738
g_rw_lock_init (&cdb->priv->rwlock);
739
g_mutex_init (&cdb->priv->transaction_lock);
740
cdb->priv->transaction_thread = NULL;
741
cdb->priv->transaction_level = 0;
637
742
cdb->priv->timer = NULL;
638
743
d (g_print ("\nDatabase succesfully opened \n"));
751
857
camel_db_begin_transaction (CamelDB *cdb,
760
cdb->priv->transaction_is_on = TRUE;
762
return (cdb_sql_exec (cdb->db, "BEGIN", NULL, NULL, error));
866
cdb_writer_lock (cdb);
868
stmt = cdb_construct_transaction_stmt (cdb, "SAVEPOINT ");
871
res = cdb_sql_exec (cdb->db, stmt, NULL, NULL, error);
771
883
camel_db_end_transaction (CamelDB *cdb,
778
ret = cdb_sql_exec (cdb->db, "COMMIT", NULL, NULL, error);
779
cdb->priv->transaction_is_on = FALSE;
892
stmt = cdb_construct_transaction_stmt (cdb, "RELEASE SAVEPOINT ");
893
ret = cdb_sql_exec (cdb->db, stmt, NULL, NULL, error);
897
cdb_writer_unlock (cdb);
783
898
CAMEL_DB_RELEASE_SQLITE_MEMORY;
794
909
camel_db_abort_transaction (CamelDB *cdb,
799
ret = cdb_sql_exec (cdb->db, "ROLLBACK", NULL, NULL, error);
800
cdb->priv->transaction_is_on = FALSE;
915
stmt = cdb_construct_transaction_stmt (cdb, "ROLLBACK TO SAVEPOINT ");
916
ret = cdb_sql_exec (cdb->db, stmt, NULL, NULL, error);
919
cdb_writer_unlock (cdb);
803
920
CAMEL_DB_RELEASE_SQLITE_MEMORY;
953
gboolean in_transaction = FALSE;
837
955
const gchar *query;
845
ret = cdb_sql_exec (cdb->db, "BEGIN", NULL, NULL, error);
960
ret = camel_db_begin_transaction (cdb, error);
964
in_transaction = TRUE;
849
966
while (qry_list) {
850
967
query = qry_list->data;
851
968
ret = cdb_sql_exec (cdb->db, query, NULL, NULL, error);
1518
1641
folder_name, folder_name);
1519
1642
ret = camel_db_add_to_transaction (cdb, table_creation_query, error);
1520
1643
sqlite3_free (table_creation_query);
1644
g_clear_error (error);
1522
1646
table_creation_query = sqlite3_mprintf ("DROP TABLE IF EXISTS %Q", folder_name);
1523
1647
ret = camel_db_add_to_transaction (cdb, table_creation_query, error);
1524
1648
sqlite3_free (table_creation_query);
1649
g_clear_error (error);
1526
1651
ret = camel_db_create_message_info_table (cdb, folder_name, error);
1527
1652
g_clear_error (error);
1689
1815
camel_db_end_transaction (cdb, &err);
1816
in_transaction = FALSE;
1691
1818
/* Migration stage zero: version fetch */
1692
1819
current_version = camel_db_get_folder_version (cdb, folder_name, &err);
1820
if (err && err->message && strstr (err->message, "no such table") != NULL) {
1821
g_clear_error (&err);
1822
current_version = -1;
1694
1825
camel_db_begin_transaction (cdb, &err);
1826
in_transaction = TRUE;
1696
1828
/* Migration stage one: storing the old data if necessary */
1697
1829
ret = camel_db_migrate_folder_prepare (cdb, folder_name, current_version, &err);
2601
2734
return GPOINTER_TO_INT (value);
2738
get_number_cb (gpointer data,
2743
guint64 *pui64 = data;
2746
*pui64 = argv[0] ? g_ascii_strtoull (argv[0], NULL, 10) : 0;
2755
* camel_db_maybe_run_maintenance:
2756
* @cdb: a #CamelDB instance
2757
* @error: (allow none): a #GError or %NULL
2759
* Runs a @cdb maintenance, which includes vacuum, if necessary.
2761
* Returns: Whether succeeded.
2766
camel_db_maybe_run_maintenance (CamelDB *cdb,
2769
GError *local_error = NULL;
2770
guint64 page_count = 0, freelist_count = 0;
2771
gboolean success = FALSE;
2773
g_return_val_if_fail (cdb != NULL, FALSE);
2775
cdb_writer_lock (cdb);
2777
if (cdb_sql_exec (cdb->db, "PRAGMA page_count;", get_number_cb, &page_count, &local_error) == SQLITE_OK &&
2778
cdb_sql_exec (cdb->db, "PRAGMA freelist_count;", get_number_cb, &freelist_count, &local_error) == SQLITE_OK) {
2779
/* Vacuum, if there's more than 5% of the free pages */
2780
success = !page_count || !freelist_count || freelist_count * 1000 / page_count <= 50 ||
2781
cdb_sql_exec (cdb->db, "vacuum;", NULL, NULL, &local_error) == SQLITE_OK;
2784
cdb_writer_unlock (cdb);
2787
g_propagate_error (error, local_error);