evolution-data-server/bgo-559153-eds-migration.patch

337 lines
12 KiB
Diff

Index: camel/camel-store.c
===================================================================
--- camel/camel-store.c (revision 9841)
+++ camel/camel-store.c (revision 9842)
@@ -322,6 +322,21 @@
}
if (!folder) {
+
+ if (flags & CAMEL_STORE_IS_MIGRATING) {
+ if ((store->flags & CAMEL_STORE_VTRASH) && strcmp(folder_name, CAMEL_VTRASH_NAME) == 0) {
+ if (store->folders)
+ camel_object_bag_abort(store->folders, folder_name);
+ return NULL;
+ }
+
+ if ((store->flags & CAMEL_STORE_VJUNK) && strcmp(folder_name, CAMEL_VJUNK_NAME) == 0) {
+ if (store->folders)
+ camel_object_bag_abort(store->folders, folder_name);
+ return NULL;
+ }
+ }
+
if ((store->flags & CAMEL_STORE_VTRASH) && strcmp(folder_name, CAMEL_VTRASH_NAME) == 0) {
folder = CS_CLASS(store)->get_trash(store, ex);
} else if ((store->flags & CAMEL_STORE_VJUNK) && strcmp(folder_name, CAMEL_VJUNK_NAME) == 0) {
Index: camel/camel-store.h
===================================================================
--- camel/camel-store.h (revision 9841)
+++ camel/camel-store.h (revision 9842)
@@ -115,6 +115,7 @@
#define CAMEL_STORE_FILTER_INBOX (1 << 2)
#define CAMEL_STORE_VJUNK (1 << 3)
#define CAMEL_STORE_PROXY (1 << 4)
+#define CAMEL_STORE_IS_MIGRATING (1 << 5)
struct _CamelDB;
Index: camel/providers/local/camel-local-folder.c
===================================================================
--- camel/providers/local/camel-local-folder.c (revision 9841)
+++ camel/providers/local/camel-local-folder.c (revision 9842)
@@ -289,7 +289,7 @@
}
folder->summary = (CamelFolderSummary *)CLOCALF_CLASS(lf)->create_summary(lf, lf->summary_path, lf->folder_path, lf->index);
- if (camel_local_summary_load((CamelLocalSummary *)folder->summary, forceindex, NULL) == -1) {
+ if (!(flags & CAMEL_STORE_IS_MIGRATING) && camel_local_summary_load((CamelLocalSummary *)folder->summary, forceindex, NULL) == -1) {
/* ? */
if (camel_local_summary_check((CamelLocalSummary *)folder->summary, lf->changes, ex) == 0) {
/* we sync here so that any hard work setting up the folder isn't lost */
Index: camel/camel-db.c
===================================================================
--- camel/camel-db.c (revision 9841)
+++ camel/camel-db.c (revision 9842)
@@ -47,6 +47,8 @@
static GStaticRecMutex trans_lock = G_STATIC_REC_MUTEX_INIT;
+static int write_mir (CamelDB *cdb, const char *folder_name, CamelMIRecord *record, CamelException *ex, gboolean delete_old_record);
+
static int
cdb_sql_exec (sqlite3 *db, const char* stmt, CamelException *ex)
{
@@ -812,13 +814,29 @@
return ret;
}
+
+int
+camel_db_write_fresh_message_info_record (CamelDB *cdb, const char *folder_name, CamelMIRecord *record, CamelException *ex)
+{
+ return write_mir (cdb, folder_name, record, ex, FALSE);
+}
+
+
int
camel_db_write_message_info_record (CamelDB *cdb, const char *folder_name, CamelMIRecord *record, CamelException *ex)
{
+ return write_mir (cdb, folder_name, record, ex, TRUE);
+}
+
+static int
+write_mir (CamelDB *cdb, const char *folder_name, CamelMIRecord *record, CamelException *ex, gboolean delete_old_record)
+{
int ret;
char *del_query;
char *ins_query;
+ /* FIXME: We should migrate from this DELETE followed by INSERT model to an INSERT OR REPLACE model as pointed out by pvanhoof */
+
/* NB: UGLIEST Hack. We can't modify the schema now. We are using msg_security (an unsed one to notify of FLAGGED/Dirty infos */
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 )",
@@ -832,7 +850,8 @@
record->part, record->labels, record->usertags,
record->cinfo, record->bdata);
- del_query = sqlite3_mprintf ("DELETE FROM %Q WHERE uid = %Q", folder_name, record->uid);
+ if (delete_old_record)
+ del_query = sqlite3_mprintf ("DELETE FROM %Q WHERE uid = %Q", folder_name, record->uid);
#if 0
char *upd_query;
@@ -842,12 +861,14 @@
g_free (upd_query);
#else
- ret = camel_db_add_to_transaction (cdb, del_query, ex);
+ if (delete_old_record)
+ ret = camel_db_add_to_transaction (cdb, del_query, ex);
ret = camel_db_add_to_transaction (cdb, ins_query, ex);
#endif
- sqlite3_free (del_query);
+ if (delete_old_record)
+ sqlite3_free (del_query);
sqlite3_free (ins_query);
return ret;
@@ -1198,3 +1219,39 @@
CAMEL_DB_RELEASE_SQLITE_MEMORY;
return ret;
}
+
+int camel_db_start_in_memory_transactions (CamelDB *cdb, CamelException *ex)
+{
+ int ret;
+ char *cmd = sqlite3_mprintf ("ATTACH DATABASE ':memory:' AS %s", CAMEL_DB_IN_MEMORY_DB);
+
+ ret = camel_db_command (cdb, cmd, ex);
+ sqlite3_free (cmd);
+
+ cmd = sqlite3_mprintf ("CREATE TEMPORARY TABLE %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 )", CAMEL_DB_IN_MEMORY_TABLE);
+ ret = camel_db_command (cdb, cmd, ex);
+ if (ret != 0 )
+ abort ();
+ sqlite3_free (cmd);
+
+ return ret;
+}
+
+int camel_db_flush_in_memory_transactions (CamelDB *cdb, const char * folder_name, CamelException *ex)
+{
+ int ret;
+ char *cmd = sqlite3_mprintf ("INSERT INTO %Q SELECT * FROM %Q", folder_name, CAMEL_DB_IN_MEMORY_TABLE);
+
+ ret = camel_db_command (cdb, cmd, ex);
+ sqlite3_free (cmd);
+
+ cmd = sqlite3_mprintf ("DROP TABLE %Q", CAMEL_DB_IN_MEMORY_TABLE);
+ ret = camel_db_command (cdb, cmd, ex);
+ sqlite3_free (cmd);
+
+ cmd = sqlite3_mprintf ("DETACH %Q", CAMEL_DB_IN_MEMORY_DB);
+ ret = camel_db_command (cdb, cmd, ex);
+ sqlite3_free (cmd);
+
+ return ret;
+}
Index: camel/camel-db.h
===================================================================
--- camel/camel-db.h (revision 9841)
+++ camel/camel-db.h (revision 9842)
@@ -4,8 +4,14 @@
#define __CAMEL_DB_H
#include <sqlite3.h>
#include <glib.h>
+
#define CAMEL_DB_FILE "folders.db"
+/* Hopefully no one will create a folder named EVO_IN_meM_hAnDlE */
+#define CAMEL_DB_IN_MEMORY_TABLE "EVO_IN_meM_hAnDlE.temp"
+#define CAMEL_DB_IN_MEMORY_DB "EVO_IN_meM_hAnDlE"
+#define CAMEL_DB_IN_MEMORY_TABLE_LIMIT 100000
+
#include "camel-exception.h"
typedef struct _CamelDBPrivate CamelDBPrivate;
@@ -132,6 +138,7 @@
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_write_fresh_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);
@@ -168,5 +175,9 @@
int camel_db_set_collate (CamelDB *cdb, const char *col, const char *collate, CamelDBCollate func);
/* Migration APIS */
int camel_db_migrate_vfolders_to_14(CamelDB *cdb, const char *folder, CamelException *ex);
+
+int camel_db_start_in_memory_transactions (CamelDB *cdb, CamelException *ex);
+int camel_db_flush_in_memory_transactions (CamelDB *cdb, const char * folder_name, CamelException *ex);
+
#endif
Index: camel/camel-folder-summary.c
===================================================================
--- camel/camel-folder-summary.c (revision 9841)
+++ camel/camel-folder-summary.c (revision 9842)
@@ -129,7 +129,7 @@
static int content_info_save(CamelFolderSummary *, FILE *, CamelMessageContentInfo *);
static void content_info_free(CamelFolderSummary *, CamelMessageContentInfo *);
-static int save_message_infos_to_db (CamelFolderSummary *s, CamelException *ex);
+static int save_message_infos_to_db (CamelFolderSummary *s, gboolean fresh_mir, CamelException *ex);
static int camel_read_mir_callback (void * ref, int ncol, char ** cols, char ** name);
static char *next_uid_string(CamelFolderSummary *s);
@@ -1237,23 +1237,20 @@
if (fclose (in) != 0)
return -1;
+ record = (((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->summary_header_to_db (s, &ex));
+ if (!record) {
+ return -1;
+ }
- camel_db_begin_transaction (cdb, &ex);
+ ret = save_message_infos_to_db (s, TRUE, &ex);
- ret = save_message_infos_to_db (s, &ex);
-
if (ret != 0) {
- camel_db_abort_transaction (cdb, &ex);
return -1;
}
- camel_db_end_transaction (cdb, &ex);
-
- record = (((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->summary_header_to_db (s, &ex));
- if (!record) {
- return -1;
- }
+ camel_db_begin_transaction (cdb, &ex);
ret = camel_db_write_folder_info_record (cdb, record, &ex);
+ camel_db_end_transaction (cdb, &ex);
g_free (record->bdata);
g_free (record);
@@ -1321,17 +1318,24 @@
return 0;
}
+typedef struct {
+ CamelException *ex;
+ gboolean migration;
+ int progress;
+} SaveToDBArgs;
+
static void
save_to_db_cb (gpointer key, gpointer value, gpointer data)
{
- CamelException *ex = (CamelException *)data;
+ SaveToDBArgs *args = (SaveToDBArgs *) data;
+ CamelException *ex = args->ex;
CamelMessageInfoBase *mi = (CamelMessageInfoBase *)value;
CamelFolderSummary *s = (CamelFolderSummary *)mi->summary;
char *folder_name = s->folder->full_name;
CamelDB *cdb = s->folder->parent_store->cdb_w;
CamelMIRecord *mir;
- if (!mi->dirty)
+ if (!args->migration && !mi->dirty)
return;
mir = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->message_info_to_db (s, (CamelMessageInfo *)mi);
@@ -1345,30 +1349,52 @@
}
}
- if (camel_db_write_message_info_record (cdb, folder_name, mir, ex) != 0) {
- camel_db_camel_mir_free (mir);
- return;
+ if (!args->migration) {
+ if (camel_db_write_message_info_record (cdb, folder_name, mir, ex) != 0) {
+ camel_db_camel_mir_free (mir);
+ return;
+ }
+ } else {
+ if (camel_db_write_fresh_message_info_record (cdb, CAMEL_DB_IN_MEMORY_TABLE, mir, ex) != 0) {
+ camel_db_camel_mir_free (mir);
+ return;
+ }
+
+ if (args->progress > CAMEL_DB_IN_MEMORY_TABLE_LIMIT) {
+ g_print ("BULK INsert limit reached \n");
+ camel_db_flush_in_memory_transactions (cdb, folder_name, ex);
+ camel_db_start_in_memory_transactions (cdb, ex);
+ args->progress = 0;
+ } else {
+ args->progress ++;
+ }
}
/* Reset the flags */
mi->dirty = FALSE;
+ mi->flags &= ~CAMEL_MESSAGE_FOLDER_FLAGGED;
camel_db_camel_mir_free (mir);
}
static int
-save_message_infos_to_db (CamelFolderSummary *s, CamelException *ex)
+save_message_infos_to_db (CamelFolderSummary *s, gboolean fresh_mirs, CamelException *ex)
{
CamelDB *cdb = s->folder->parent_store->cdb_w;
char *folder_name;
+ SaveToDBArgs args;
+ args.ex = ex;
+ args.migration = fresh_mirs;
+ args.progress = 0;
+
folder_name = s->folder->full_name;
if (camel_db_prepare_message_info_table (cdb, folder_name, ex) != 0) {
return -1;
}
CAMEL_SUMMARY_LOCK(s, summary_lock);
/* Push MessageInfo-es */
- g_hash_table_foreach (s->loaded_infos, save_to_db_cb, ex);
+ g_hash_table_foreach (s->loaded_infos, save_to_db_cb, &args);
CAMEL_SUMMARY_UNLOCK(s, summary_lock);
/* FIXME[disk-summary] make sure we free the message infos that are loaded
* are freed if not used anymore or should we leave that to the timer? */
@@ -1398,7 +1424,7 @@
camel_db_begin_transaction (cdb, ex);
- ret = save_message_infos_to_db (s, ex);
+ ret = save_message_infos_to_db (s, FALSE, ex);
if (ret != 0) {
camel_db_abort_transaction (cdb, ex);
/* Failed, so lets reset the flag */