diff options
author | Srinivasa Ragavan <sragavan@src.gnome.org> | 2008-09-29 04:53:01 +0000 |
---|---|---|
committer | Srinivasa Ragavan <sragavan@src.gnome.org> | 2008-09-29 04:53:01 +0000 |
commit | 1541ee22933eccaa8c441cef128bbcaa8b1b4254 (patch) | |
tree | 62f4099c6fbd930f5444ac559f566b4ec481cfe5 | |
parent | 149bb73ff7941b443a0b54be057d1ffc5e37f0ba (diff) | |
download | evolution-data-server-1541ee22933eccaa8c441cef128bbcaa8b1b4254.tar.gz |
DBv2. Folders work. vfolders too, but need lot of optimization.db-summary-v2
svn path=/branches/db-summary-v2/; revision=9625
24 files changed, 587 insertions, 418 deletions
diff --git a/camel/camel-db.c b/camel/camel-db.c index 89cf06c15..7bc019c33 100644 --- a/camel/camel-db.c +++ b/camel/camel-db.c @@ -28,6 +28,7 @@ #include <config.h> +#include <sys/stat.h> #include <string.h> #include <stdlib.h> @@ -49,6 +50,7 @@ #endif static GStaticRecMutex trans_lock = G_STATIC_REC_MUTEX_INIT; +static char *db_path = NULL; static int cdb_sql_exec (sqlite3 *db, const char* stmt, CamelException *ex) @@ -116,8 +118,6 @@ camel_db_open (const char *path, CamelException *ex) cdb->db = db; cdb->lock = g_mutex_new (); /* These will be written once the Summary takes control of the CDB. */ - cdb->sort_by = NULL; - cdb->collate = NULL; d(g_print ("\nDatabase succesfully opened \n")); /* Which is big / costlier ? A Stack frame or a pointer */ @@ -155,9 +155,6 @@ camel_db_set_collate (CamelDB *cdb, const char *col, const char *collate, CamelD return 0; g_mutex_lock (cdb->lock); - cdb->sort_by = col; - cdb->collate = collate; - cdb->collate_cb = func; d(g_print("Creating Collation %s on %s with %p\n", collate, col, func)); if (collate && func) ret = sqlite3_create_collation(cdb->db, collate, SQLITE_UTF8, NULL, func); @@ -338,7 +335,7 @@ camel_db_count_junk_message_info (CamelDB *cdb, const char *table_name, guint32 if (!cdb) return -1; - query = sqlite3_mprintf ("SELECT COUNT (*) FROM %Q WHERE junk = 1", table_name); + query = sqlite3_mprintf ("SELECT COUNT (*) FROM messages WHERE folder_key = %Q AND junk = 1", table_name); ret = camel_db_count_message_info (cdb, query, count, ex); sqlite3_free (query); @@ -355,7 +352,7 @@ camel_db_count_unread_message_info (CamelDB *cdb, const char *table_name, guint3 if (!cdb) return -1; - query = sqlite3_mprintf ("SELECT COUNT (*) FROM %Q WHERE read = 0", table_name); + query = sqlite3_mprintf ("SELECT COUNT (*) FROM messages WHERE folder_key = %Q AND read = 0", table_name); ret = camel_db_count_message_info (cdb, query, count, ex); sqlite3_free (query); @@ -372,7 +369,7 @@ camel_db_count_visible_unread_message_info (CamelDB *cdb, const char *table_name if (!cdb) return -1; - query = sqlite3_mprintf ("SELECT COUNT (*) FROM %Q WHERE read = 0 AND junk = 0 AND deleted = 0", table_name); + query = sqlite3_mprintf ("SELECT COUNT (*) FROM messages WHERE folder_key = %Q AND read = 0 AND junk = 0 AND deleted = 0", table_name); ret = camel_db_count_message_info (cdb, query, count, ex); sqlite3_free (query); @@ -389,7 +386,7 @@ camel_db_count_visible_message_info (CamelDB *cdb, const char *table_name, guint if (!cdb) return -1; - query = sqlite3_mprintf ("SELECT COUNT (*) FROM %Q WHERE junk = 0 AND deleted = 0", table_name); + query = sqlite3_mprintf ("SELECT COUNT (*) FROM messages WHERE folder_key = %Q AND junk = 0 AND deleted = 0", table_name); ret = camel_db_count_message_info (cdb, query, count, ex); sqlite3_free (query); @@ -406,7 +403,7 @@ camel_db_count_junk_not_deleted_message_info (CamelDB *cdb, const char *table_na if (!cdb) return -1; - query = sqlite3_mprintf ("SELECT COUNT (*) FROM %Q WHERE junk = 1 AND deleted = 0", table_name); + query = sqlite3_mprintf ("SELECT COUNT (*) FROM messages WHERE folder_key = %Q AND junk = 1 AND deleted = 0", table_name); ret = camel_db_count_message_info (cdb, query, count, ex); sqlite3_free (query); @@ -423,7 +420,7 @@ camel_db_count_deleted_message_info (CamelDB *cdb, const char *table_name, guint if (!cdb) return -1; - query = sqlite3_mprintf ("SELECT COUNT (*) FROM %Q WHERE deleted = 1", table_name); + query = sqlite3_mprintf ("SELECT COUNT (*) FROM messages WHERE folder_key = %Q AND deleted = 1", table_name); ret = camel_db_count_message_info (cdb, query, count, ex); sqlite3_free (query); @@ -442,7 +439,7 @@ camel_db_count_total_message_info (CamelDB *cdb, const char *table_name, guint32 if (!cdb) return -1; - query = sqlite3_mprintf ("SELECT COUNT (*) FROM %Q", table_name); + query = sqlite3_mprintf ("SELECT COUNT (*) FROM messages where folder_key = %Q", table_name); ret = camel_db_count_message_info (cdb, query, count, ex); sqlite3_free (query); @@ -583,14 +580,15 @@ read_uids_callback (void *ref, int ncol, char ** cols, char ** name) } int -camel_db_get_folder_uids (CamelDB *db, char *folder_name, GPtrArray *array, CamelException *ex) +camel_db_get_folder_uids (CamelDB *db, char *folder_name, char *sort_by, char *collate, GPtrArray *array, CamelException *ex) { char *sel_query; int ret; - - sel_query = sqlite3_mprintf("SELECT uid FROM %Q%s%s%s%s", folder_name, db->sort_by ? " order by " : "", db->sort_by ? db->sort_by: "", (db->sort_by && db->collate) ? " collate " : "", (db->sort_by && db->collate) ? db->collate : ""); + printf("start %s: %d\n", folder_name, time(NULL)); + sel_query = sqlite3_mprintf("SELECT uid FROM messages WHERE folder_key=%Q %s%s%s%s", folder_name, sort_by ? " order by " : "", sort_by ? sort_by: "", (sort_by && collate) ? " collate " : "", (sort_by && collate) ? collate : ""); ret = camel_db_select (db, sel_query, read_uids_callback, array, ex); + printf("end %s: %d\n", folder_name, time(NULL)); sqlite3_free (sel_query); return ret; @@ -603,7 +601,7 @@ camel_db_get_folder_junk_uids (CamelDB *db, char *folder_name, CamelException *e int ret; GPtrArray *array = g_ptr_array_new(); - sel_query = sqlite3_mprintf("SELECT uid FROM %Q where junk=1", folder_name); + sel_query = sqlite3_mprintf("SELECT uid FROM messages where folder_key=%Q AND junk=1", folder_name); ret = camel_db_select (db, sel_query, read_uids_callback, array, ex); @@ -623,7 +621,7 @@ camel_db_get_folder_deleted_uids (CamelDB *db, char *folder_name, CamelException int ret; GPtrArray *array = g_ptr_array_new(); - sel_query = sqlite3_mprintf("SELECT uid FROM %Q where deleted=1", folder_name); + sel_query = sqlite3_mprintf("SELECT uid FROM messages where folder_key=%Q AND deleted=1", folder_name); ret = camel_db_select (db, sel_query, read_uids_callback, array, ex); sqlite3_free (sel_query); @@ -720,7 +718,10 @@ int camel_db_create_folders_table (CamelDB *cdb, CamelException *ex) { char *query = "CREATE TABLE IF NOT EXISTS folders ( folder_name TEXT PRIMARY KEY, version REAL, flags INTEGER, nextuid INTEGER, time NUMERIC, saved_count INTEGER, unread_count INTEGER, deleted_count INTEGER, junk_count INTEGER, visible_count INTEGER, jnd_count INTEGER, bdata TEXT )"; + + return 0; CAMEL_DB_RELEASE_SQLITE_MEMORY; + return ((camel_db_command (cdb, query, ex))); } @@ -729,7 +730,8 @@ camel_db_prepare_message_info_table (CamelDB *cdb, const char *folder_name, Came { int ret; char *table_creation_query, *safe_index; - + + return 0; /* README: It is possible to compress all system flags into a single column and use just as userflags but that makes querying for other applications difficult an d bloats the parsing code. Instead, it is better to bloat the tables. Sqlite should have some optimizations for sparse columns etc. */ table_creation_query = sqlite3_mprintf ("CREATE TABLE IF NOT EXISTS %Q ( uid TEXT PRIMARY KEY , flags INTEGER , msg_type INTEGER , read INTEGER , deleted INTEGER , replied INTEGER , important INTEGER , junk INTEGER , attachment INTEGER , msg_security INTEGER , size INTEGER , dsent NUMERIC , dreceived NUMERIC , subject TEXT , mail_from TEXT , mail_to TEXT , mail_cc TEXT , mlist TEXT , followup_flag TEXT , followup_completed_on TEXT , followup_due_by TEXT , part TEXT , labels TEXT , usertags TEXT , cinfo TEXT , bdata TEXT )", folder_name); @@ -755,10 +757,10 @@ camel_db_write_message_info_record (CamelDB *cdb, const char *folder_name, Camel char *del_query; char *ins_query; - ins_query = sqlite3_mprintf ("INSERT INTO %Q VALUES (%Q, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %ld, %ld, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %Q )", - folder_name, record->uid, record->flags, + ins_query = sqlite3_mprintf ("INSERT INTO messages VALUES (%Q, %Q, '%s%s', %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %ld, %ld, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %Q )", + folder_name, record->uid, folder_name, record->uid, record->flags, record->msg_type, record->read, record->deleted, record->replied, - record->important, record->junk, record->attachment, record->msg_security, + record->important, record->junk, record->attachment, record->dirty, record->size, record->dsent, record->dreceived, record->subject, record->from, record->to, record->cc, record->mlist, record->followup_flag, @@ -766,7 +768,7 @@ camel_db_write_message_info_record (CamelDB *cdb, const char *folder_name, Camel record->part, record->labels, record->usertags, record->cinfo, record->bdata); - del_query = sqlite3_mprintf ("DELETE FROM %Q WHERE uid = %Q", folder_name, record->uid); + del_query = sqlite3_mprintf ("DELETE FROM messages WHERE folder_key = %Q AND uid = %Q", folder_name, record->uid); #if 0 char *upd_query; @@ -795,13 +797,13 @@ camel_db_write_folder_info_record (CamelDB *cdb, CamelFIRecord *record, CamelExc char *del_query; char *ins_query; - ins_query = sqlite3_mprintf ("INSERT INTO folders VALUES ( %Q, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %Q ) ", - record->folder_name, record->version, + ins_query = sqlite3_mprintf ("INSERT INTO folders VALUES ( %Q, %Q, %Q, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %Q ) ", + record->account_url, record->folder_name, record->folder_key, record->version, record->flags, record->nextuid, record->time, record->saved_count, record->unread_count, record->deleted_count, record->junk_count, record->visible_count, record->jnd_count, record->bdata); - del_query = sqlite3_mprintf ("DELETE FROM folders WHERE folder_name = %Q", record->folder_name); + del_query = sqlite3_mprintf ("DELETE FROM folders WHERE account_url = %Q AND folder_name = %Q", record->account_url, record->folder_name); #if 0 @@ -870,19 +872,23 @@ read_fir_callback (void * ref, int ncol, char ** cols, char ** name) record->jnd_count = cols [i] ? strtoul (cols [i], NULL, 10) : 0; else if (!strcmp (name [i], "bdata")) record->bdata = g_strdup (cols [i]); - + else if (!strcmp (name [i], "account_url")) + record->account_url = g_strdup (cols [i]); + else if (!strcmp (name [i], "folder_key")) + record->folder_key = g_strdup (cols [i]); + } #endif return 0; } int -camel_db_read_folder_info_record (CamelDB *cdb, const char *folder_name, CamelFIRecord **record, CamelException *ex) +camel_db_read_folder_info_record (CamelDB *cdb, const char *url, const char *folder_name, CamelFIRecord **record, CamelException *ex) { char *query; int ret; - query = sqlite3_mprintf ("SELECT * FROM folders WHERE folder_name = %Q", folder_name); + query = sqlite3_mprintf ("SELECT * FROM folders WHERE account_url = %Q AND folder_name = %Q", url, folder_name); ret = camel_db_select (cdb, query, read_fir_callback, record, ex); sqlite3_free (query); @@ -890,12 +896,12 @@ camel_db_read_folder_info_record (CamelDB *cdb, const char *folder_name, CamelFI } int -camel_db_read_message_info_record_with_uid (CamelDB *cdb, const char *folder_name, const char *uid, gpointer p, CamelDBSelectCB read_mir_callback, CamelException *ex) +camel_db_read_message_info_record_with_uid (CamelDB *cdb, const char *folder_name, const char *uid, gpointer p, CamelDBSelectCB read_mir_callback, gboolean vuid, CamelException *ex) { char *query; int ret; - query = sqlite3_mprintf ("SELECT uid, flags, size, dsent, dreceived, subject, mail_from, mail_to, mail_cc, mlist, part, labels, usertags, cinfo, bdata FROM %Q WHERE uid = %Q", folder_name, uid); + query = sqlite3_mprintf ("SELECT folder_key, %s, flags, size, dsent, dreceived, subject, mail_from, mail_to, mail_cc, mlist, part, labels, usertags, cinfo, bdata FROM messages WHERE folder_key = %Q AND %s = %Q", vuid ? "vuid" : "uid", folder_name, vuid ? "vuid" : "uid", uid); ret = camel_db_select (cdb, query, read_mir_callback, p, ex); sqlite3_free (query); @@ -903,13 +909,14 @@ camel_db_read_message_info_record_with_uid (CamelDB *cdb, const char *folder_nam } int -camel_db_read_message_info_records (CamelDB *cdb, const char *folder_name, gpointer p, CamelDBSelectCB read_mir_callback, CamelException *ex) +camel_db_read_message_info_records (CamelDB *cdb, const char *folder_name, gpointer p, CamelDBSelectCB read_mir_callback, char *v_query, CamelException *ex) { char *query; int ret; - - query = sqlite3_mprintf ("SELECT uid, flags, size, dsent, dreceived, subject, mail_from, mail_to, mail_cc, mlist, part, labels, usertags, cinfo, bdata FROM %Q ", folder_name); + char *tmp = sqlite3_mprintf ("%Q", folder_name); + query = sqlite3_mprintf ("SELECT folder_key, %s, flags, size, dsent, dreceived, subject, mail_from, mail_to, mail_cc, mlist, part, labels, usertags, cinfo, bdata FROM messages where %s%s", v_query ? "vuid" : "uid", v_query ? v_query : "folder_key = ", v_query ? "" : tmp); ret = camel_db_select (cdb, query, read_mir_callback, p, ex); + sqlite3_free (tmp); sqlite3_free (query); return (ret); @@ -918,7 +925,7 @@ camel_db_read_message_info_records (CamelDB *cdb, const char *folder_name, gpoin int camel_db_delete_uid (CamelDB *cdb, const char *folder, const char *uid, CamelException *ex) { - char *tab = sqlite3_mprintf ("DELETE FROM %Q WHERE uid = %Q", folder, uid); + char *tab = sqlite3_mprintf ("DELETE FROM messages WHERE folder_key = %Q AND uid = %Q", folder, uid); int ret; ret = camel_db_command (cdb, tab, ex); @@ -936,7 +943,7 @@ camel_db_delete_uids (CamelDB *cdb, const char * folder_name, GSList *uids, Came GString *str = g_string_new ("DELETE FROM "); GSList *iterator; - tmp = sqlite3_mprintf ("%Q WHERE uid IN (", folder_name); + tmp = sqlite3_mprintf ("messages WHERE folder_KEY = %Q AND uid IN (", folder_name); g_string_append_printf (str, "%s ", tmp); sqlite3_free (tmp); @@ -965,15 +972,15 @@ camel_db_delete_uids (CamelDB *cdb, const char * folder_name, GSList *uids, Came } int -camel_db_clear_folder_summary (CamelDB *cdb, char *folder, CamelException *ex) +camel_db_clear_folder_summary (CamelDB *cdb, char *url, char *folder, char *key, CamelException *ex) { int ret; char *folders_del; char *msginfo_del; - folders_del = sqlite3_mprintf ("DELETE FROM folders WHERE folder_name = %Q", folder); - msginfo_del = sqlite3_mprintf ("DELETE FROM %Q ", folder); + folders_del = sqlite3_mprintf ("DELETE FROM folders WHERE account_url = %Q AND folder_name = %Q", folder); + msginfo_del = sqlite3_mprintf ("DELETE FROM messages WHERE folder_key= %Q ", key); camel_db_begin_transaction (cdb, ex); camel_db_add_to_transaction (cdb, msginfo_del, ex); @@ -986,6 +993,7 @@ camel_db_clear_folder_summary (CamelDB *cdb, char *folder, CamelException *ex) return ret; } +/* Obsolete */ int camel_db_delete_folder (CamelDB *cdb, const char *folder, CamelException *ex) { @@ -1005,16 +1013,12 @@ camel_db_delete_folder (CamelDB *cdb, const char *folder, CamelException *ex) } int -camel_db_rename_folder (CamelDB *cdb, const char *old_folder, const char *new_folder, CamelException *ex) +camel_db_rename_folder (CamelDB *cdb, char *url, const char *old_folder, const char *new_folder, CamelException *ex) { int ret; char *cmd; - cmd = sqlite3_mprintf ("ALTER TABLE %Q RENAME TO %Q", old_folder, new_folder); - ret = camel_db_command (cdb, cmd, ex); - sqlite3_free (cmd); - - cmd = sqlite3_mprintf ("UPDATE folders SET folder_name = %Q WHERE folder_name = %Q", new_folder, old_folder); + cmd = sqlite3_mprintf ("UPDATE folders SET folder_name = %Q WHERE account_url = %Q AND folder_name = %Q", new_folder, url, old_folder); ret = camel_db_command (cdb, cmd, ex); sqlite3_free (cmd); @@ -1026,7 +1030,9 @@ void camel_db_camel_mir_free (CamelMIRecord *record) { if (record) { + camel_pstring_free (record->folder_key); camel_pstring_free (record->uid); + camel_pstring_free (record->vuid); camel_pstring_free (record->subject); camel_pstring_free (record->from); camel_pstring_free (record->to); @@ -1118,3 +1124,55 @@ camel_db_migrate_vfolders_to_14 (CamelDB *cdb, const char *folder, CamelExceptio CAMEL_DB_RELEASE_SQLITE_MEMORY; return ret; } + +static int +cdb_setup_tables (CamelDB *db, CamelException *ex) +{ + int ret = 0; + const char *query; + + query = "CREATE TABLE IF NOT EXISTS folders ( account_url TEXT , folder_name TEXT , folder_key TEXT, version REAL, flags INTEGER, nextuid INTEGER, time NUMERIC, saved_count INTEGER, unread_count INTEGER, deleted_count INTEGER, junk_count INTEGER, visible_count INTEGER, jnd_count INTEGER, bdata TEXT, PRIMARY KEY(account_url, folder_name))"; + ret = camel_db_command (db, query, ex); + if (ret == -1) + return ret; + + query = "CREATE TABLE IF NOT EXISTS messages ( folder_key TEXT , uid TEXT , vuid TEXT, flags INTEGER , msg_type INTEGER , read INTEGER , deleted INTEGER , replied INTEGER , important INTEGER , junk INTEGER , attachment INTEGER , dirty INTEGER , size INTEGER , dsent NUMERIC , dreceived NUMERIC , subject TEXT , mail_from TEXT , mail_to TEXT , mail_cc TEXT , mlist TEXT , followup_flag TEXT , followup_completed_on TEXT , followup_due_by TEXT , part TEXT , labels TEXT , usertags TEXT , cinfo TEXT , bdata TEXT, PRIMARY KEY (folder_key, uid) )"; + + ret = camel_db_command (db, query, ex); + if (ret == -1) + return ret; + + /* Create index for searches */ + ret = camel_db_command (db, "CREATE INDEX 'messages-junk' on messages (junk)", ex); + ret = camel_db_command (db, "CREATE INDEX 'messages-deleted' on messages (deleted)", ex); + ret = camel_db_command (db, "CREATE INDEX 'messages-read' on messages (read)", ex); + + return ret; +} + +/* A func that just creates tables and closes everything */ +int +camel_db_setup (const char *path, CamelException *ex) +{ + CamelDB *db; + + db_path = g_build_filename (path, CAMEL_DB_V2_FILE, NULL); + if (!g_file_test(db_path, G_FILE_TEST_EXISTS)) { + if (!g_file_test(path, G_FILE_TEST_EXISTS)) { + g_mkdir_with_parents (path, S_IRWXU); + } + db = camel_db_open (db_path, ex); + if (!db) + return -1; + cdb_setup_tables (db, ex); + camel_db_close(db); + } + + return 0; +} + +CamelDB * +camel_db_get_handle (CamelException *ex) +{ + return camel_db_open (db_path, ex); +} diff --git a/camel/camel-db.h b/camel/camel-db.h index 40ab32cff..803213f19 100644 --- a/camel/camel-db.h +++ b/camel/camel-db.h @@ -4,7 +4,9 @@ #define __CAMEL_DB_H #include <sqlite3.h> #include <glib.h> + #define CAMEL_DB_FILE "folders.db" +#define CAMEL_DB_V2_FILE "summary.db" #include "camel-exception.h" @@ -13,9 +15,6 @@ typedef int(*CamelDBCollate)(void*,int,const void*,int,const void*); struct _CamelDB { sqlite3 *db; GMutex *lock; - const char *sort_by; - const char *collate; - CamelDBCollate collate_cb; #ifdef CAMEL_DB_DEBUG GTimer *timer; #endif @@ -28,6 +27,7 @@ struct _CamelDB { /* The extensive DB format, supporting basic searching and sorting + folder_key - unique folder id uid, - Message UID flags, - Camel Message info flags unread/read, - boolean read/unread status @@ -56,10 +56,12 @@ struct _CamelDB { */ typedef struct _CamelMIRecord { + char *folder_key; char *uid; + char *vuid; guint32 flags; guint32 msg_type; - guint32 msg_security; + gboolean dirty; gboolean read; gboolean deleted; gboolean replied; @@ -85,6 +87,8 @@ typedef struct _CamelMIRecord { } CamelMIRecord; typedef struct _CamelFIRecord { + char *account_url; + char *folder_key; char *folder_name; guint32 version; guint32 flags; @@ -116,8 +120,8 @@ int camel_db_begin_transaction (CamelDB *cdb, CamelException *ex); int camel_db_add_to_transaction (CamelDB *cdb, const char *query, CamelException *ex); int camel_db_end_transaction (CamelDB *cdb, CamelException *ex); int camel_db_abort_transaction (CamelDB *cdb, CamelException *ex); -int camel_db_clear_folder_summary (CamelDB *cdb, char *folder, CamelException *ex); -int camel_db_rename_folder (CamelDB *cdb, const char *old_folder, const char *new_folder, CamelException *ex); +int camel_db_clear_folder_summary (CamelDB *cdb, char *url, char *folder, char *key, CamelException *ex); +int camel_db_rename_folder (CamelDB *cdb, char *url, const char *old_folder, const char *new_folder, CamelException *ex); int camel_db_delete_folder (CamelDB *cdb, const char *folder, CamelException *ex); int camel_db_delete_uid (CamelDB *cdb, const char *folder, const char *uid, CamelException *ex); @@ -128,13 +132,13 @@ int camel_db_create_folders_table (CamelDB *cdb, CamelException *ex); int camel_db_select (CamelDB *cdb, const char* stmt, CamelDBSelectCB callback, gpointer data, CamelException *ex); int camel_db_write_folder_info_record (CamelDB *cdb, CamelFIRecord *record, CamelException *ex); -int camel_db_read_folder_info_record (CamelDB *cdb, const char *folder_name, CamelFIRecord **record, CamelException *ex); +int camel_db_read_folder_info_record (CamelDB *cdb, const char *url, const char *folder_name, CamelFIRecord **record, CamelException *ex); int camel_db_prepare_message_info_table (CamelDB *cdb, const char *folder_name, CamelException *ex); int camel_db_write_message_info_record (CamelDB *cdb, const char *folder_name, CamelMIRecord *record, CamelException *ex); -int camel_db_read_message_info_records (CamelDB *cdb, const char *folder_name, gpointer p, CamelDBSelectCB read_mir_callback, CamelException *ex); -int camel_db_read_message_info_record_with_uid (CamelDB *cdb, const char *folder_name, const char *uid, gpointer p, CamelDBSelectCB read_mir_callback, CamelException *ex); +int camel_db_read_message_info_records (CamelDB *cdb, const char *folder_name, gpointer p, CamelDBSelectCB read_mir_callback, char *v_query, CamelException *ex); +int camel_db_read_message_info_record_with_uid (CamelDB *cdb, const char *folder_name, const char *uid, gpointer p, CamelDBSelectCB read_mir_callback, gboolean vuid, CamelException *ex); int camel_db_count_junk_message_info (CamelDB *cdb, const char *table_name, guint32 *count, CamelException *ex); int camel_db_count_unread_message_info (CamelDB *cdb, const char *table_name, guint32 *count, CamelException *ex); @@ -156,7 +160,7 @@ GPtrArray * camel_db_get_vuids_from_vfolder (CamelDB *db, char *folder_name, cha int camel_db_add_to_vfolder (CamelDB *db, char *folder_name, char *vuid, CamelException *ex); int camel_db_add_to_vfolder_transaction (CamelDB *db, char *folder_name, char *vuid, CamelException *ex); -int camel_db_get_folder_uids (CamelDB *db, char *folder_name, GPtrArray *array, CamelException *ex); +int camel_db_get_folder_uids (CamelDB *db, char *folder_name, char *sort_by, char *collate, GPtrArray *array, CamelException *ex); GPtrArray * camel_db_get_folder_junk_uids (CamelDB *db, char *folder_name, CamelException *ex); GPtrArray * camel_db_get_folder_deleted_uids (CamelDB *db, char *folder_name, CamelException *ex); diff --git a/camel/camel-folder-search.c b/camel/camel-folder-search.c index 8762fb317..f469da82e 100644 --- a/camel/camel-folder-search.c +++ b/camel/camel-folder-search.c @@ -490,14 +490,17 @@ camel_folder_search_search(CamelFolderSearch *search, const char *expr, GPtrArra sql_query = camel_sexp_to_sql (expr); else sql_query = camel_sexp_to_sql_sexp (expr); - tmp1 = camel_db_sqlize_string(search->folder->full_name); - tmp = g_strdup_printf ("SELECT uid FROM %s %s %s", tmp1, sql_query ? "WHERE":"", sql_query?sql_query:""); + tmp1 = camel_db_sqlize_string(search->folder->folder_key); + if (CAMEL_IS_VEE_FOLDER(search->folder)) + tmp = g_strdup_printf ("SELECT vuid FROM messages where %s%s%s", sql_query?"(":"", sql_query?sql_query:"", sql_query?")":""); + else + tmp = g_strdup_printf ("SELECT uid FROM messages where (folder_key = %s)%s%s%s%s", tmp1, sql_query?" AND ":"", sql_query?"(":"", sql_query?sql_query:"", sql_query?")":""); camel_db_free_sqlized_string (tmp1); g_free (sql_query); dd(printf("Equivalent sql %s\n", tmp)); matches = g_ptr_array_new(); - cdb = (CamelDB *) (search->folder->cdb); + cdb = (CamelDB *) (search->folder->parent_store->cdb); camel_db_select (cdb, tmp, (CamelDBSelectCB) read_uid_callback, matches, ex); if (ex && camel_exception_is_set(ex)) { const char *exception = camel_exception_get_description (ex); diff --git a/camel/camel-folder-summary.c b/camel/camel-folder-summary.c index 879b185aa..83977815a 100644 --- a/camel/camel-folder-summary.c +++ b/camel/camel-folder-summary.c @@ -66,6 +66,7 @@ /* Make 5 minutes as default cache drop */ #define SUMMARY_CACHE_DROP 300 +#define log_time(x) if(camel_debug("logtime")) x; static pthread_mutex_t info_lock = PTHREAD_MUTEX_INITIALIZER; @@ -128,7 +129,7 @@ static int content_info_save(CamelFolderSummary *, FILE *, CamelMessag static void content_info_free(CamelFolderSummary *, CamelMessageContentInfo *); static int save_message_infos_to_db (CamelFolderSummary *s, CamelException *ex); -static int camel_read_mir_callback (void * ref, int ncol, char ** cols, char ** name); +int camel_read_mir_callback (void * ref, int ncol, char ** cols, char ** name); static char *next_uid_string(CamelFolderSummary *s); @@ -183,6 +184,9 @@ camel_folder_summary_init (CamelFolderSummary *s) s->meta_summary->uid_len = 20; s->cache_load_time = 0; s->timeout_handle = 0; + + s->sort_col = NULL; + s->collate = NULL; } static void free_o_name(void *key, void *value, void *data) @@ -492,12 +496,38 @@ camel_folder_summary_array(CamelFolderSummary *s) return res; } +CamelMessageInfo * +camel_folder_summary_peek_info (CamelFolderSummary *s, const char *uid) +{ + CamelMessageInfo *info = g_hash_table_lookup(s->loaded_infos, uid); + + if (info) + camel_message_info_ref(info); + return info; +} + struct _db_pass_data { CamelFolderSummary *summary; gboolean double_ref; gboolean add; /* or just insert to hashtable */ }; +int +camel_folder_summary_load_info_from_db(CamelFolderSummary *s, char *folder_key, const char *uid, gboolean vuid, CamelException *ex) +{ + struct _db_pass_data data; + int ret; + CamelDB *cdb = s->folder->parent_store->cdb; + + data.summary = s; + data.double_ref = TRUE; + data.add = FALSE; + + ret = camel_db_read_message_info_record_with_uid (cdb, folder_key, uid, &data, camel_read_mir_callback, vuid, &ex); + + return ret; +} + static CamelMessageInfo * message_info_from_uid (CamelFolderSummary *s, const char *uid) { @@ -510,33 +540,20 @@ message_info_from_uid (CamelFolderSummary *s, const char *uid) info = g_hash_table_lookup (s->loaded_infos, uid); if (!info) { - CamelDB *cdb; CamelException ex;// May be this should come from the caller char *folder_name; - struct _db_pass_data data; d(printf ("\ncamel_folder_summary_uid called \n")); camel_exception_init (&ex); s->flags &= ~CAMEL_SUMMARY_DIRTY; - folder_name = s->folder->full_name; - cdb = s->folder->cdb; + folder_name = s->folder->folder_key; CAMEL_SUMMARY_UNLOCK(s, ref_lock); CAMEL_SUMMARY_UNLOCK(s, summary_lock); - data.summary = s; - data.double_ref = TRUE; - data.add = FALSE; + camel_folder_summary_load_info_from_db (s, folder_name, uid, FALSE, &ex); - - ret = camel_db_read_message_info_record_with_uid (cdb, folder_name, uid, &data, camel_read_mir_callback, &ex); - if (ret != 0) { - // if (strcmp (folder_name, "UNMATCHED")) - //g_warning ("Unable to read uid %s from folder %s: %s", uid, folder_name, camel_exception_get_description(&ex)); - - return NULL; - } CAMEL_SUMMARY_LOCK(s, summary_lock); CAMEL_SUMMARY_LOCK(s, ref_lock); @@ -842,10 +859,23 @@ int camel_folder_summary_cache_size (CamelFolderSummary *s) { /* FIXME[disk-summary] this is a timely hack. fix it well */ - if (!CAMEL_IS_VEE_FOLDER(s->folder)) - return g_hash_table_size (s->loaded_infos); - else - return s->uids->len; + return g_hash_table_size (s->loaded_infos); +} + +int +reload_from_db (CamelFolderSummary *s, CamelException *ex) +{ + int ret; + struct _db_pass_data data; + CamelDB *cdb = s->folder->parent_store->cdb; + char *folder_name = s->folder->folder_key; + + data.summary = s; + data.double_ref = FALSE; + data.add = FALSE; + ret = camel_db_read_message_info_records (cdb, folder_name, (gpointer)&data, camel_read_mir_callback, NULL, ex); + + return ret; } int @@ -858,23 +888,19 @@ camel_folder_summary_reload_from_db (CamelFolderSummary *s, CamelException *ex) /* FIXME[disk-summary] baseclass this, and vfolders we may have to * load better. */ + gboolean virtual = CAMEL_IS_VEE_SUMMARY(s); d(printf ("\ncamel_folder_summary_reload_from_db called \n")); - folder_name = s->folder->full_name; - cdb = s->folder->cdb; - /* FIXME FOR SANKAR: No need to pass the address of summary here. */ - data.summary = s; - data.double_ref = FALSE; - data.add = FALSE; - ret = camel_db_read_message_info_records (cdb, folder_name, (gpointer)&data, camel_read_mir_callback, NULL); + + ret = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->reload_from_db(s, ex); s->cache_load_time = time (NULL); /* FIXME[disk-summary] LRU please and not timeouts */ if (!g_getenv("CAMEL_FREE_INFOS") && !s->timeout_handle) s->timeout_handle = g_timeout_add_seconds (SUMMARY_CACHE_DROP, (GSourceFunc) cfs_try_release_memory, s); - printf("Triggering summary_reloaded on %s %p\n", s->folder->full_name, s); + d(printf("Triggering summary_reloaded on %s %p\n", s->folder->full_name, s)); camel_object_trigger_event(s, "summary_reloaded", s); return ret == 0 ? 0 : -1; } @@ -906,19 +932,12 @@ camel_folder_summary_load_from_db (CamelFolderSummary *s, CamelException *ex) if (ret) return ret; - folder_name = s->folder->full_name; - cdb = s->folder->cdb; + folder_name = s->folder->folder_key; + cdb = s->folder->parent_store->cdb; - ret = camel_db_get_folder_uids (cdb, folder_name, s->uids, ex); + ret = camel_db_get_folder_uids (cdb, folder_name, s->sort_col, s->collate, s->uids, ex); /* camel_folder_summary_dump (s); */ -#if 0 - data.summary = s; - data.add = TRUE; - data.double_ref = FALSE; - ret = camel_db_read_message_info_records (cdb, folder_name, (gpointer) &data, camel_read_mir_callback, ex); -#endif - return ret == 0 ? 0 : -1; } @@ -931,6 +950,10 @@ mir_from_cols (CamelMIRecord *mir, CamelFolderSummary *s, int ncol, char ** cols if ( !strcmp (name [i], "uid") ) mir->uid = (char *) camel_pstring_strdup (cols [i]); + if ( !strcmp (name [i], "vuid") ) + mir->uid = (char *) camel_pstring_strdup (cols [i]); + else if ( !strcmp (name [i], "uid") ) + mir->folder_key = (char *) camel_pstring_strdup (cols [i]); else if ( !strcmp (name [i], "flags") ) mir->flags = cols [i] ? strtoul (cols [i], NULL, 10) : 0; else if ( !strcmp (name [i], "read") ) @@ -981,7 +1004,7 @@ mir_from_cols (CamelMIRecord *mir, CamelFolderSummary *s, int ncol, char ** cols } } -static int +int camel_read_mir_callback (void * ref, int ncol, char ** cols, char ** name) { struct _db_pass_data *data = (struct _db_pass_data *) ref; @@ -1115,7 +1138,6 @@ error: } - int camel_folder_summary_migrate_infos(CamelFolderSummary *s) { @@ -1124,7 +1146,7 @@ camel_folder_summary_migrate_infos(CamelFolderSummary *s) CamelMessageInfo *mi; CamelMessageInfoBase *info; int ret = 0; - CamelDB *cdb = s->folder->cdb; + CamelDB *cdb = s->folder->parent_store->cdb_write; CamelFIRecord *record; CamelException ex; @@ -1198,12 +1220,14 @@ camel_folder_summary_migrate_infos(CamelFolderSummary *s) if (!record) { return -1; } - + record->account_url = camel_service_get_url((CamelService *)s->folder->parent_store); + record->folder_key = camel_folder_get_hash (s->folder); ret = camel_db_write_folder_info_record (cdb, record, &ex); g_free (record->bdata); + g_free (record->account_url); g_free (record); - + if (ret != 0) { return -1; } @@ -1272,8 +1296,8 @@ save_to_db_cb (gpointer key, gpointer value, gpointer data) CamelException *ex = (CamelException *)data; CamelMessageInfoBase *mi = (CamelMessageInfoBase *)value; CamelFolderSummary *s = (CamelFolderSummary *)mi->summary; - char *folder_name = s->folder->full_name; - CamelDB *cdb = s->folder->cdb; + char *folder_name = s->folder->folder_key; + CamelDB *cdb = s->folder->parent_store->cdb_write; CamelMIRecord *mir; if (!mi->dirty) @@ -1304,10 +1328,10 @@ save_to_db_cb (gpointer key, gpointer value, gpointer data) static int save_message_infos_to_db (CamelFolderSummary *s, CamelException *ex) { - CamelDB *cdb = s->folder->cdb; + CamelDB *cdb = s->folder->parent_store->cdb_write; char *folder_name; - folder_name = s->folder->full_name; + folder_name = s->folder->folder_key; if (camel_db_prepare_message_info_table (cdb, folder_name, ex) != 0) { return -1; } @@ -1324,7 +1348,7 @@ save_message_infos_to_db (CamelFolderSummary *s, CamelException *ex) int camel_folder_summary_save_to_db (CamelFolderSummary *s, CamelException *ex) { - CamelDB *cdb = s->folder->cdb; + CamelDB *cdb = s->folder->parent_store->cdb_write; CamelFIRecord *record; int ret, count; @@ -1340,6 +1364,7 @@ camel_folder_summary_save_to_db (CamelFolderSummary *s, CamelException *ex) return camel_folder_summary_header_save_to_db (s, ex); printf("Saving %d/%d dirty records of %s\n", count, g_hash_table_size (s->loaded_infos), s->folder->full_name); + log_time(printf("Summary save to db for %s: start %ld\n", s->folder ? s->folder->full_name : "NULL", time(NULL))); camel_db_begin_transaction (cdb, ex); @@ -1352,16 +1377,19 @@ camel_folder_summary_save_to_db (CamelFolderSummary *s, CamelException *ex) } camel_db_end_transaction (cdb, ex); + log_time(printf("Summary save to db for %s: end-summary %ld\n", s->folder ? s->folder->full_name : "NULL", time(NULL))); record = (((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->summary_header_to_db (s, ex)); if (!record) { s->flags |= CAMEL_SUMMARY_DIRTY; return -1; } - + record->account_url = camel_service_get_url((CamelService *)s->folder->parent_store); + record->folder_key = camel_folder_get_hash (s->folder); camel_db_begin_transaction (cdb, ex); ret = camel_db_write_folder_info_record (cdb, record, ex); g_free (record->bdata); + g_free (record->account_url); g_free (record); if (ret != 0) { @@ -1371,6 +1399,7 @@ camel_folder_summary_save_to_db (CamelFolderSummary *s, CamelException *ex) } camel_db_end_transaction (cdb, ex); + log_time(printf("Summary save to db for %s: end-header %ld\n", s->folder ? s->folder->full_name : "NULL", time(NULL))); return ret; } @@ -1378,7 +1407,7 @@ camel_folder_summary_save_to_db (CamelFolderSummary *s, CamelException *ex) int camel_folder_summary_header_save_to_db (CamelFolderSummary *s, CamelException *ex) { - CamelDB *cdb = s->folder->cdb; + CamelDB *cdb = s->folder->parent_store->cdb_write; CamelFIRecord *record; int ret; @@ -1388,10 +1417,12 @@ camel_folder_summary_header_save_to_db (CamelFolderSummary *s, CamelException *e if (!record) { return -1; } - + record->account_url = camel_service_get_url((CamelService *)s->folder->parent_store); + record->folder_key = camel_folder_get_hash (s->folder); camel_db_begin_transaction (cdb, ex); ret = camel_db_write_folder_info_record (cdb, record, ex); g_free (record->bdata); + g_free (record->account_url); g_free (record); if (ret != 0) { @@ -1553,6 +1584,7 @@ camel_folder_summary_header_load_from_db (CamelFolderSummary *s, CamelStore *sto CamelDB *cdb; CamelFIRecord *record; int ret = 0; + char *url = camel_service_get_url((CamelService *)store); d(printf ("\ncamel_folder_summary_load_from_db called \n")); s->flags &= ~CAMEL_SUMMARY_DIRTY; @@ -1560,7 +1592,7 @@ camel_folder_summary_header_load_from_db (CamelFolderSummary *s, CamelStore *sto cdb = store->cdb; record = g_new0 (CamelFIRecord, 1); - camel_db_read_folder_info_record (cdb, folder_name, &record, ex); + camel_db_read_folder_info_record (cdb, url, folder_name, &record, ex); if (record) { if ( ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->summary_header_from_db (s, record) == -1) @@ -1572,6 +1604,7 @@ camel_folder_summary_header_load_from_db (CamelFolderSummary *s, CamelStore *sto g_free (record->folder_name); g_free (record->bdata); g_free (record); + g_free (url); return ret; } @@ -2065,12 +2098,13 @@ camel_folder_summary_clear_db (CamelFolderSummary *s) { CamelDB *cdb; char *folder_name; + char *url = camel_service_get_url(s->folder->parent_store); d(printf ("\ncamel_folder_summary_load_from_db called \n")); s->flags &= ~CAMEL_SUMMARY_DIRTY; - folder_name = s->folder->full_name; - cdb = s->folder->cdb; + folder_name = s->folder->folder_key; + cdb = s->folder->parent_store->cdb_write; CAMEL_SUMMARY_LOCK(s, summary_lock); if (camel_folder_summary_count(s) == 0) { @@ -2087,7 +2121,8 @@ camel_folder_summary_clear_db (CamelFolderSummary *s) CAMEL_SUMMARY_UNLOCK(s, summary_lock); - camel_db_clear_folder_summary (cdb, folder_name, NULL); + camel_db_clear_folder_summary (cdb, url, s->folder->full_name, folder_name, NULL); + g_free (url); } @@ -2137,7 +2172,7 @@ camel_folder_summary_remove (CamelFolderSummary *s, CamelMessageInfo *info) s->meta_summary->msg_expunged = TRUE; CAMEL_SUMMARY_UNLOCK(s, summary_lock); - if (!ret && camel_db_delete_uid (s->folder->cdb, s->folder->full_name, camel_message_info_uid(info), NULL) != 0) + if (!ret && camel_db_delete_uid (s->folder->parent_store->cdb_write, s->folder->folder_key, camel_message_info_uid(info), NULL) != 0) return ; camel_message_info_free(info); @@ -2174,7 +2209,7 @@ camel_folder_summary_remove_uid(CamelFolderSummary *s, const char *uid) CAMEL_SUMMARY_UNLOCK(s, ref_lock); CAMEL_SUMMARY_UNLOCK(s, summary_lock); - if (!ret && camel_db_delete_uid (s->folder->cdb, s->folder->full_name, tmpid, NULL) != 0) { + if (!ret && camel_db_delete_uid (s->folder->parent_store->cdb_write, s->folder->folder_key, tmpid, NULL) != 0) { g_free(tmpid); return ; } @@ -2298,8 +2333,8 @@ camel_folder_summary_remove_range (CamelFolderSummary *s, int start, int end) } camel_exception_init (&ex); - folder_name = s->folder->full_name; - cdb = s->folder->cdb; + folder_name = s->folder->folder_key; + cdb = s->folder->parent_store->cdb_write; /* FIXME[disk-summary] lifecycle of infos should be checked. * Add should add to db and del should del to db. Sync only @@ -2615,13 +2650,14 @@ summary_header_to_db (CamelFolderSummary *s, CamelException *ex) CamelDB *db; char *table_name; - db = s->folder->cdb; + /* Though we gonna read, we would do it while saving. Lets not block the thread. */ + db = s->folder->parent_store->cdb_write; //table_name = safe_table (camel_file_util_safe_filename (s->folder->full_name)); - table_name = s->folder->full_name; + table_name = s->folder->folder_key; io(printf("Savining header to db\n")); - record->folder_name = table_name; + record->folder_name = s->folder->full_name; /* we always write out the current version */ record->version = CAMEL_FOLDER_SUMMARY_VERSION; @@ -2999,7 +3035,7 @@ message_info_from_db (CamelFolderSummary *s, CamelMIRecord *record) /* Extract User flags/labels */ part = record->labels; - if (part) { + if (part && *part) { label = part; for (i=0;part[i];i++) { @@ -3147,6 +3183,7 @@ message_info_to_db (CamelFolderSummary *s, CamelMessageInfo *info) record->replied = mi->flags & CAMEL_MESSAGE_ANSWERED ? 1 : 0; record->important = mi->flags & CAMEL_MESSAGE_FLAGGED ? 1 : 0; record->junk = mi->flags & CAMEL_MESSAGE_JUNK ? 1 : 0; + record->dirty = mi->flags & CAMEL_MESSAGE_FOLDER_FLAGGED ? 1 : 0; record->attachment = mi->flags & CAMEL_MESSAGE_ATTACHMENTS ? 1 : 0; record->size = mi->size; @@ -4789,7 +4826,8 @@ camel_folder_summary_class_init (CamelFolderSummaryClass *klass) klass->message_info_free = message_info_free; klass->message_info_clone = message_info_clone; klass->message_info_from_uid = message_info_from_uid; - + klass->reload_from_db = reload_from_db; + klass->content_info_new_from_header = content_info_new_from_header; klass->content_info_new_from_parser = content_info_new_from_parser; klass->content_info_new_from_message = content_info_new_from_message; diff --git a/camel/camel-folder-summary.h b/camel/camel-folder-summary.h index 0f23ea6cb..370491725 100644 --- a/camel/camel-folder-summary.h +++ b/camel/camel-folder-summary.h @@ -247,6 +247,10 @@ struct _CamelFolderSummary { struct _CamelFolderMetaSummary *meta_summary; /* Meta summary */ time_t cache_load_time; guint timeout_handle; + + /* Sort */ + char *sort_col; + char *collate; }; struct _CamelFolderSummaryClass { @@ -283,6 +287,8 @@ struct _CamelFolderSummaryClass { int (*content_info_save)(CamelFolderSummary *, FILE *, CamelMessageContentInfo *); void (*content_info_free)(CamelFolderSummary *, CamelMessageContentInfo *); CamelMessageInfo * (*message_info_from_uid) (CamelFolderSummary *, const char *); + int * (*reload_from_db) (CamelFolderSummary *, CamelException *); + /* get the next uid */ char *(*next_uid_string)(CamelFolderSummary *); diff --git a/camel/camel-folder.c b/camel/camel-folder.c index de9ce8543..bd6e74aa7 100644 --- a/camel/camel-folder.c +++ b/camel/camel-folder.c @@ -183,6 +183,7 @@ camel_folder_init (gpointer object, gpointer klass) folder->priv->changed_frozen = camel_folder_change_info_new(); g_static_rec_mutex_init(&folder->priv->lock); g_static_mutex_init(&folder->priv->change_lock); + folder->folder_key = NULL; } static void @@ -194,7 +195,7 @@ camel_folder_finalize (CamelObject *object) g_free(camel_folder->name); g_free(camel_folder->full_name); g_free(camel_folder->description); - + g_free (camel_folder->folder_key); if (camel_folder->parent_store) camel_object_unref (camel_folder->parent_store); @@ -205,11 +206,6 @@ camel_folder_finalize (CamelObject *object) camel_folder_change_info_free(p->changed_frozen); - if (camel_folder->cdb) { - camel_db_close (camel_folder->cdb); - camel_folder->cdb = NULL; - } - g_static_rec_mutex_free(&p->lock); g_static_mutex_free(&p->change_lock); @@ -263,37 +259,8 @@ camel_folder_construct (CamelFolder *folder, CamelStore *parent_store, folder->name = g_strdup (name); folder->full_name = g_strdup (full_name); + camel_folder_get_hash (folder); - store_db_path = g_build_filename (service->url->path, CAMEL_DB_FILE, NULL); - camel_exception_init(&ex); - if (strlen (store_db_path) < 2) { - char *store_path = camel_session_get_storage_path ((CamelSession *)camel_service_get_session (service), service, &ex); - - g_free (store_db_path); - store_db_path = g_build_filename (store_path, CAMEL_DB_FILE, NULL); - g_free (store_path); - } - - folder->cdb = camel_db_open (store_db_path, &ex); - if (camel_exception_is_set (&ex)) { - char *store_path; - - g_print ("Failure for store_db_path : [%s]\n", store_db_path); - g_free (store_db_path); - - store_path = camel_session_get_storage_path ((CamelSession *)camel_service_get_session (service), service, &ex); - store_db_path = g_build_filename (store_path, CAMEL_DB_FILE, NULL); - g_free (store_path); - camel_exception_clear(&ex); - folder->cdb = camel_db_open (store_db_path, &ex); - if (camel_exception_is_set (&ex)) { - g_print("Retry with %s failed\n", store_db_path); - g_free(store_db_path); - camel_exception_clear(&ex); - return; - } - } - g_free (store_db_path); } @@ -1589,7 +1556,8 @@ void camel_folder_delete (CamelFolder *folder) { g_return_if_fail (CAMEL_IS_FOLDER (folder)); - + char *url; + CAMEL_FOLDER_REC_LOCK (folder, lock); if (folder->folder_flags & CAMEL_FOLDER_HAS_BEEN_DELETED) { CAMEL_FOLDER_REC_UNLOCK (folder, lock); @@ -1603,8 +1571,9 @@ camel_folder_delete (CamelFolder *folder) CAMEL_FOLDER_REC_UNLOCK (folder, lock); /* Delete the references of the folder from the DB.*/ - camel_db_delete_folder (folder->cdb, folder->full_name, NULL); - + url = camel_service_get_url(folder->parent_store); + camel_db_clear_folder_summary (folder->parent_store->cdb_write, url, folder->full_name, folder->folder_key, NULL); + g_free(url); camel_object_trigger_event (folder, "deleted", NULL); } @@ -1637,11 +1606,13 @@ void camel_folder_rename(CamelFolder *folder, const char *new) { char *old; - + char *url = camel_service_get_url(folder->parent_store); old = g_strdup(folder->full_name); CF_CLASS (folder)->rename(folder, new); - camel_db_rename_folder (folder->cdb, old, new, NULL); + #warning "DBV2 FOLDER RENAME WONT WORK" + camel_db_rename_folder (folder->parent_store->cdb, url, old, new, NULL); + g_free(url); camel_object_trigger_event (folder, "renamed", old); g_free(old); } @@ -2115,6 +2086,59 @@ camel_folder_free_deep (CamelFolder *folder, GPtrArray *array) } +char * +camel_folder_hash(CamelStore *store, char *folder_name, char buffer[8]) +{ + GChecksum *checksum; + guint8 *digest; + gsize length; + int state = 0, save = 0; + char *tmp; + int i; + + length = g_checksum_type_get_length (G_CHECKSUM_MD5); + digest = g_alloca (length); + + checksum = g_checksum_new (G_CHECKSUM_MD5); + tmp = camel_service_get_url((CamelService *)store); + g_checksum_update (checksum, (guchar *) tmp, -1); + g_free (tmp); + g_checksum_update (checksum, (guchar *) folder_name, -1); + g_checksum_get_digest (checksum, digest, &length); + g_checksum_free (checksum); + + g_base64_encode_step (digest, 6, FALSE, buffer, &state, &save); + g_base64_encode_close (FALSE, buffer, &state, &save); + + for (i=0;i<8;i++) { + if (buffer[i] == '+') + buffer[i] = '.'; + if (buffer[i] == '/') + buffer[i] = '_'; + } +} + +char * +camel_folder_make_hash(CamelFolder *folder, char buffer[8]) +{ + camel_folder_hash (folder->parent_store, folder->full_name, buffer); +} + +const char * +camel_folder_get_hash(CamelFolder *folder) +{ + char buffer[8]; + + if (folder->folder_key) + return folder->folder_key; + + camel_folder_make_hash (folder, buffer); + folder->folder_key = g_strdup_printf("%c%c%c%c%c%c%c%c", buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7]); + + return folder->folder_key; + +} + /** * camel_folder_change_info_new: * diff --git a/camel/camel-folder.h b/camel/camel-folder.h index afa9ca231..995bc21b1 100644 --- a/camel/camel-folder.h +++ b/camel/camel-folder.h @@ -109,7 +109,7 @@ struct _CamelFolder { guint32 folder_flags; guint32 permanent_flags; - CamelDB *cdb; + char *folder_key; }; #define CAMEL_FOLDER_HAS_SUMMARY_CAPABILITY (1<<0) @@ -369,6 +369,12 @@ void camel_folder_change_info_remove_uid (CamelFolderChangeInfo *info, const c void camel_folder_change_info_change_uid (CamelFolderChangeInfo *info, const char *uid); void camel_folder_change_info_recent_uid (CamelFolderChangeInfo *info, const char *uid); +/* Hash */ + +const char * camel_folder_get_hash(CamelFolder *folder); +char * camel_folder_make_hash(CamelFolder *folder, char buffer[8]); +char * camel_folder_hash(CamelStore *store, char *folder_name, char buffer[8]); + G_END_DECLS #endif /* CAMEL_FOLDER_H */ diff --git a/camel/camel-search-sql-sexp.c b/camel/camel-search-sql-sexp.c index 7dcff529c..e6d21a86c 100644 --- a/camel/camel-search-sql-sexp.c +++ b/camel/camel-search-sql-sexp.c @@ -534,6 +534,26 @@ get_size (struct _ESExp *f, int argc, struct _ESExpResult **argv, void *data) return r; } +static ESExpResult * +sql_exp (struct _ESExp *f, int argc, struct _ESExpResult **argv, void *data) +{ + ESExpResult *r; + int i; + GString *str = g_string_new (NULL); + + d(printf("executing sql-exp\n")); + + r = e_sexp_result_new(f, ESEXP_RES_STRING); + for (i=0;i<argc;i++) { + if (argv[i]->type == ESEXP_RES_STRING && argv[i]->value.string) + g_string_append (str, argv[i]->value.string); + } + r->value.string = str->str; + g_string_free (str, FALSE); + + return r; +} + /* 'builtin' functions */ static struct { char *name; @@ -562,6 +582,7 @@ static struct { { "get-received-date", get_received_date, 0}, { "get-current-date", get_current_date, 0}, { "get-size", get_size, 0}, + { "sql-exp", sql_exp, 0}, /* { "uid", CAMEL_STRUCT_OFFSET(CamelFolderSearchClass, uid), 1 }, */ }; @@ -704,7 +725,9 @@ int main () "(not (or (header-matches \"from\" \"bugzilla-daemon@bugzilla.ximian.com\") (header-matches \"from\" \"bugzilla-daemon@bugzilla.gnome.org\") (header-matches \"from\" \"bugzilla_noreply@novell.com\") (header-matches \"from\" \"bugzilla-daemon@mozilla.org\") (header-matches \"from\" \"root@dist.suse.de\") (header-matches \"from\" \"root@hilbert3.suse.de\") (header-matches \"from\" \"root@hilbert4.suse.de\") (header-matches \"from\" \"root@hilbert5.suse.de\") (header-matches \"from\" \"root@hilbert6.suse.de\") (header-matches \"from\" \"root@suse.de\") (header-matches \"from\" \"swamp_noreply@suse.de\") (and (header-matches \"from\" \"hermes@opensuse.org\") (header-starts-with \"subject\" \"submit-Request\"))))", "(and (match-threads \"replies_parents\" (and (match-all (or (header-matches \"to\" \"maw@ximian.com\") (header-matches \"to\" \"mw@ximian.com\") (header-matches \"to\" \"maw@novell.com\") (header-matches \"to\" \"maw.AMERICAS3.AMERICAS@novell.com\") (header-matches \"cc\" \"maw@ximian.com\") (header-matches \"cc\" \"mw@ximian.com\") (header-matches \"cc\" \"maw@novell.com\") (header-matches \"cc\" \"maw.AMERICAS3.AMERICAS@novell.com\"))) (match-all (not (or (header-matches \"from\" \"bugzilla-daemon@bugzilla.ximian.com\") (header-matches \"from\" \"bugzilla-daemon@bugzilla.gnome.org\") (header-matches \"from\" \"bugzilla_noreply@novell.com\") (header-matches \"from\" \"bugzilla-daemon@mozilla.org\") (header-matches \"from\" \"root@dist.suse.de\") (header-matches \"from\" \"root@hilbert3.suse.de\") (header-matches \"from\" \"root@hilbert4.suse.de\") (header-matches \"from\" \"root@hilbert5.suse.de\") (header-matches \"from\" \"root@hilbert6.suse.de\") (header-matches \"from\" \"root@suse.de\") (header-matches \"from\" \"swamp_noreply@suse.de\") (and (header-matches \"from\" \"hermes@opensuse.org\") (header-starts-with \"subject\" \"submit-Request\"))))) (match-all (> (get-sent-date) (- (get-current-date) 1209600))) )) (match-all (and (not (system-flag \"deleted\")) (not (system-flag \"junk\")))))", "and ((match-all (system-flag \"Deleted\")) (match-all (system-flag \"junk\")))", - "(and (match-threads \"replies_parents\" (and (match-all (or (header-matches \"to\" \"maw@ximian.com\")))))))" + "(and (match-threads \"replies_parents\" (and (match-all (or (header-matches \"to\" \"maw@ximian.com\")))))))", + "(and (sql-exp \"folder_key = 'ASDGASd' AND folder_key = 'DSFWEA'\") (match-threads \"replies_parents\" (and (match-all (or (header-matches \"to\" \"maw@ximian.com\")))))))" + }; for (i=0; i < G_N_ELEMENTS(txt); i++) { diff --git a/camel/camel-session.c b/camel/camel-session.c index 4c91bcac1..3f7e64a76 100644 --- a/camel/camel-session.c +++ b/camel/camel-session.c @@ -80,6 +80,7 @@ camel_session_init (CamelSession *session) session->priv->thread_active = g_hash_table_new(NULL, NULL); session->priv->thread_pool = NULL; session->priv->junk_headers = NULL; + } static void @@ -154,6 +155,8 @@ void camel_session_construct (CamelSession *session, const char *storage_path) { session->storage_path = g_strdup (storage_path); + /* Init the DB */ + camel_db_setup (session->storage_path, NULL); } static CamelService * diff --git a/camel/camel-store.c b/camel/camel-store.c index a1e702799..51f0fc6a1 100644 --- a/camel/camel-store.c +++ b/camel/camel-store.c @@ -163,7 +163,10 @@ camel_store_finalize (CamelObject *object) camel_db_close (store->cdb); store->cdb = NULL; } - + if (store->cdb_write) { + camel_db_close (store->cdb_write); + store->cdb_write = NULL; + } g_free (store->priv); } @@ -212,48 +215,8 @@ construct (CamelService *service, CamelSession *session, if (camel_exception_is_set (ex)) return; - store_db_path = g_build_filename (service->url->path, CAMEL_DB_FILE, NULL); - - if (!service->url->path || strlen (store_db_path) < 2) { - store_path = camel_session_get_storage_path (session, service, ex); - - g_free (store_db_path); - store_db_path = g_build_filename (store_path, CAMEL_DB_FILE, NULL); - } - - if (!g_file_test (service->url->path ? service->url->path : store_path, G_FILE_TEST_EXISTS)) { - /* Cache might be blown. Recreate. */ - g_mkdir_with_parents (service->url->path ? service->url->path : store_path, S_IRWXU); - } - - g_free (store_path); - - store->cdb = camel_db_open (store_db_path, ex); - printf("store_db_path %s\n", store_db_path); - if (camel_exception_is_set (ex)) { - char *store_path; - - g_print ("Failure for store_db_path : [%s]\n", store_db_path); - g_free (store_db_path); - - store_path = camel_session_get_storage_path (session, service, ex); - store_db_path = g_build_filename (store_path, CAMEL_DB_FILE, NULL); - g_free (store_path); - camel_exception_clear(ex); - store->cdb = camel_db_open (store_db_path, ex); - if (camel_exception_is_set (ex)) { - g_print("Retry with %s failed\n", store_db_path); - g_free(store_db_path); - camel_exception_clear(ex); - return; - } - } - g_free (store_db_path); - - if (camel_db_create_folders_table (store->cdb, ex)) - printf ("something went wrong terribly\n"); - else - printf ("folders table successfully created \n"); + store->cdb = camel_db_get_handle (ex); + store->cdb_write = camel_db_get_handle (ex); if (camel_exception_is_set (ex)) return; diff --git a/camel/camel-store.h b/camel/camel-store.h index df0b012b9..ed7b45d48 100644 --- a/camel/camel-store.h +++ b/camel/camel-store.h @@ -123,6 +123,7 @@ struct _CamelStore { CamelObjectBag *folders; CamelDB *cdb; + CamelDB *cdb_write; guint32 flags; guint32 mode; diff --git a/camel/camel-vee-folder.c b/camel/camel-vee-folder.c index ca1826164..f9d204437 100644 --- a/camel/camel-vee-folder.c +++ b/camel/camel-vee-folder.c @@ -111,6 +111,7 @@ camel_vee_folder_construct (CamelVeeFolder *vf, CamelStore *parent_store, const vf->flags = flags; camel_folder_construct(folder, parent_store, full, name); + vf->folder_keys = g_ptr_array_new (); folder->summary = camel_vee_summary_new(folder); @@ -192,7 +193,9 @@ camel_vee_folder_add_folder(CamelVeeFolder *vf, CamelFolder *sub) if (g_list_find(p->folders, sub) == NULL) { camel_object_ref((CamelObject *)sub); p->folders = g_list_append(p->folders, sub); - + printf("adding %s %s for %s\n", sub->full_name, sub->folder_key, ((CamelFolder *)vf)->full_name); + g_ptr_array_add (vf->folder_keys, sub->folder_key); + g_hash_table_insert (vf->hashes, sub->folder_key, sub); CAMEL_FOLDER_LOCK(vf, change_lock); /* update the freeze state of 'sub' to match our freeze state */ @@ -219,19 +222,12 @@ camel_vee_folder_add_folder(CamelVeeFolder *vf, CamelFolder *sub) d(printf("camel_vee_folder_add_folder(%s, %s)\n", ((CamelFolder *)vf)->full_name, sub->full_name)); - cache = camel_folder_summary_cache_size(sub->summary); - if (!cache) { - camel_object_hook_event(sub->summary, "summary_reloaded", summary_reloaded, vf); - g_hash_table_insert(vf->loaded, sub, GINT_TO_POINTER(1)); - } camel_object_hook_event((CamelObject *)sub, "folder_changed", (CamelObjectEventHookFunc)folder_changed, vf); camel_object_hook_event((CamelObject *)sub, "deleted", (CamelObjectEventHookFunc)subfolder_deleted, vf); camel_object_hook_event((CamelObject *)sub, "renamed", (CamelObjectEventHookFunc)folder_renamed, vf); ((CamelVeeFolderClass *)((CamelObject *)vf)->klass)->add_folder(vf, sub); - if (cache) - summary_reloaded((CamelObject *) sub->summary, (void *)sub->summary, (void *)vf); } /** @@ -264,13 +260,12 @@ camel_vee_folder_remove_folder(CamelVeeFolder *vf, CamelFolder *sub) camel_object_unhook_event((CamelObject *)sub, "folder_changed", (CamelObjectEventHookFunc) folder_changed, vf); camel_object_unhook_event((CamelObject *)sub, "deleted", (CamelObjectEventHookFunc) subfolder_deleted, vf); camel_object_unhook_event((CamelObject *)sub, "renamed", (CamelObjectEventHookFunc) folder_renamed, vf); - if (GPOINTER_TO_INT(g_hash_table_lookup (vf->loaded, sub))) { - g_hash_table_remove (vf->loaded, sub); - camel_object_unhook_event((CamelObject *)sub->summary, "summary_reloaded", (CamelObjectEventHookFunc) summary_reloaded, vf); - } + p->folders = g_list_remove(p->folders, sub); - + g_ptr_array_remove_fast (vf->folder_keys, sub->folder_key); + g_hash_table_remove (vf->hashes, sub->folder_key); + /* undo the freeze state that we have imposed on this source folder */ CAMEL_FOLDER_LOCK(vf, change_lock); for (i = 0; i < ((CamelFolder *)vf)->priv->frozen; i++) @@ -329,7 +324,7 @@ camel_vee_folder_remove_folder(CamelVeeFolder *vf, CamelFolder *sub) int camel_vee_folder_rebuild_folder(CamelVeeFolder *vf, CamelFolder *sub, CamelException *ex) { - return ((CamelVeeFolderClass *)((CamelObject *)vf)->klass)->rebuild_folder(vf, sub, ex); + //return ((CamelVeeFolderClass *)((CamelObject *)vf)->klass)->rebuild_folder(vf, sub, ex); } static void @@ -438,7 +433,7 @@ camel_vee_folder_get_location(CamelVeeFolder *vf, const CamelVeeMessageInfo *vin { CamelFolder *folder; - folder = vinfo->summary->folder; + folder = g_hash_table_lookup(vf->hashes, vinfo->folder_key); /* locking? yes? no? although the vfolderinfo is valid when obtained the folder in it might not necessarily be so ...? */ @@ -452,7 +447,7 @@ camel_vee_folder_get_location(CamelVeeFolder *vf, const CamelVeeMessageInfo *vin return res; } else { if (realuid) - *realuid = g_strdup(camel_message_info_uid(vinfo)+8); + *realuid = g_strdup(camel_message_info_uid(vinfo)); return folder; } @@ -504,17 +499,10 @@ count_result (CamelFolderSummary *summary, char *query, CamelException *ex) CamelVeeFolder *vf = (CamelVeeFolder *)folder; int count=0; char *expr = g_strdup_printf ("(and %s %s)", vf->expression ? vf->expression : "", query); - GList *node; - struct _CamelVeeFolderPrivate *p = _PRIVATE(vf); - - node = p->folders; - while (node) { - CamelFolder *f = node->data; - count += count_folder(f, expr, ex); - node = node->next; - } + count = count_folder(vf, expr, ex); g_free(expr); + return count; } @@ -537,7 +525,7 @@ summary_header_to_db (CamelFolderSummary *s, CamelException *ex) record->time = s->time; record->saved_count = s->uids->len; - if (!(((CamelVeeSummary *) s)->force_counts) && !g_getenv("FORCE_VFOLDER_COUNT")) { + if (!(((CamelVeeSummary *) s)->force_counts) && !g_getenv("FORCE_VFOLDER_COUNT") && 0) { /* We should be in sync always. so use the count. Don't search.*/ record->junk_count = s->junk_count; record->deleted_count = s->deleted_count; @@ -559,7 +547,7 @@ summary_header_to_db (CamelFolderSummary *s, CamelException *ex) record->jnd_count = s->junk_not_deleted_count; } - d(printf("%s %d %d %d %d %d\n", s->folder->full_name, record->junk_count, record->deleted_count, record->unread_count, record->visible_count, record->jnd_count)); + printf("VFC %s %d %d %d %d %d\n", s->folder->full_name, record->junk_count, record->deleted_count, record->unread_count, record->visible_count, record->jnd_count); return record; } @@ -570,6 +558,8 @@ vee_sync(CamelFolder *folder, gboolean expunge, CamelException *ex) struct _CamelVeeFolderPrivate *p = _PRIVATE(vf); GList *node; + camel_folder_summary_save_to_db (folder->summary, ex); + CAMEL_VEE_FOLDER_LOCK(vf, subfolder_lock); node = p->folders; @@ -630,7 +620,8 @@ vee_get_message(CamelFolder *folder, const char *uid, CamelException *ex) mi = (CamelVeeMessageInfo *)camel_folder_summary_uid(folder->summary, uid); if (mi) { - msg = camel_folder_get_message(mi->summary->folder, camel_message_info_uid(mi)+8, ex); + CamelFolder *lfolder = g_hash_table_lookup(((CamelVeeFolder *)folder)->hashes, mi->folder_key); + msg = camel_folder_get_message(lfolder, camel_message_info_uid(mi), ex); camel_message_info_free((CamelMessageInfo *)mi); } else { camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, @@ -641,6 +632,23 @@ vee_get_message(CamelFolder *folder, const char *uid, CamelException *ex) return msg; } +static char * +make_folder_keys (GPtrArray *array) +{ + int i; + GString *str = g_string_new(NULL); + char *ret; + + g_string_append_printf (str, "\"(folder_key = '%s'", array->pdata[0]); + for (i=1; i<array->len; i++) + g_string_append_printf (str, " OR folder_key = '%s'", array->pdata[i]); + g_string_append (str, ")\""); + ret = str->str; + g_string_free(str, FALSE); + + return ret; +} + static GPtrArray * vee_search_by_expression(CamelFolder *folder, const char *expression, CamelException *ex) { @@ -651,45 +659,28 @@ vee_search_by_expression(CamelFolder *folder, const char *expression, CamelExcep struct _CamelVeeFolderPrivate *p = _PRIVATE(vf); GHashTable *searched = g_hash_table_new(NULL, NULL); CamelVeeFolder *folder_unmatched = vf->parent_vee_store ? vf->parent_vee_store->folder_unmatched : NULL; + char *fexp = NULL; - if (vf != folder_unmatched) - expr = g_strdup_printf ("(and %s %s)", vf->expression ? vf->expression : "", expression); - else - expr = g_strdup (expression); - - node = p->folders; - while (node) { - CamelFolder *f = node->data; - int i; - char hash[8]; - - /* make sure we only search each folder once - for unmatched folder to work right */ - if (g_hash_table_lookup(searched, f) == NULL) { - camel_vee_folder_hash_folder(f, hash); - matches = camel_folder_search_by_expression(f, expr, ex); - if (matches) { - for (i = 0; i < matches->len; i++) { - char *uid = matches->pdata[i], *vuid; - - vuid = g_malloc(strlen(uid)+9); - memcpy(vuid, hash, 8); - strcpy(vuid+8, uid); - g_ptr_array_add(result, (gpointer) camel_pstring_strdup(vuid)); - g_free (vuid); - } - camel_folder_search_free(f, matches); - } - g_hash_table_insert(searched, f, f); + if (vf->folder_keys->len) + fexp = make_folder_keys (vf->folder_keys); + + if (vf != folder_unmatched) { + if (fexp) { + expr = g_strdup_printf ("(and (sql-exp %s) %s %s)", fexp, vf->expression ? vf->expression : "", expression); + } else { + expr = g_strdup_printf ("(and (sql-exp \"folder_key = 'empty' \")%s %s)", vf->expression ? vf->expression : "", expression); } - node = g_list_next(node); - } + } else + expr = g_strdup (expression); + g_free (fexp); + camel_folder_search_set_folder (vf->search, folder); + matches = camel_folder_search_search (vf->search, expr, NULL, ex); g_free(expr); - g_hash_table_destroy(searched); - d(printf("returning %d\n", result->len)); - return result; + d(printf("returning %d\n", matches->len)); + return matches; } static GPtrArray * @@ -808,7 +799,7 @@ vee_folder_add_uid(CamelVeeFolder *vf, CamelFolder *f, const char *inuid, const { CamelVeeMessageInfo *mi = NULL; - mi = camel_vee_summary_add((CamelVeeSummary *)((CamelFolder *)vf)->summary, f->summary, (char *)inuid, hash); + //mi = camel_vee_summary_add((CamelVeeSummary *)((CamelFolder *)vf)->summary, f->summary, (char *)inuid, hash); return mi; } @@ -855,7 +846,7 @@ vee_folder_remove_folder(CamelVeeFolder *vf, CamelFolder *source) CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *)camel_folder_summary_index(((CamelFolder *)folder_unmatched)->summary, i); if (mi) { - if (mi->summary == ssummary) { + if (1) { camel_folder_change_info_remove_uid(folder_unmatched->changes, camel_message_info_uid(mi)); if (last == -1) { last = start = i; @@ -876,6 +867,7 @@ vee_folder_remove_folder(CamelVeeFolder *vf, CamelFolder *source) } /*FIXME: This can be optimized a lot like, searching for UID in the summary uids */ +#if 0 start = -1; last = -1; count = camel_folder_summary_count(folder->summary); @@ -926,7 +918,7 @@ vee_folder_remove_folder(CamelVeeFolder *vf, CamelFolder *source) if (last != -1) camel_folder_summary_remove_range(folder->summary, start, last); - +#endif COUNT_DEL_EXPR(folder->summary->junk_count, "(match-all (system-flag \"junk\"))"); COUNT_DEL_EXPR(folder->summary->deleted_count, "(match-all (system-flag \"deleted\"))"); COUNT_DEL_EXPR(folder->summary->unread_count, "(match-all (not (system-flag \"Seen\")))"); @@ -1018,7 +1010,7 @@ folder_added_uid(char *uidin, void *value, struct _update_data *u) } } - +#if 0 /* build query contents for a single folder */ static int vee_rebuild_folder(CamelVeeFolder *vf, CamelFolder *source, CamelException *ex) @@ -1208,7 +1200,7 @@ vee_rebuild_folder(CamelVeeFolder *vf, CamelFolder *source, CamelException *ex) return 0; } - +#endif /* (match-folder "folder1" "folder2") @@ -1350,7 +1342,7 @@ folder_changed_remove_uid(CamelFolder *sub, const char *uid, const char hash[8], vinfo = (CamelVeeMessageInfo *) camel_folder_summary_uid (((CamelFolder *) vf)->summary, vuid); if (vinfo) { - update_summary (vinfo, vinfo->old_flags, 0, FALSE, FALSE); + // update_summary (vinfo, vinfo->old_flags, 0, FALSE, FALSE); camel_message_info_free((CamelMessageInfo *)vinfo); } camel_folder_change_info_remove_uid(vf->changes, vuid); @@ -1364,7 +1356,7 @@ folder_changed_remove_uid(CamelFolder *sub, const char *uid, const char hash[8], n = GPOINTER_TO_INT (oldval); if (n == 1) { g_hash_table_remove(unmatched_uids, oldkey); - if (vee_folder_add_uid(folder_unmatched, sub, uid, hash)) + //if (vee_folder_add_uid(folder_unmatched, sub, uid, hash)) camel_folder_change_info_add_uid(folder_unmatched->changes, oldkey); g_free(oldkey); } else { @@ -1383,7 +1375,7 @@ folder_changed_remove_uid(CamelFolder *sub, const char *uid, const char hash[8], vinfo = (CamelVeeMessageInfo *)camel_folder_get_message_info((CamelFolder *)folder_unmatched, vuid); if (vinfo) { camel_folder_change_info_remove_uid(folder_unmatched->changes, vuid); - camel_folder_summary_remove_uid(((CamelFolder *)folder_unmatched)->summary, vuid); + //camel_folder_summary_remove_uid(((CamelFolder *)folder_unmatched)->summary, vuid); camel_folder_free_message_info((CamelFolder *)folder_unmatched, (CamelMessageInfo *)vinfo); } } @@ -1410,7 +1402,7 @@ folder_changed_change_uid(CamelFolder *sub, const char *uid, const char hash[8], info = camel_folder_get_message_info(sub, uid); if (info) { if (vinfo) { - guint32 of = vinfo->old_flags; + guint32 of = 1;//vinfo->old_flags; camel_folder_change_info_change_uid(vf->changes, vuid); update_summary (vinfo, camel_message_info_flags(info), of, FALSE /* Doesn't matter */, TRUE); camel_message_info_free((CamelMessageInfo *)vinfo); @@ -1418,7 +1410,7 @@ folder_changed_change_uid(CamelFolder *sub, const char *uid, const char hash[8], if (uinfo) { camel_folder_change_info_change_uid(folder_unmatched->changes, vuid); - update_summary (uinfo, camel_message_info_flags(info), uinfo->old_flags, FALSE /* Doesn't matter */, TRUE); + //update_summary (uinfo, camel_message_info_flags(info), uinfo->old_flags, FALSE /* Doesn't matter */, TRUE); camel_message_info_free((CamelMessageInfo *)uinfo); } @@ -1741,7 +1733,7 @@ subfolder_deleted(CamelFolder *f, void *event_data, CamelVeeFolder *vf) { camel_vee_folder_remove_folder(vf, f); } - +#if 0 static void subfolder_renamed_update(CamelVeeFolder *vf, CamelFolder *sub, char hash[8]) { @@ -1819,6 +1811,7 @@ folder_renamed_base(CamelVeeFolder *vf, CamelFolder *f, const char *old) if (folder_unmatched != NULL) subfolder_renamed_update(folder_unmatched, f, hash); } +#endif static void folder_renamed(CamelFolder *sub, const char *old, CamelVeeFolder *vf) @@ -1911,7 +1904,7 @@ folder_load_flags(CamelSession *session, CamelSessionThreadMsg *msg) continue; } - vinfo->old_flags = camel_message_info_flags (info); + //vinfo->old_flags = camel_message_info_flags (info); camel_message_info_free((CamelMessageInfo *)info); camel_message_info_free((CamelMessageInfo *)vinfo); } @@ -1946,11 +1939,6 @@ summary_reloaded(CamelObject *o, void *event_data, void *data) if (p->destroyed) return; - /* Kick off a thread to reload flags from the summary */ - if (GPOINTER_TO_INT(g_hash_table_lookup (vf->loaded, summary->folder))) { - g_hash_table_remove (vf->loaded, summary->folder); - camel_object_unhook_event((CamelObject *)o, "summary_reloaded", (CamelObjectEventHookFunc) summary_reloaded, data); - } m = camel_session_thread_msg_new(session, &folder_flags_ops, sizeof(*m)); m->sub = summary->folder; @@ -1965,7 +1953,7 @@ summary_reloaded(CamelObject *o, void *event_data, void *data) static void vee_add_folder(CamelVeeFolder *vf, CamelFolder *sub) { - vee_rebuild_folder(vf, sub, NULL); + //vee_rebuild_folder(vf, sub, NULL); } static void @@ -1973,13 +1961,8 @@ vee_remove_folder(CamelVeeFolder *vf, CamelFolder *sub) { char *shash, hash[8]; - camel_vee_folder_hash_folder(sub, hash); - vee_folder_remove_folder(vf, sub); - shash = g_strdup_printf("%c%c%c%c%c%c%c%c", hash[0], hash[1], hash[2], hash[3], hash[4], hash[5], hash[6], hash[7]); - if (g_hash_table_lookup (vf->hashes, shash)) - g_hash_table_remove (vf->hashes, shash); + //vee_folder_remove_folder(vf, sub); - g_free(shash); } @@ -1999,15 +1982,15 @@ vee_set_expression(CamelVeeFolder *vf, const char *query) } /* Recreate the table when the query changes, only if we are not setting it first */ - if (vf->expression) - camel_db_recreate_vfolder (((CamelFolder *) vf)->parent_store->cdb, ((CamelFolder *) vf)->full_name, NULL); + //if (vf->expression) + // camel_db_recreate_vfolder (((CamelFolder *) vf)->parent_store->cdb, ((CamelFolder *) vf)->full_name, NULL); g_free(vf->expression); if (query) vf->expression = g_strdup(query); - node = p->folders; + /*node = p->folders; while (node) { CamelFolder *f = node->data; @@ -2015,7 +1998,7 @@ vee_set_expression(CamelVeeFolder *vf, const char *query) break; node = node->next; - } + }*/ CAMEL_VEE_FOLDER_LOCK(vf, changed_lock); g_list_free(p->folders_changed); @@ -2052,9 +2035,9 @@ camel_vee_folder_class_init (CamelVeeFolderClass *klass) klass->set_expression = vee_set_expression; klass->add_folder = vee_add_folder; klass->remove_folder = vee_remove_folder; - klass->rebuild_folder = vee_rebuild_folder; + //klass->rebuild_folder = vee_rebuild_folder; klass->folder_changed = folder_changed_base; - klass->folder_renamed = folder_renamed_base; + //klass->folder_renamed = folder_renamed_base; } static void @@ -2077,8 +2060,7 @@ camel_vee_folder_init (CamelVeeFolder *obj) obj->changes = camel_folder_change_info_new(); obj->search = camel_folder_search_new(); - obj->hashes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); - obj->loaded = g_hash_table_new (g_direct_hash, g_direct_equal); + obj->hashes = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL); obj->deleted = FALSE; p->summary_lock = g_mutex_new(); p->subfolder_lock = g_mutex_new(); @@ -2107,10 +2089,6 @@ vee_folder_stop_folder(CamelVeeFolder *vf, CamelFolder *sub) camel_object_unhook_event((CamelObject *)sub, "folder_changed", (CamelObjectEventHookFunc) folder_changed, vf); camel_object_unhook_event((CamelObject *)sub, "deleted", (CamelObjectEventHookFunc) subfolder_deleted, vf); camel_object_unhook_event((CamelObject *)sub, "renamed", (CamelObjectEventHookFunc) folder_renamed, vf); - if (GPOINTER_TO_INT(g_hash_table_lookup (vf->loaded, sub))) { - g_hash_table_remove (vf->loaded, sub); - camel_object_unhook_event((CamelObject *)sub->summary, "summary_reloaded", (CamelObjectEventHookFunc) summary_reloaded, vf); - } p->folders = g_list_remove(p->folders, sub); @@ -2166,7 +2144,10 @@ camel_vee_folder_sync_headers (CamelFolder *vf, CamelException *ex) /* Save the counts to DB */ record = summary_header_to_db (vf->summary, ex); - camel_db_write_folder_info_record (vf->parent_store->cdb, record, ex); + record->account_url = camel_service_get_url((CamelService *)vf->parent_store); + record->folder_key = camel_folder_get_hash (vf); + camel_db_write_folder_info_record (vf->parent_store->cdb_write, record, ex); + g_free (record->account_url); g_free (record); } @@ -2214,6 +2195,5 @@ camel_vee_folder_finalise (CamelObject *obj) g_mutex_free(p->subfolder_lock); g_mutex_free(p->changed_lock); g_hash_table_destroy (vf->hashes); - g_hash_table_destroy (vf->loaded); g_free(p); } diff --git a/camel/camel-vee-folder.h b/camel/camel-vee-folder.h index 62e0a909e..92c799c00 100644 --- a/camel/camel-vee-folder.h +++ b/camel/camel-vee-folder.h @@ -52,7 +52,7 @@ struct _CamelVeeFolder { * say that this folder is part of the unmatched folder */ struct _CamelVeeStore *parent_vee_store; GHashTable *hashes; - GHashTable *loaded; + GPtrArray *folder_keys; gboolean deleted; }; diff --git a/camel/camel-vee-summary.c b/camel/camel-vee-summary.c index 5110f0d94..506064e03 100644 --- a/camel/camel-vee-summary.c +++ b/camel/camel-vee-summary.c @@ -45,8 +45,11 @@ vee_message_info_free(CamelFolderSummary *s, CamelMessageInfo *info) { CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *)info; - camel_pstring_free(info->uid); - camel_object_unref (mi->summary); + camel_pstring_free(mi->folder_key); + + #warning "DBV2: SEE IF IT IS RIGHT" + ((CamelFolderSummaryClass *) camel_vee_summary_parent)->message_info_free(s, info); + } static CamelMessageInfo * @@ -55,18 +58,16 @@ vee_message_info_clone(CamelFolderSummary *s, const CamelMessageInfo *mi) CamelVeeMessageInfo *to; const CamelVeeMessageInfo *from = (const CamelVeeMessageInfo *)mi; - to = (CamelVeeMessageInfo *)camel_message_info_new(s); + to = ((CamelFolderSummaryClass *) camel_vee_summary_parent)->message_info_clone(s, mi); - to->summary = from->summary; - camel_object_ref (to->summary); - to->info.summary = s; to->info.uid = camel_pstring_strdup(from->info.uid); + to->folder_key = camel_pstring_strdup(from->folder_key); return (CamelMessageInfo *)to; } #define HANDLE_NULL_INFO(value) if (!rmi) { g_warning (G_STRLOC ": real info is NULL for %s, safeguarding\n", mi->uid); return value; } - +/* static const void * vee_info_ptr (const CamelMessageInfo *mi, int id) { @@ -137,6 +138,8 @@ vee_info_user_tag(const CamelMessageInfo *mi, const char *id) return ret; } +*/ +/* static gboolean vee_info_set_user_flag(CamelMessageInfo *mi, const char *name, gboolean value) { @@ -166,46 +169,18 @@ vee_info_set_user_tag(CamelMessageInfo *mi, const char *name, const char *value) return res; } +*/ static gboolean vee_info_set_flags(CamelMessageInfo *mi, guint32 flags, guint32 set) { int res = FALSE; + guint32 old_flags = ((CamelMessageInfoBase *)mi)->flags; + CamelVeeMessageInfo *vinfo = (CamelVeeMessageInfo *)mi; - if (mi->uid) { - guint32 old_visible, old_unread, old_deleted, old_junked, old_junked_not_deleted; - guint32 visible, unread, deleted, junked, junked_not_deleted; - CamelMessageInfo *rmi = camel_folder_summary_uid (((CamelVeeMessageInfo *)mi)->summary, mi->uid+8); + res = camel_message_info_set_flags(mi, flags, set); + #warning "DBV2: UPDATE THE PARENT FOLDER ON COUNTS" - HANDLE_NULL_INFO(FALSE); - camel_object_get(rmi->summary->folder, NULL, - CAMEL_FOLDER_DELETED, &old_deleted, - CAMEL_FOLDER_VISIBLE, &old_visible, - CAMEL_FOLDER_JUNKED, &old_junked, - CAMEL_FOLDER_JUNKED_NOT_DELETED, &old_junked_not_deleted, - CAMEL_FOLDER_UNREAD, &old_unread, NULL); - camel_folder_freeze(rmi->summary->folder); - res = camel_message_info_set_flags(rmi, flags, set); - ((CamelVeeMessageInfo *) mi)->old_flags = camel_message_info_flags (rmi); - camel_folder_thaw(rmi->summary->folder); - - camel_object_get(rmi->summary->folder, NULL, - CAMEL_FOLDER_DELETED, &deleted, - CAMEL_FOLDER_VISIBLE, &visible, - CAMEL_FOLDER_JUNKED, &junked, - CAMEL_FOLDER_JUNKED_NOT_DELETED, &junked_not_deleted, - CAMEL_FOLDER_UNREAD, &unread, NULL); - /* Keep the summary in sync */ - mi->summary->unread_count += unread - old_unread; - mi->summary->deleted_count += deleted - old_deleted; - mi->summary->junk_count += junked - old_junked; - mi->summary->junk_not_deleted_count += junked_not_deleted - old_junked_not_deleted; - mi->summary->visible_count += visible - old_visible; - - d(printf("VF %d %d %d %d %d\n", mi->summary->unread_count, mi->summary->deleted_count, mi->summary->junk_count, mi->summary->junk_not_deleted_count, mi->summary->visible_count)); - camel_message_info_free (rmi); - } - return res; } @@ -213,6 +188,7 @@ static CamelMessageInfo * message_info_from_uid (CamelFolderSummary *s, const char *uid) { CamelMessageInfo *info; + char folder_key[9]; /* FIXME[disk-summary] too bad design. Need to peek it from cfs * instead of hacking ugly like this */ @@ -229,56 +205,85 @@ message_info_from_uid (CamelFolderSummary *s, const char *uid) if (!info) { CamelVeeMessageInfo *vinfo; - char tmphash[9]; - - /* This function isn't really nice. But no great way - * But in vfolder case, this may not be so bad, as vuid has the hash in first 8 bytes. - * So this just compares the entire string only if it belongs to the same folder. - * Otherwise, the first byte itself would return in strcmp, saving the CPU. - */ - if (!camel_folder_summary_check_uid (s, uid)) { - d(g_message ("Unable to find %s in the summary of %s", uid, s->folder->full_name)); - return NULL; - } - - /* Create the info and load it, its so easy. */ - info = camel_message_info_new (s); - camel_message_info_ref(info); - info->dirty = FALSE; - vinfo = (CamelVeeMessageInfo *) info; - info->uid = camel_pstring_strdup(uid); - strncpy(tmphash, uid, 8); - tmphash[8] = 0; - vinfo->summary = g_hash_table_lookup(((CamelVeeFolder *) s->folder)->hashes, tmphash); - camel_object_ref (vinfo->summary); - camel_folder_summary_insert (s, info, FALSE); + strncpy(folder_key, uid, 8); + folder_key[8] = 0; + camel_folder_summary_load_info_from_db (s, folder_key, uid, TRUE, NULL); } return info; } +static char * +make_folder_keys (GPtrArray *array) +{ + int i; + GString *str = g_string_new(NULL); + char *ret; + + g_string_append_printf (str, "(folder_key = '%s'", array->pdata[0]); + for (i=1; i<array->len; i++) + g_string_append_printf (str, " OR folder_key = '%s'", array->pdata[i]); + g_string_append (str, ")"); + ret = str->str; + g_string_free(str, FALSE); + + return ret; +} + +struct _db_pass_data { + CamelFolderSummary *summary; + gboolean double_ref; + gboolean add; /* or just insert to hashtable */ +}; +int camel_read_mir_callback (void * ref, int ncol, char ** cols, char ** name); + +static int +reload_from_db (CamelFolderSummary *s, CamelException *ex) +{ + int ret; + struct _db_pass_data data; + CamelDB *cdb = s->folder->parent_store->cdb; + char *query = make_folder_keys (((CamelVeeFolder *) s->folder)->folder_keys); + char *sql = camel_sexp_to_sql_sexp (((CamelVeeFolder *)s->folder)->expression); + char *final; + + final = g_strdup_printf("(%s) AND (%s)", query, sql); + data.summary = s; + data.double_ref = FALSE; + data.add = FALSE; + ret = camel_db_read_message_info_records (cdb, s->folder->folder_key, (gpointer)&data, camel_read_mir_callback, final, ex); + + g_free (query); + g_free (sql); + g_free (final); + + return ret; +} + + static void camel_vee_summary_class_init (CamelVeeSummaryClass *klass) { ((CamelFolderSummaryClass *)klass)->message_info_clone = vee_message_info_clone; ((CamelFolderSummaryClass *)klass)->message_info_free = vee_message_info_free; - +/* ((CamelFolderSummaryClass *)klass)->info_ptr = vee_info_ptr; ((CamelFolderSummaryClass *)klass)->info_uint32 = vee_info_uint32; ((CamelFolderSummaryClass *)klass)->info_time = vee_info_time; ((CamelFolderSummaryClass *)klass)->info_user_flag = vee_info_user_flag; ((CamelFolderSummaryClass *)klass)->info_user_tag = vee_info_user_tag; - +*/ #if 0 ((CamelFolderSummaryClass *)klass)->info_set_string = vee_info_set_string; ((CamelFolderSummaryClass *)klass)->info_set_uint32 = vee_info_set_uint32; ((CamelFolderSummaryClass *)klass)->info_set_time = vee_info_set_time; ((CamelFolderSummaryClass *)klass)->info_set_references = vee_info_set_references; -#endif ((CamelFolderSummaryClass *)klass)->info_set_user_flag = vee_info_set_user_flag; ((CamelFolderSummaryClass *)klass)->info_set_user_tag = vee_info_set_user_tag; +#endif ((CamelFolderSummaryClass *)klass)->info_set_flags = vee_info_set_flags; - ((CamelFolderSummaryClass *)klass)->message_info_from_uid = message_info_from_uid; + ((CamelFolderSummaryClass *)klass)->message_info_from_uid = message_info_from_uid; + ((CamelFolderSummaryClass *)klass)->reload_from_db = reload_from_db; } static void @@ -337,9 +342,11 @@ camel_vee_summary_new(CamelFolder *parent) /* FIXME[disk-summary] handle excep and ret */ camel_folder_summary_header_load_from_db ((CamelFolderSummary *)s, parent->parent_store, parent->full_name, NULL); + return &s->summary; } +#if 0 GPtrArray * camel_vee_summary_get_ids (CamelVeeSummary *summary, char hash[8]) { @@ -348,7 +355,7 @@ camel_vee_summary_get_ids (CamelVeeSummary *summary, char hash[8]) GPtrArray *array; /* FIXME[disk-summary] fix exception passing */ - array = camel_db_get_vuids_from_vfolder(cfs->folder->cdb, cfs->folder->full_name, shash, NULL); + array = camel_db_get_vuids_from_vfolder(cfs->folder->parent_store->cdb, cfs->folder->full_name, shash, NULL); g_free(shash); @@ -397,4 +404,5 @@ camel_vee_summary_add(CamelVeeSummary *s, CamelFolderSummary *summary, const cha camel_folder_summary_insert(&s->summary, (CamelMessageInfo *)mi, FALSE); return mi; -} +} +#endif diff --git a/camel/camel-vee-summary.h b/camel/camel-vee-summary.h index f4f631ca5..c560a3444 100644 --- a/camel/camel-vee-summary.h +++ b/camel/camel-vee-summary.h @@ -41,9 +41,8 @@ typedef struct _CamelVeeSummaryClass CamelVeeSummaryClass; typedef struct _CamelVeeMessageInfo CamelVeeMessageInfo; struct _CamelVeeMessageInfo { - CamelMessageInfo info; - CamelFolderSummary *summary; - guint32 old_flags; /* These are just for identifying changed flags */ + CamelMessageInfoBase info; + const char *folder_key; }; struct _CamelVeeSummary { diff --git a/camel/camel-vtrash-folder.c b/camel/camel-vtrash-folder.c index 402f180b3..642e63746 100644 --- a/camel/camel-vtrash-folder.c +++ b/camel/camel-vtrash-folder.c @@ -145,10 +145,10 @@ vtrash_getv(CamelObject *object, CamelException *ex, CamelArgGetV *args) count = camel_folder_summary_count(folder->summary); for (j=0; j<count; j++) { if ((info = (CamelMessageInfoBase *) camel_folder_summary_index(folder->summary, j))) { - guint32 flags; + guint32 flags = 0; vinfo = (CamelVeeMessageInfo *) info; - flags = vinfo->old_flags ? vinfo->old_flags : camel_message_info_flags(info); + //flags = vinfo->old_flags ? vinfo->old_flags : camel_message_info_flags(info); if ((flags & (CAMEL_MESSAGE_SEEN)) == 0) unread++; @@ -198,7 +198,7 @@ vtrash_append_message (CamelFolder *folder, CamelMimeMessage *message, camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, _(vdata[((CamelVTrashFolder *)folder)->type].error_copy)); } - +#if 0 struct _transfer_data { CamelFolder *folder; CamelFolder *dest; @@ -298,6 +298,8 @@ vtrash_transfer_messages_to (CamelFolder *source, GPtrArray *uids, } } +#endif +#if 0 /* FIXME[disk-summary] rewrite the same way as camel-vee-summary.c */ static GPtrArray * vtrash_search_by_expression(CamelFolder *folder, const char *expression, CamelException *ex) @@ -354,7 +356,7 @@ vtrash_search_by_expression(CamelFolder *folder, const char *expression, CamelEx return result; } - +#endif static GPtrArray * vtrash_search_by_uids(CamelFolder *folder, const char *expression, GPtrArray *uids, CamelException *ex) { @@ -523,14 +525,14 @@ vtrash_add_folder(CamelVeeFolder *vf, CamelFolder *sub) CAMEL_VEE_FOLDER_LOCK(vf, summary_lock); if (((CamelVTrashFolder *)vf)->bit == CAMEL_MESSAGE_DELETED) { - infos = camel_db_get_folder_deleted_uids (sub->cdb, sub->full_name, NULL); + infos = camel_db_get_folder_deleted_uids (sub->parent_store->cdb, sub->full_name, NULL); if (infos) { ((CamelFolder *)vf)->summary->saved_count += infos->len; ((CamelFolder *)vf)->summary->deleted_count += infos->len; } } else if (((CamelVTrashFolder *)vf)->bit == CAMEL_MESSAGE_JUNK) - infos = camel_db_get_folder_junk_uids (sub->cdb, sub->full_name, NULL); + infos = camel_db_get_folder_junk_uids (sub->parent_store->cdb, sub->full_name, NULL); if (!infos) { CAMEL_VEE_FOLDER_UNLOCK(vf, summary_lock); @@ -560,7 +562,7 @@ vtrash_add_folder(CamelVeeFolder *vf, CamelFolder *sub) g_free(shash); } - +#if 0 static void vtrash_remove_folder(CamelVeeFolder *vf, CamelFolder *sub) { @@ -627,7 +629,7 @@ vtrash_remove_folder(CamelVeeFolder *vf, CamelFolder *sub) camel_folder_change_info_free(vf_changes); } } - +#endif static int vtrash_rebuild_folder(CamelVeeFolder *vf, CamelFolder *source, CamelException *ex) { @@ -646,7 +648,7 @@ camel_vtrash_folder_class_init (CamelVTrashFolderClass *klass) ((CamelObjectClass *)klass)->getv = vtrash_getv; folder_class->append_message = vtrash_append_message; - folder_class->transfer_messages_to = vtrash_transfer_messages_to; + //folder_class->transfer_messages_to = vtrash_transfer_messages_to; /* Not required, lets use the base class search function */ /* folder_class->search_by_expression = vtrash_search_by_expression; */ /* folder_class->search_by_uids = vtrash_search_by_uids; */ diff --git a/camel/providers/imap/camel-imap-folder.c b/camel/providers/imap/camel-imap-folder.c index b0b6be210..6e73c04d3 100644 --- a/camel/providers/imap/camel-imap-folder.c +++ b/camel/providers/imap/camel-imap-folder.c @@ -1483,7 +1483,7 @@ imap_expunge_uids_offline (CamelFolder *folder, GPtrArray *uids, CamelException * the cached data may be useful in replaying a COPY later. */ } - camel_db_delete_uids (folder->cdb, folder->full_name, list, ex); + camel_db_delete_uids (folder->parent_store->cdb_write, folder->full_name, list, ex); g_slist_free(list); camel_folder_summary_save_to_db (folder->summary, ex); @@ -1568,7 +1568,7 @@ imap_expunge_uids_online (CamelFolder *folder, GPtrArray *uids, CamelException * * the cached data may be useful in replaying a COPY later. */ } - camel_db_delete_uids (folder->cdb, folder->full_name, list, ex); + camel_db_delete_uids (folder->parent_store->cdb_write, folder->full_name, list, ex); g_slist_free (list); camel_folder_summary_save_to_db (folder->summary, ex); camel_object_trigger_event (CAMEL_OBJECT (folder), "folder_changed", changes); @@ -3506,7 +3506,7 @@ camel_imap_folder_changed (CamelFolder *folder, int exists, } /* Delete all in one transaction */ - camel_db_delete_uids (folder->cdb, folder->full_name, deleted, ex); + camel_db_delete_uids (folder->parent_store->cdb_write, folder->full_name, deleted, ex); g_slist_foreach (deleted, (GFunc) g_free, NULL); g_slist_free (deleted); } diff --git a/camel/providers/imap/camel-imap-store.c b/camel/providers/imap/camel-imap-store.c index 1820fa75f..5ab24c70c 100644 --- a/camel/providers/imap/camel-imap-store.c +++ b/camel/providers/imap/camel-imap-store.c @@ -1126,6 +1126,7 @@ imap_forget_folder (CamelImapStore *imap_store, const char *folder_name, CamelEx g_unlink (state_file); g_free (state_file); + #warning "DBV2: This delete folder won't work" camel_db_delete_folder (((CamelStore *)imap_store)->cdb, folder_name, ex); camel_imap_message_cache_delete (folder_dir, ex); diff --git a/camel/providers/imap/camel-imap-summary.c b/camel/providers/imap/camel-imap-summary.c index 530cfa7aa..88f49995c 100644 --- a/camel/providers/imap/camel-imap-summary.c +++ b/camel/providers/imap/camel-imap-summary.c @@ -37,6 +37,7 @@ #include "camel-imap-summary.h" #include "camel-imap-utils.h" +#include "camel-store.h" #define CAMEL_IMAP_SUMMARY_VERSION (3) @@ -168,8 +169,11 @@ camel_imap_summary_new (struct _CamelFolder *folder, const char *filename) camel_exception_init (&ex); summary->folder = folder; - if (folder) - camel_db_set_collate (folder->cdb, "uid", "uid_sort", (CamelDBCollate)sort_uid_cmp); + if (folder) { + camel_db_set_collate (folder->parent_store->cdb, "uid", "imap_uid_sort", (CamelDBCollate)sort_uid_cmp); + summary->sort_col = "uid"; + summary->collate = "imap_uid_sort"; + } camel_folder_summary_set_build_content (summary, TRUE); camel_folder_summary_set_filename (summary, filename); diff --git a/camel/providers/local/camel-local-store.c b/camel/providers/local/camel-local-store.c index 19cc559e0..bbca955f8 100644 --- a/camel/providers/local/camel-local-store.c +++ b/camel/providers/local/camel-local-store.c @@ -103,15 +103,6 @@ camel_local_store_finalize (CamelLocalStore *local_store) if (local_store->toplevel_dir) g_free (local_store->toplevel_dir); - store = ((CamelStore *)local_store); - d(printf ("\n\aLocal Store Finalize \n\a")); - - if (store && store->cdb) { - d(printf ("\n\aClosing Store DB for hte local provider \n\a")); - camel_db_close (store->cdb); - store->cdb = NULL; - } - } CamelType diff --git a/camel/providers/local/camel-maildir-summary.c b/camel/providers/local/camel-maildir-summary.c index ac8f7c6fb..3177e8c77 100644 --- a/camel/providers/local/camel-maildir-summary.c +++ b/camel/providers/local/camel-maildir-summary.c @@ -43,6 +43,8 @@ #include "camel-private.h" #include "camel-string-utils.h" #include "camel-maildir-summary.h" +#include "camel-folder.h" +#include "camel-store.h" #define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/ @@ -168,8 +170,10 @@ CamelMaildirSummary CamelMaildirSummary *o = (CamelMaildirSummary *)camel_object_new(camel_maildir_summary_get_type ()); ((CamelFolderSummary *)o)->folder = folder; - if (folder) - camel_db_set_collate (folder->cdb, "dreceived", NULL, NULL); + if (folder) { + camel_db_set_collate (folder->parent_store->cdb, "dreceived", NULL, NULL); + ((CamelFolderSummary *)o)->sort_col = "dreceived"; + } camel_local_summary_construct((CamelLocalSummary *)o, filename, maildirdir, index); return o; } diff --git a/camel/providers/local/camel-mbox-summary.c b/camel/providers/local/camel-mbox-summary.c index e4b055c8c..855ef72f1 100644 --- a/camel/providers/local/camel-mbox-summary.c +++ b/camel/providers/local/camel-mbox-summary.c @@ -48,6 +48,7 @@ #define io(x) #define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/ +#define dd(x) if(camel_debug("mbox")) x; #define CAMEL_MBOX_SUMMARY_VERSION (1) @@ -213,12 +214,15 @@ camel_mbox_summary_finalise(CamelObject *obj) static int frompos_sort (void *enc, int len1, void * data1, int len2, void *data2) { - char *sa1 = (char*)g_utf8_normalize (data1, len1, G_NORMALIZE_DEFAULT); - char *sa2 = (char*)g_utf8_normalize (data2, len2, G_NORMALIZE_DEFAULT); + //char *sa1 = (char*)g_utf8_normalize (data1, len1, G_NORMALIZE_DEFAULT); + //char *sa2 = (char*)g_utf8_normalize (data2, len2, G_NORMALIZE_DEFAULT); + char *sa1 = data1; + char *sa2 = data2; + sa1[len1]=0; sa2[len2]=0; int a1 = strtoul (sa1, NULL, 10); int a2 = strtoul (sa2, NULL, 10); - g_free(sa1); g_free(sa2); + //g_free(sa1); g_free(sa2); return a1 > a2; } @@ -239,7 +243,9 @@ camel_mbox_summary_new(struct _CamelFolder *folder, const char *filename, const if (folder) { /* Set the functions for db sorting */ /* FIXME: Add column names though a #define */ - camel_db_set_collate (folder->cdb, "bdata", "frompos_sort", (CamelDBCollate)frompos_sort); + camel_db_set_collate (folder->parent_store->cdb, "bdata", "mbox_frompos_sort", (CamelDBCollate)frompos_sort); + ((CamelFolderSummary *)new)->sort_col = "bdata"; + ((CamelFolderSummary *)new)->collate = "mbox_frompos_sort"; } camel_local_summary_construct((CamelLocalSummary *)new, filename, mbox_name, index); return new; @@ -367,7 +373,8 @@ message_info_new_from_header(CamelFolderSummary *s, struct _camel_header_raw *h) && camel_local_summary_decode_x_evolution((CamelLocalSummary *)s, xev, &mi->info) == 0) { uid = camel_message_info_uid(mi); d(printf("found valid x-evolution: %s\n", uid)); - info = (CamelMboxMessageInfo *)camel_folder_summary_uid(s, uid); + /* If one is there, it should be there already */ + info = (CamelMboxMessageInfo *) camel_folder_summary_peek_info (s, uid); if (info) { if ((info->info.info.flags & CAMEL_MESSAGE_FOLDER_NOTSEEN)) { info->info.info.flags &= ~CAMEL_MESSAGE_FOLDER_NOTSEEN; @@ -567,6 +574,8 @@ summary_update(CamelLocalSummary *cls, off_t offset, CamelFolderChangeInfo *chan If we're not starting from the start, we must be starting from the old end, so everything must be treated as new */ count = camel_folder_summary_count(s); + if (count - camel_folder_summary_cache_size(s) > 100) /* It makes sense to load summary, if enough isn't there. */ + camel_folder_summary_reload_from_db (s, ex); for (i=0;i<count;i++) { mi = (CamelMboxMessageInfo *)camel_folder_summary_index(s, i); if (offset == 0) @@ -613,7 +622,7 @@ summary_update(CamelLocalSummary *cls, off_t offset, CamelFolderChangeInfo *chan } /* Delete all in one transaction */ - camel_db_delete_uids (s->folder->cdb, s->folder->full_name, del, ex); + camel_db_delete_uids (s->folder->parent_store->cdb_write, s->folder->folder_key, del, ex); g_slist_foreach (del, (GFunc) camel_pstring_free, NULL); g_slist_free (del); @@ -622,6 +631,7 @@ summary_update(CamelLocalSummary *cls, off_t offset, CamelFolderChangeInfo *chan /* update the file size/mtime in the summary */ if (ok != -1) { if (g_stat(cls->folder_path, &st) == 0) { + dd(printf("Setting %s: %d %d to %d %d\n", cls->folder_path, mbs->folder_size, s->time, st.st_size, st.st_mtime)); camel_folder_summary_touch(s); mbs->folder_size = st.st_size; s->time = st.st_mtime; @@ -673,6 +683,8 @@ mbox_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changes, Camel ret = 0; } else { /* is the summary uptodate? */ + dd(printf("CHECK %s: %d %d to %d %d\n", cls->folder_path, mbs->folder_size, s->time, st.st_size, st.st_mtime)); + if (st.st_size != mbs->folder_size || st.st_mtime != s->time) { if (mbs->folder_size < st.st_size) { /* this will automatically rescan from 0 if there is a problem */ @@ -691,6 +703,7 @@ mbox_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changes, Camel if (ret != -1) { if (mbs->folder_size != st.st_size || s->time != st.st_mtime) { + dd(printf("SET CHECK %s: %d %d to %d %d\n", cls->folder_path, mbs->folder_size, s->time, st.st_size, st.st_mtime)); mbs->folder_size = st.st_size; s->time = st.st_mtime; camel_folder_summary_touch(s); @@ -789,6 +802,29 @@ mbox_summary_sync_full(CamelMboxSummary *mbs, gboolean expunge, CamelFolderChang return -1; } +static gint +cms_sort_frompos (gpointer a, gpointer b, gpointer data) +{ + CamelFolderSummary *summary = (CamelFolderSummary *)data; + CamelMboxMessageInfo *info1, *info2; + int ret = 0; + + /* Things are in memory already. Sorting speeds up syncing, if things are sorted by from pos. */ + info1 = camel_folder_summary_uid (summary, *(char **)a); + info2 = camel_folder_summary_uid (summary, *(char **)b); + + if (info1->frompos > info2->frompos) + ret = 1; + else if (info1->frompos < info2->frompos) + ret = -1; + else + ret = 0; + camel_message_info_free (info1); + camel_message_info_free (info2); + + return ret; + +} /* perform a quick sync - only system flags have changed */ static int mbox_summary_sync_quick(CamelMboxSummary *mbs, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex) @@ -836,6 +872,9 @@ mbox_summary_sync_quick(CamelMboxSummary *mbs, gboolean expunge, CamelFolderChan /* Sync only the changes */ summary = camel_folder_summary_get_changed ((CamelFolderSummary *)mbs); + if (summary->len) + g_ptr_array_sort_with_data (summary, cms_sort_frompos, (gpointer) mbs); + dd(printf("sync quick: changed len %d\n", summary->len)); for (i = 0; i < summary->len; i++) { int xevoffset; int pc = (i+1)*100/summary->len; @@ -909,6 +948,8 @@ mbox_summary_sync_quick(CamelMboxSummary *mbs, gboolean expunge, CamelFolderChan camel_mime_parser_drop_step(mp); info->info.info.flags &= 0xffff; + info->info.info.dirty = TRUE; + camel_message_info_free((CamelMessageInfo *)info); } @@ -955,7 +996,7 @@ mbox_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInf int quick = TRUE, work=FALSE; int ret; GPtrArray *summary = NULL; - + /* first, sync ourselves up, just to make sure */ if (camel_local_summary_check(cls, changeinfo, ex) == -1) return -1; @@ -964,6 +1005,7 @@ mbox_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInf summary = camel_folder_summary_get_changed ((CamelFolderSummary *)mbs); + dd(printf("summary sync changed %d\n", summary->len)); for (i=0; i<summary->len; i++) { CamelMboxMessageInfo *info = (CamelMboxMessageInfo *)camel_folder_summary_uid(s, summary->pdata[i]); @@ -982,7 +1024,7 @@ mbox_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInf int dcount =0; - if (camel_db_count_deleted_message_info (s->folder->cdb, s->folder->full_name, &dcount, ex) == -1) + if (camel_db_count_deleted_message_info (s->folder->parent_store->cdb_write, s->folder->folder_key, &dcount, ex) == -1) return -1; if (dcount) quick = FALSE; @@ -1015,6 +1057,7 @@ mbox_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInf } if (mbs->folder_size != st.st_size || s->time != st.st_mtime) { + dd(printf("sync set %s: %d %d to %d %d\n", cls->folder_path, mbs->folder_size, s->time, st.st_size, st.st_mtime)); s->time = st.st_mtime; mbs->folder_size = st.st_size; camel_folder_summary_touch(s); @@ -1191,7 +1234,7 @@ camel_mbox_summary_sync_mbox(CamelMboxSummary *cls, guint32 flags, CamelFolderCh info = NULL; } } - camel_db_delete_uids (s->folder->cdb, s->folder->full_name, del, ex); + camel_db_delete_uids (s->folder->parent_store->cdb_write, s->folder->folder_key, del, ex); g_slist_foreach (del, (GFunc) camel_pstring_free, NULL); g_slist_free (del); @@ -1212,6 +1255,7 @@ camel_mbox_summary_sync_mbox(CamelMboxSummary *cls, guint32 flags, CamelFolderCh |CAMEL_MESSAGE_FOLDER_FLAGGED |CAMEL_MESSAGE_FOLDER_XEVCHANGE); camel_folder_summary_touch(s); + ((CamelMessageInfo *)info)->dirty = TRUE; } camel_message_info_free((CamelMessageInfo *)info); } diff --git a/camel/providers/local/camel-mh-summary.c b/camel/providers/local/camel-mh-summary.c index 101823c12..bf2e05b20 100644 --- a/camel/providers/local/camel-mh-summary.c +++ b/camel/providers/local/camel-mh-summary.c @@ -38,7 +38,8 @@ #include "camel-private.h" #include "camel-mh-summary.h" - +#include "camel-folder.h" +#include "camel-store.h" #define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/ #define CAMEL_MH_SUMMARY_VERSION (0x2000) @@ -133,14 +134,17 @@ sort_uid_cmp (void *enc, int len1, void * data1, int len2, void *data2) * * Return value: A new #CamelMhSummary object. **/ -CamelMhSummary *camel_mh_summary_new(struct _CamelFolder *folder, const char *filename, const char *mhdir, CamelIndex *index) +CamelMhSummary *camel_mh_summary_new(CamelFolder *folder, const char *filename, const char *mhdir, CamelIndex *index) { CamelMhSummary *o = (CamelMhSummary *)camel_object_new(camel_mh_summary_get_type ()); ((CamelFolderSummary *)o)->folder = folder; if (folder) { - camel_db_set_collate (folder->cdb, "uid", "uid_sort", (CamelDBCollate)sort_uid_cmp); + camel_db_set_collate (folder->parent_store->cdb, "uid", "mh_uid_sort", (CamelDBCollate)sort_uid_cmp); + ((CamelFolderSummary *)o)->sort_col = "uid"; + ((CamelFolderSummary *)o)->collate = "mh_uid_sort"; } + camel_local_summary_construct((CamelLocalSummary *)o, filename, mhdir, index); return o; } diff --git a/camel/providers/local/camel-spool-summary.c b/camel/providers/local/camel-spool-summary.c index 7920e7bc7..ec4de1934 100644 --- a/camel/providers/local/camel-spool-summary.c +++ b/camel/providers/local/camel-spool-summary.c @@ -39,7 +39,8 @@ #include "camel-operation.h" #include "camel-spool-summary.h" - +#include "camel-store.h" +#include "camel-folder.h" #define io(x) #define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/ @@ -127,7 +128,9 @@ camel_spool_summary_new(struct _CamelFolder *folder, const char *mbox_name) if (folder) { /* Set the functions for db sorting */ /* FIXME: Add column names though a #define */ - camel_db_set_collate (folder->cdb, "bdata", "frompos_sort", (CamelDBCollate)frompos_sort); + camel_db_set_collate (folder->parent_store->cdb, "bdata", "spool_frompos_sort", (CamelDBCollate)frompos_sort); + ((CamelFolderSummary *)new)->sort_col = "bdata"; + ((CamelFolderSummary *)new)->collate = "spool_frompos_sort"; } camel_local_summary_construct((CamelLocalSummary *)new, NULL, mbox_name, NULL); camel_folder_summary_load_from_db ((CamelFolderSummary *)new, NULL); |