[evolution-data-server] CamelFolderSummary API changes



commit 508ea7c93045d61d3f72807c253c820c9e42b262
Author: Milan Crha <mcrha redhat com>
Date:   Thu Oct 6 16:57:51 2011 +0200

    CamelFolderSummary API changes

 camel/camel-db.c                                |  303 +++-
 camel/camel-db.h                                |   49 +-
 camel/camel-disco-folder.c                      |   16 +-
 camel/camel-folder-search.c                     |    2 +-
 camel/camel-folder-summary.c                    | 2169 +++++++++++++----------
 camel/camel-folder-summary.h                    |  335 ++--
 camel/camel-folder-thread.c                     |   10 +-
 camel/camel-folder.c                            |   36 +-
 camel/camel-store-summary.c                     |  158 ++-
 camel/camel-store-summary.h                     |    4 +
 camel/camel-vee-folder.c                        |  232 +--
 camel/camel-vee-summary.c                       |  110 +-
 camel/camel-vee-summary.h                       |    4 +-
 camel/camel-vtrash-folder.c                     |    8 +-
 camel/providers/imap/camel-imap-folder.c        |  259 +--
 camel/providers/imap/camel-imap-message-cache.c |    6 +-
 camel/providers/imap/camel-imap-store.c         |   42 +-
 camel/providers/imap/camel-imap-summary.c       |   45 +-
 camel/providers/imap/camel-imap-utils.c         |   33 +-
 camel/providers/imapx/camel-imapx-folder.c      |   12 +
 camel/providers/imapx/camel-imapx-server.c      |  120 +-
 camel/providers/imapx/camel-imapx-store.c       |    4 +-
 camel/providers/imapx/camel-imapx-summary.c     |   44 +-
 camel/providers/imapx/camel-imapx-utils.c       |  121 +--
 camel/providers/imapx/camel-imapx-utils.h       |    1 -
 camel/providers/local/camel-local-folder.c      |    2 +-
 camel/providers/local/camel-local-summary.c     |   69 +-
 camel/providers/local/camel-local-summary.h     |    4 +-
 camel/providers/local/camel-maildir-folder.c    |    8 +-
 camel/providers/local/camel-maildir-store.c     |    6 +-
 camel/providers/local/camel-maildir-summary.c   |   31 +-
 camel/providers/local/camel-mbox-folder.c       |    8 +-
 camel/providers/local/camel-mbox-store.c        |    6 +-
 camel/providers/local/camel-mbox-summary.c      |  126 +-
 camel/providers/local/camel-mh-folder.c         |    2 +-
 camel/providers/local/camel-mh-store.c          |    6 +-
 camel/providers/local/camel-mh-summary.c        |   30 +-
 camel/providers/local/camel-spool-summary.c     |   14 +-
 camel/providers/nntp/camel-nntp-folder.c        |   14 +-
 camel/providers/nntp/camel-nntp-summary.c       |   79 +-
 40 files changed, 2434 insertions(+), 2094 deletions(-)
---
diff --git a/camel/camel-db.c b/camel/camel-db.c
index bef5e24..5d8d67f 100644
--- a/camel/camel-db.c
+++ b/camel/camel-db.c
@@ -1070,33 +1070,42 @@ camel_db_delete_uid_from_vfolder_transaction (CamelDB *db,
 }
 
 static gint
-read_uids_callback (gpointer ref,
+read_uids_callback (gpointer ref_array,
                     gint ncol,
                     gchar **cols,
                     gchar **name)
 {
-	GPtrArray *array = (GPtrArray *) ref;
+	GPtrArray *array = ref_array;
 
-	#if 0
-	gint i;
-	for (i = 0; i < ncol; ++i) {
-		if (!name[i] || !cols[i])
-			continue;
+	g_return_val_if_fail (ncol == 1, 0);
 
-		if (!strcmp (name [i], "uid"))
-			g_ptr_array_add (array, (gchar *) (camel_pstring_strdup (cols[i])));
-	}
-	#else
-		if (cols[0])
-			g_ptr_array_add (array, (gchar *) (camel_pstring_strdup (cols[0])));
-	#endif
+	if (cols[0])
+		g_ptr_array_add (array, (gchar *) (camel_pstring_strdup (cols[0])));
 
-	 return 0;
+	return 0;
+}
+
+static gint
+read_uids_to_hash_callback (gpointer ref_hash,
+			    gint ncol,
+			    gchar **cols,
+			    gchar **name)
+{
+	GHashTable *hash = ref_hash;
+
+	g_return_val_if_fail (ncol == 2, 0);
+
+	if (cols[0])
+		g_hash_table_insert (hash, (gchar *) camel_pstring_strdup (cols[0]), GUINT_TO_POINTER (cols[1] ? strtoul (cols[1], NULL, 10) : 0));
+
+	return 0;
 }
 
 /**
  * camel_db_get_folder_uids:
  *
+ * Fills hash with uid->GUINT_TO_POINTER (flag)
+ *
  * Since: 2.24
  **/
 gint
@@ -1104,15 +1113,15 @@ camel_db_get_folder_uids (CamelDB *db,
                           const gchar *folder_name,
                           const gchar *sort_by,
                           const gchar *collate,
-                          GPtrArray *array,
+                          GHashTable *hash,
                           GError **error)
 {
 	 gchar *sel_query;
 	 gint ret;
 
-	 sel_query = sqlite3_mprintf("SELECT uid FROM %Q%s%s%s%s", folder_name, sort_by ? " order by " : "", sort_by ? sort_by: "", (sort_by && collate) ? " collate " : "", (sort_by && collate) ? collate : "");
+	 sel_query = sqlite3_mprintf("SELECT uid,flags FROM %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, error);
+	 ret = camel_db_select (db, sel_query, read_uids_to_hash_callback, hash, error);
 	 sqlite3_free (sel_query);
 
 	 return ret;
@@ -1172,13 +1181,19 @@ camel_db_get_folder_deleted_uids (CamelDB *db,
 	 return array;
 }
 
+struct ReadPreviewData
+{
+	GHashTable *columns_hash;
+	GHashTable *hash;
+};
+
 static gint
 read_preview_callback (gpointer ref,
                        gint ncol,
                        gchar **cols,
                        gchar **name)
 {
-	GHashTable *hash = (GHashTable *) ref;
+	struct ReadPreviewData *rpd = ref;
 	const gchar *uid = NULL;
 	gchar *msg = NULL;
 	gint i;
@@ -1187,13 +1202,20 @@ read_preview_callback (gpointer ref,
 		if (!name[i] || !cols[i])
 			continue;
 
-		if (!strcmp (name [i], "uid"))
-			uid = camel_pstring_strdup (cols[i]);
-		else if (!strcmp (name [i], "preview"))
-			msg = g_strdup (cols[i]);
+		switch (camel_db_get_column_ident (&rpd->columns_hash, i, ncol, name)) {
+			case CAMEL_DB_COLUMN_UID:
+				uid = camel_pstring_strdup (cols[i]);
+				break;
+			case CAMEL_DB_COLUMN_PREVIEW:
+				msg = g_strdup (cols[i]);
+				break;
+			default:
+				g_warn_if_reached ();
+				break;
+		}
 	}
 
-	g_hash_table_insert (hash, (gchar *) uid, msg);
+	g_hash_table_insert (rpd->hash, (gchar *) uid, msg);
 
 	return 0;
 }
@@ -1208,21 +1230,28 @@ camel_db_get_folder_preview (CamelDB *db,
                              const gchar *folder_name,
                              GError **error)
 {
-	 gchar *sel_query;
-	 gint ret;
-	 GHashTable *hash = g_hash_table_new (g_str_hash, g_str_equal);
+	gchar *sel_query;
+	gint ret;
+	struct ReadPreviewData rpd;
+	GHashTable *hash = g_hash_table_new (g_str_hash, g_str_equal);
 
-	 sel_query = sqlite3_mprintf("SELECT uid, preview FROM '%q_preview'", folder_name);
+	sel_query = sqlite3_mprintf ("SELECT uid, preview FROM '%q_preview'", folder_name);
 
-	 ret = camel_db_select (db, sel_query, read_preview_callback, hash, error);
-	 sqlite3_free (sel_query);
+	rpd.columns_hash = NULL;
+	rpd.hash = hash;
 
-	 if (!g_hash_table_size (hash) || ret != 0) {
-		 g_hash_table_destroy (hash);
-		 hash = NULL;
-	 }
+	ret = camel_db_select (db, sel_query, read_preview_callback, &rpd, error);
+	sqlite3_free (sel_query);
+
+	if (rpd.columns_hash)
+		g_hash_table_destroy (rpd.columns_hash);
 
-	 return hash;
+	if (!g_hash_table_size (hash) || ret != 0) {
+		g_hash_table_destroy (hash);
+		hash = NULL;
+	}
+
+	return hash;
 }
 
 /**
@@ -1256,20 +1285,8 @@ read_vuids_callback (gpointer ref,
 {
 	GPtrArray *array = (GPtrArray *) ref;
 
-	#if 0
-	gint i;
-
-	for (i = 0; i < ncol; ++i) {
-		if (!name[i] || !cols[i] || strlen (cols[i]) <= 8)
-			continue;
-
-		if (!strcmp (name [i], "vuid"))
-			g_ptr_array_add (array, (gchar *) (camel_pstring_strdup (cols[i]+8)));
-	}
-	#else
-		if (cols[0] && strlen (cols[0]) > 8)
-			g_ptr_array_add (array, (gchar *) (camel_pstring_strdup (cols[0]+8)));
-	#endif
+	if (cols[0] && strlen (cols[0]) > 8)
+		g_ptr_array_add (array, (gchar *) (camel_pstring_strdup (cols[0]+8)));
 
 	return 0;
 }
@@ -1768,13 +1785,19 @@ camel_db_write_folder_info_record (CamelDB *cdb,
 	return ret;
 }
 
+struct ReadFirData
+{
+	GHashTable *columns_hash;
+	CamelFIRecord *record;
+};
+
 static gint
 read_fir_callback (gpointer ref,
                    gint ncol,
                    gchar **cols,
                    gchar **name)
 {
-	CamelFIRecord *record = *(CamelFIRecord **) ref;
+	struct ReadFirData *rfd = ref;
 	gint i;
 
 	d(g_print ("\nread_fir_callback called \n"));
@@ -1783,39 +1806,47 @@ read_fir_callback (gpointer ref,
 		if (!name[i] || !cols[i])
 			continue;
 
-		if (!strcmp (name [i], "folder_name"))
-			record->folder_name = g_strdup (cols[i]);
-
-		else if (!strcmp (name [i], "version"))
-			record->version = cols[i] ? strtoul (cols[i], NULL, 10) : 0;
-
-		else if (!strcmp (name [i], "flags"))
-			record->flags = cols[i] ? strtoul (cols[i], NULL, 10) : 0;
-
-		else if (!strcmp (name [i], "nextuid"))
-			record->nextuid = cols[i] ? strtoul (cols[i], NULL, 10) : 0;
-
-		else if (!strcmp (name [i], "time"))
-			record->time = cols[i] ? strtoul (cols[i], NULL, 10) : 0;
-
-		else if (!strcmp (name [i], "saved_count"))
-			record->saved_count = cols[i] ? strtoul (cols[i], NULL, 10) : 0;
-
-		else if (!strcmp (name [i], "unread_count"))
-			record->unread_count = cols[i] ? strtoul (cols[i], NULL, 10) : 0;
-
-		else if (!strcmp (name [i], "deleted_count"))
-			record->deleted_count = cols[i] ? strtoul (cols[i], NULL, 10) : 0;
-
-		else if (!strcmp (name [i], "junk_count"))
-			record->junk_count = cols[i] ? strtoul (cols[i], NULL, 10) : 0;
-		else if (!strcmp (name [i], "visible_count"))
-			record->visible_count = cols[i] ? strtoul (cols[i], NULL, 10) : 0;
-		else if (!strcmp (name [i], "jnd_count"))
-			record->jnd_count = cols[i] ? strtoul (cols[i], NULL, 10) : 0;
-		else if (!strcmp (name [i], "bdata"))
-			record->bdata = g_strdup (cols[i]);
-
+		switch (camel_db_get_column_ident (&rfd->columns_hash, i, ncol, name)) {
+			case CAMEL_DB_COLUMN_FOLDER_NAME:
+				rfd->record->folder_name = g_strdup (cols[i]);
+				break;
+			case CAMEL_DB_COLUMN_VERSION:
+				rfd->record->version = cols[i] ? strtoul (cols[i], NULL, 10) : 0;
+				break;
+			case CAMEL_DB_COLUMN_FLAGS:
+				rfd->record->flags = cols[i] ? strtoul (cols[i], NULL, 10) : 0;
+				break;
+			case CAMEL_DB_COLUMN_NEXTUID:
+				rfd->record->nextuid = cols[i] ? strtoul (cols[i], NULL, 10) : 0;
+				break;
+			case CAMEL_DB_COLUMN_TIME:
+				rfd->record->time = cols[i] ? strtoul (cols[i], NULL, 10) : 0;
+				break;
+			case CAMEL_DB_COLUMN_SAVED_COUNT:
+				rfd->record->saved_count = cols[i] ? strtoul (cols[i], NULL, 10) : 0;
+				break;
+			case CAMEL_DB_COLUMN_UNREAD_COUNT:
+				rfd->record->unread_count = cols[i] ? strtoul (cols[i], NULL, 10) : 0;
+				break;
+			case CAMEL_DB_COLUMN_DELETED_COUNT:
+				rfd->record->deleted_count = cols[i] ? strtoul (cols[i], NULL, 10) : 0;
+				break;
+			case CAMEL_DB_COLUMN_JUNK_COUNT:
+				rfd->record->junk_count = cols[i] ? strtoul (cols[i], NULL, 10) : 0;
+				break;
+			case CAMEL_DB_COLUMN_VISIBLE_COUNT:
+				rfd->record->visible_count = cols[i] ? strtoul (cols[i], NULL, 10) : 0;
+				break;
+			case CAMEL_DB_COLUMN_JND_COUNT:
+				rfd->record->jnd_count = cols[i] ? strtoul (cols[i], NULL, 10) : 0;
+				break;
+			case CAMEL_DB_COLUMN_BDATA:
+				rfd->record->bdata = g_strdup (cols[i]);
+				break;
+			default:
+				g_warn_if_reached ();
+				break;
+		}
 	}
 
 	return 0;
@@ -1829,17 +1860,24 @@ read_fir_callback (gpointer ref,
 gint
 camel_db_read_folder_info_record (CamelDB *cdb,
                                   const gchar *folder_name,
-                                  CamelFIRecord **record,
+                                  CamelFIRecord *record,
                                   GError **error)
 {
+	struct ReadFirData rfd;
 	gchar *query;
 	gint ret;
 
-	query = sqlite3_mprintf ("SELECT * FROM folders WHERE folder_name = %Q", folder_name);
-	ret = camel_db_select (cdb, query, read_fir_callback, record, error);
+	rfd.columns_hash = NULL;
+	rfd.record = record;
 
+	query = sqlite3_mprintf ("SELECT * FROM folders WHERE folder_name = %Q", folder_name);
+	ret = camel_db_select (cdb, query, read_fir_callback, &rfd, error);
 	sqlite3_free (query);
-	return (ret);
+
+	if (rfd.columns_hash)
+		g_hash_table_destroy (rfd.columns_hash);
+
+	return ret;
 }
 
 /**
@@ -2370,3 +2408,94 @@ camel_db_flush_in_memory_transactions (CamelDB *cdb,
 
 	return ret;
 }
+
+static struct _known_column_names {
+	const gchar *name;
+	CamelDBKnownColumnNames ident;
+} known_column_names[] = {
+	{ "attachment",			CAMEL_DB_COLUMN_ATTACHMENT },
+	{ "bdata",			CAMEL_DB_COLUMN_BDATA },
+	{ "bodystructure",		CAMEL_DB_COLUMN_BODYSTRUCTURE },
+	{ "cinfo",			CAMEL_DB_COLUMN_CINFO },
+	{ "deleted",			CAMEL_DB_COLUMN_DELETED },
+	{ "deleted_count",		CAMEL_DB_COLUMN_DELETED_COUNT },
+	{ "dreceived",			CAMEL_DB_COLUMN_DRECEIVED },
+	{ "dsent",			CAMEL_DB_COLUMN_DSENT },
+	{ "flags",			CAMEL_DB_COLUMN_FLAGS },
+	{ "folder_name",		CAMEL_DB_COLUMN_FOLDER_NAME },
+	{ "followup_completed_on",	CAMEL_DB_COLUMN_FOLLOWUP_COMPLETED_ON },
+	{ "followup_due_by",		CAMEL_DB_COLUMN_FOLLOWUP_DUE_BY },
+	{ "followup_flag",		CAMEL_DB_COLUMN_FOLLOWUP_FLAG },
+	{ "important",			CAMEL_DB_COLUMN_IMPORTANT },
+	{ "jnd_count",			CAMEL_DB_COLUMN_JND_COUNT },
+	{ "junk",			CAMEL_DB_COLUMN_JUNK },
+	{ "junk_count",			CAMEL_DB_COLUMN_JUNK_COUNT },
+	{ "labels",			CAMEL_DB_COLUMN_LABELS },
+	{ "mail_cc",			CAMEL_DB_COLUMN_MAIL_CC },
+	{ "mail_from",			CAMEL_DB_COLUMN_MAIL_FROM },
+	{ "mail_to",			CAMEL_DB_COLUMN_MAIL_TO },
+	{ "mlist",			CAMEL_DB_COLUMN_MLIST },
+	{ "nextuid",			CAMEL_DB_COLUMN_NEXTUID },
+	{ "part",			CAMEL_DB_COLUMN_PART },
+	{ "preview",			CAMEL_DB_COLUMN_PREVIEW },
+	{ "read",			CAMEL_DB_COLUMN_READ },
+	{ "replied",			CAMEL_DB_COLUMN_REPLIED },
+	{ "saved_count",		CAMEL_DB_COLUMN_SAVED_COUNT },
+	{ "size",			CAMEL_DB_COLUMN_SIZE },
+	{ "subject",			CAMEL_DB_COLUMN_SUBJECT },
+	{ "time",			CAMEL_DB_COLUMN_TIME },
+	{ "uid",			CAMEL_DB_COLUMN_UID },
+	{ "unread_count",		CAMEL_DB_COLUMN_UNREAD_COUNT },
+	{ "usertags",			CAMEL_DB_COLUMN_USERTAGS },
+	{ "version",			CAMEL_DB_COLUMN_VERSION },
+	{ "visible_count",		CAMEL_DB_COLUMN_VISIBLE_COUNT },
+	{ "vuid",			CAMEL_DB_COLUMN_VUID }
+};
+
+/**
+ * camel_db_get_column_ident:
+ * Traverses column name from index @index into an enum #CamelDBKnownColumnNames value;
+ * The @col_names contains @ncols columns. First time this is called is created
+ * the @hash from col_names indexes into the enum, and this is reused for every other call.
+ * The function expects that column names are returned always in the same order.
+ * When all rows are read the @hash table can be freed with g_hash_table_destroy().
+ **/
+CamelDBKnownColumnNames
+camel_db_get_column_ident (GHashTable **hash, gint index, gint ncols, gchar **col_names)
+{
+	gpointer value = NULL;
+
+	g_return_val_if_fail (hash != NULL, CAMEL_DB_COLUMN_UNKNOWN);
+	g_return_val_if_fail (col_names != NULL, CAMEL_DB_COLUMN_UNKNOWN);
+	g_return_val_if_fail (ncols > 0, CAMEL_DB_COLUMN_UNKNOWN);
+	g_return_val_if_fail (index >= 0, CAMEL_DB_COLUMN_UNKNOWN);
+	g_return_val_if_fail (index < ncols, CAMEL_DB_COLUMN_UNKNOWN);
+
+	if (!*hash) {
+		gint ii, jj, from, max = G_N_ELEMENTS (known_column_names);
+
+		*hash = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+		for (ii = 0, jj = 0; ii < ncols; ii++) {
+			const gchar *name = col_names[ii];
+			gboolean first = TRUE;
+
+			if (!name)
+				continue;
+
+			for (from = jj; first || jj != from; jj = (jj + 1) % max, first = FALSE) {
+				if (g_str_equal (name, known_column_names[jj].name)) {
+					g_hash_table_insert (*hash, GINT_TO_POINTER (ii), GINT_TO_POINTER (known_column_names[jj].ident));
+					break;
+				}
+			}
+
+			if (from == jj && !first)
+				g_warning ("%s: missing column name '%s' in a list of known columns", G_STRFUNC, name);
+		}
+	}
+
+	g_return_val_if_fail (g_hash_table_lookup_extended (*hash, GINT_TO_POINTER (index), NULL, &value), CAMEL_DB_COLUMN_UNKNOWN);
+
+	return GPOINTER_TO_INT (value);
+}
diff --git a/camel/camel-db.h b/camel/camel-db.h
index ad89225..b4c1721 100644
--- a/camel/camel-db.h
+++ b/camel/camel-db.h
@@ -200,6 +200,49 @@ typedef struct _CamelFIRecord {
 
 typedef struct _CamelDB CamelDB;
 
+typedef enum {
+	CAMEL_DB_COLUMN_UNKNOWN = -1,
+	CAMEL_DB_COLUMN_ATTACHMENT,
+	CAMEL_DB_COLUMN_BDATA,
+	CAMEL_DB_COLUMN_BODYSTRUCTURE,
+	CAMEL_DB_COLUMN_CINFO,
+	CAMEL_DB_COLUMN_DELETED,
+	CAMEL_DB_COLUMN_DELETED_COUNT,
+	CAMEL_DB_COLUMN_DRECEIVED,
+	CAMEL_DB_COLUMN_DSENT,
+	CAMEL_DB_COLUMN_FLAGS,
+	CAMEL_DB_COLUMN_FOLDER_NAME,
+	CAMEL_DB_COLUMN_FOLLOWUP_COMPLETED_ON,
+	CAMEL_DB_COLUMN_FOLLOWUP_DUE_BY,
+	CAMEL_DB_COLUMN_FOLLOWUP_FLAG,
+	CAMEL_DB_COLUMN_IMPORTANT,
+	CAMEL_DB_COLUMN_JND_COUNT,
+	CAMEL_DB_COLUMN_JUNK,
+	CAMEL_DB_COLUMN_JUNK_COUNT,
+	CAMEL_DB_COLUMN_LABELS,
+	CAMEL_DB_COLUMN_MAIL_CC,
+	CAMEL_DB_COLUMN_MAIL_FROM,
+	CAMEL_DB_COLUMN_MAIL_TO,
+	CAMEL_DB_COLUMN_MLIST,
+	CAMEL_DB_COLUMN_NEXTUID,
+	CAMEL_DB_COLUMN_PART,
+	CAMEL_DB_COLUMN_PREVIEW,
+	CAMEL_DB_COLUMN_READ,
+	CAMEL_DB_COLUMN_REPLIED,
+	CAMEL_DB_COLUMN_SAVED_COUNT,
+	CAMEL_DB_COLUMN_SIZE,
+	CAMEL_DB_COLUMN_SUBJECT,
+	CAMEL_DB_COLUMN_TIME,
+	CAMEL_DB_COLUMN_UID,
+	CAMEL_DB_COLUMN_UNREAD_COUNT,
+	CAMEL_DB_COLUMN_USERTAGS,
+	CAMEL_DB_COLUMN_VERSION,
+	CAMEL_DB_COLUMN_VISIBLE_COUNT,
+	CAMEL_DB_COLUMN_VUID
+} CamelDBKnownColumnNames;
+
+CamelDBKnownColumnNames camel_db_get_column_ident (GHashTable **hash, gint index, gint ncols, gchar **col_names);
+
 /**
  * CamelDBSelectCB:
  *
@@ -231,7 +274,7 @@ gint camel_db_create_folders_table (CamelDB *cdb, GError **error);
 gint camel_db_select (CamelDB *cdb, const gchar * stmt, CamelDBSelectCB callback, gpointer data, GError **error);
 
 gint camel_db_write_folder_info_record (CamelDB *cdb, CamelFIRecord *record, GError **error);
-gint camel_db_read_folder_info_record (CamelDB *cdb, const gchar *folder_name, CamelFIRecord **record, GError **error);
+gint camel_db_read_folder_info_record (CamelDB *cdb, const gchar *folder_name, CamelFIRecord *record, GError **error);
 
 gint camel_db_prepare_message_info_table (CamelDB *cdb, const gchar *folder_name, GError **error);
 
@@ -260,7 +303,7 @@ GPtrArray * camel_db_get_vuids_from_vfolder (CamelDB *db, const gchar *folder_na
 gint camel_db_add_to_vfolder (CamelDB *db, gchar *folder_name, gchar *vuid, GError **error);
 gint camel_db_add_to_vfolder_transaction (CamelDB *db, const gchar *folder_name, const gchar *vuid, GError **error);
 
-gint camel_db_get_folder_uids (CamelDB *db, const gchar *folder_name, const gchar *sort_by, const gchar *collate, GPtrArray *array, GError **error);
+gint camel_db_get_folder_uids (CamelDB *db, const gchar *folder_name, const gchar *sort_by, const gchar *collate, GHashTable *hash, GError **error);
 
 GPtrArray * camel_db_get_folder_junk_uids (CamelDB *db, gchar *folder_name, GError **error);
 GPtrArray * camel_db_get_folder_deleted_uids (CamelDB *db, const gchar *folder_name, GError **error);
@@ -282,5 +325,5 @@ gint camel_db_write_preview_record (CamelDB *db, const gchar *folder_name, const
 
 gint
 camel_db_reset_folder_version (CamelDB *cdb, const gchar *folder_name, gint reset_version, GError **error);
-#endif
 
+#endif
diff --git a/camel/camel-disco-folder.c b/camel/camel-disco-folder.c
index 81e54a86..56440b2 100644
--- a/camel/camel-disco-folder.c
+++ b/camel/camel-disco-folder.c
@@ -262,25 +262,27 @@ disco_expunge_sync (CamelFolder *folder,
 {
 	GPtrArray *uids;
 	gint i;
-	guint count;
 	CamelMessageInfo *info;
 	gboolean success;
+	GPtrArray *known_uids;
 
 	uids = g_ptr_array_new ();
 	camel_folder_summary_prepare_fetch_all (folder->summary, NULL);
-	count = camel_folder_summary_count (folder->summary);
-	for (i = 0; i < count; i++) {
-		info = camel_folder_summary_index (folder->summary, i);
+	known_uids = camel_folder_summary_get_array (folder->summary);
+	for (i = 0; known_uids && i < known_uids->len; i++) {
+		const gchar *uid = g_ptr_array_index (known_uids, i);
+
+		info = camel_folder_summary_get (folder->summary, uid);
 		if (camel_message_info_flags (info) & CAMEL_MESSAGE_DELETED)
-			g_ptr_array_add (uids, g_strdup (camel_message_info_uid (info)));
+			g_ptr_array_add (uids, (gpointer) uid);
 		camel_message_info_free (info);
 	}
 
 	success = disco_expunge_uids (folder, uids, cancellable, error);
 
-	for (i = 0; i < uids->len; i++)
-		g_free (uids->pdata[i]);
 	g_ptr_array_free (uids, TRUE);
+	if (known_uids)
+		camel_folder_summary_free_array (known_uids);
 
 	return success;
 }
diff --git a/camel/camel-folder-search.c b/camel/camel-folder-search.c
index 5d71725..364c539 100644
--- a/camel/camel-folder-search.c
+++ b/camel/camel-folder-search.c
@@ -883,7 +883,7 @@ search_match_all (struct _ESExp *f,
 	for (i = 0; i < v->len; i++) {
 		const gchar *uid;
 
-		search->current = camel_folder_summary_uid (search->folder->summary, v->pdata[i]);
+		search->current = camel_folder_summary_get (search->folder->summary, v->pdata[i]);
 		if (!search->current)
 			continue;
 		uid = camel_message_info_uid (search->current);
diff --git a/camel/camel-folder-summary.c b/camel/camel-folder-summary.c
index d0cf62f..354b255 100644
--- a/camel/camel-folder-summary.c
+++ b/camel/camel-folder-summary.c
@@ -84,6 +84,24 @@ struct _CamelFolderSummaryPrivate {
 
 	gboolean need_preview;
 	GHashTable *preview_updates;
+
+	guint32 nextuid;	/* next uid? */
+	guint32 saved_count;	/* how many were saved/loaded */
+	guint32 unread_count;	/* handy totals */
+	guint32 deleted_count;
+	guint32 junk_count;
+	guint32 junk_not_deleted_count;
+	guint32 visible_count;
+
+	gchar *summary_path;
+	gboolean build_content;	/* do we try and parse/index the content, or not? */
+
+	GHashTable *uids; /* uids of all known message infos; the 'value' are used flags for the message info */
+	GHashTable *loaded_infos; /* uid->CamelMessageInfo*, those currently in memory */
+
+	struct _CamelFolder *folder; /* parent folder, for events */
+	time_t cache_load_time;
+	guint timeout_handle;
 };
 
 static GStaticMutex info_lock = G_STATIC_MUTEX_INIT;
@@ -101,8 +119,6 @@ static GStaticMutex info_lock = G_STATIC_MUTEX_INIT;
 
 #define CAMEL_FOLDER_SUMMARY_VERSION (14)
 
-#define META_SUMMARY_SUFFIX_LEN 5 /* strlen("-meta") */
-
 /* trivial lists, just because ... */
 struct _node {
 	struct _node *next;
@@ -138,6 +154,19 @@ static CamelMessageContentInfo * summary_build_content_info_message (CamelFolder
 
 static CamelMessageInfo * message_info_from_uid (CamelFolderSummary *s, const gchar *uid);
 
+enum {
+	PROP_0,
+	PROP_FOLDER,
+	PROP_SAVED_COUNT,
+	PROP_UNREAD_COUNT,
+	PROP_DELETED_COUNT,
+	PROP_JUNK_COUNT,
+	PROP_JUNK_NOT_DELETED_COUNT,
+	PROP_VISIBLE_COUNT,
+	PROP_BUILD_CONTENT,
+	PROP_NEED_PREVIEW
+};
+
 G_DEFINE_TYPE (CamelFolderSummary, camel_folder_summary, CAMEL_TYPE_OBJECT)
 
 static void
@@ -204,36 +233,216 @@ static void
 folder_summary_finalize (GObject *object)
 {
 	CamelFolderSummary *summary = CAMEL_FOLDER_SUMMARY (object);
+	CamelFolderSummaryPrivate *priv = summary->priv;
 
-	if (summary->timeout_handle)
-		g_source_remove (summary->timeout_handle);
-	/*camel_folder_summary_clear(s);*/
-	g_ptr_array_foreach (summary->uids, (GFunc) camel_pstring_free, NULL);
-	g_ptr_array_free (summary->uids, TRUE);
-	g_hash_table_destroy (summary->loaded_infos);
+	if (priv->timeout_handle)
+		g_source_remove (priv->timeout_handle);
 
-	g_hash_table_foreach (summary->priv->filter_charset, free_o_name, NULL);
-	g_hash_table_destroy (summary->priv->filter_charset);
+	g_hash_table_destroy (priv->uids);
+	g_hash_table_destroy (priv->loaded_infos);
 
-	g_hash_table_destroy (summary->priv->preview_updates);
+	g_hash_table_foreach (priv->filter_charset, free_o_name, NULL);
+	g_hash_table_destroy (priv->filter_charset);
 
-	g_free (summary->summary_path);
+	g_hash_table_destroy (priv->preview_updates);
 
-	/* Freeing memory occupied by meta-summary-header */
-	g_free (summary->meta_summary->path);
-	g_free (summary->meta_summary);
+	g_free (priv->summary_path);
 
-	g_static_rec_mutex_free (&summary->priv->summary_lock);
-	g_static_rec_mutex_free (&summary->priv->io_lock);
-	g_static_rec_mutex_free (&summary->priv->filter_lock);
-	g_static_rec_mutex_free (&summary->priv->alloc_lock);
-	g_static_rec_mutex_free (&summary->priv->ref_lock);
+	g_static_rec_mutex_free (&priv->summary_lock);
+	g_static_rec_mutex_free (&priv->io_lock);
+	g_static_rec_mutex_free (&priv->filter_lock);
+	g_static_rec_mutex_free (&priv->alloc_lock);
+	g_static_rec_mutex_free (&priv->ref_lock);
 
 	/* Chain up to parent's finalize() method. */
 	G_OBJECT_CLASS (camel_folder_summary_parent_class)->finalize (object);
 }
 
-static	gint
+static void
+folder_summary_set_folder (CamelFolderSummary *summary, CamelFolder *folder)
+{
+	g_return_if_fail (summary != NULL);
+	g_return_if_fail (summary->priv != NULL);
+	g_return_if_fail (summary->priv->folder == NULL);
+	/* folder can be NULL in certain cases, see maildir-store */
+	
+	summary->priv->folder = folder;
+}
+
+static void
+folder_summary_set_property (GObject *object,
+			     guint property_id,
+			     const GValue *value,
+			     GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_FOLDER:
+			folder_summary_set_folder (
+				CAMEL_FOLDER_SUMMARY (object),
+				CAMEL_FOLDER (g_value_get_object (value)));
+			return;
+
+		case PROP_BUILD_CONTENT:
+			camel_folder_summary_set_build_content (
+				CAMEL_FOLDER_SUMMARY (object),
+				g_value_get_boolean (value));
+			return;
+
+		case PROP_NEED_PREVIEW:
+			camel_folder_summary_set_need_preview (
+				CAMEL_FOLDER_SUMMARY (object),
+				g_value_get_boolean (value));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+folder_summary_get_property (GObject *object,
+			     guint property_id,
+			     GValue *value,
+			     GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_FOLDER:
+			g_value_set_object (
+				value, camel_folder_summary_get_folder (
+				CAMEL_FOLDER_SUMMARY (object)));
+			return;
+
+		case PROP_SAVED_COUNT:
+			g_value_set_uint (
+				value, camel_folder_summary_get_saved_count (
+				CAMEL_FOLDER_SUMMARY (object)));
+			return;
+
+		case PROP_UNREAD_COUNT:
+			g_value_set_uint (
+				value, camel_folder_summary_get_unread_count (
+				CAMEL_FOLDER_SUMMARY (object)));
+			return;
+
+		case PROP_DELETED_COUNT:
+			g_value_set_uint (
+				value, camel_folder_summary_get_deleted_count (
+				CAMEL_FOLDER_SUMMARY (object)));
+			return;
+
+		case PROP_JUNK_COUNT:
+			g_value_set_uint (
+				value, camel_folder_summary_get_junk_count (
+				CAMEL_FOLDER_SUMMARY (object)));
+			return;
+
+		case PROP_JUNK_NOT_DELETED_COUNT:
+			g_value_set_uint (
+				value, camel_folder_summary_get_junk_not_deleted_count (
+				CAMEL_FOLDER_SUMMARY (object)));
+			return;
+
+		case PROP_VISIBLE_COUNT:
+			g_value_set_uint (
+				value, camel_folder_summary_get_visible_count (
+				CAMEL_FOLDER_SUMMARY (object)));
+			return;
+
+		case PROP_BUILD_CONTENT:
+			g_value_set_boolean (
+				value, camel_folder_summary_get_build_content (
+				CAMEL_FOLDER_SUMMARY (object)));
+			return;
+
+		case PROP_NEED_PREVIEW:
+			g_value_set_boolean (
+				value, camel_folder_summary_get_need_preview (
+				CAMEL_FOLDER_SUMMARY (object)));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+/**
+ * folder_summary_update_counts_by_flags:
+ *
+ * Since: 3.0
+ **/
+static void
+folder_summary_update_counts_by_flags (CamelFolderSummary *summary,
+                                       guint32 flags,
+                                       gboolean subtract)
+{
+	gint unread = 0, deleted = 0, junk = 0;
+	gboolean is_junk_folder = FALSE, is_trash_folder = FALSE;
+	GObject *summary_object;
+
+	g_return_if_fail (summary != NULL);
+	g_return_if_fail (summary->priv != NULL);
+
+	summary_object = G_OBJECT (summary);
+
+	if (summary->priv->folder && CAMEL_IS_VTRASH_FOLDER (summary->priv->folder)) {
+		CamelVTrashFolder *vtrash = CAMEL_VTRASH_FOLDER (summary->priv->folder);
+
+		is_junk_folder = vtrash && vtrash->type == CAMEL_VTRASH_FOLDER_JUNK;
+		is_trash_folder = vtrash && vtrash->type == CAMEL_VTRASH_FOLDER_TRASH;
+	}
+
+	if (!(flags & CAMEL_MESSAGE_SEEN))
+		unread = subtract ? -1 : 1;
+
+	if (flags & CAMEL_MESSAGE_DELETED)
+		deleted = subtract ? -1 : 1;
+
+	if (flags & CAMEL_MESSAGE_JUNK)
+		junk = subtract ? -1 : 1;
+
+	dd(printf("%p: %d %d %d | %d %d %d \n", (gpointer) summary, unread, deleted, junk, summary->priv->unread_count, summary->priv->visible_count, summary->priv->saved_count));
+
+	g_object_freeze_notify (summary_object);
+
+	if (deleted) {
+		summary->priv->deleted_count += deleted;
+		g_object_notify (summary_object, "deleted-count");
+	}
+
+	if (junk) {
+		summary->priv->junk_count += junk;
+		g_object_notify (summary_object, "junk-count");
+	}
+
+	if (junk && !deleted) {
+		summary->priv->junk_not_deleted_count += junk;
+		g_object_notify (summary_object, "junk-not-deleted-count");
+	}
+
+	if (!junk && !deleted) {
+		summary->priv->visible_count += subtract ? -1 : 1;
+		g_object_notify (summary_object, "visible-count");
+	}
+
+	if (junk && !is_junk_folder)
+		unread = 0;
+	if (deleted && !is_trash_folder)
+		unread = 0;
+
+	if (unread) {
+		summary->priv->unread_count += unread;
+		g_object_notify (summary_object, "unread-count");
+	}
+
+	summary->priv->saved_count += subtract ? -1 : 1;
+	g_object_notify (summary_object, "saved-count");
+
+	camel_folder_summary_touch (summary);
+
+	g_object_thaw_notify (summary_object);
+
+	dd(printf("%p: %d %d %d | %d %d %d\n", (gpointer) summary, unread, deleted, junk, summary->priv->unread_count, summary->priv->visible_count, summary->priv->saved_count));
+}
+
+static gboolean
 summary_header_from_db (CamelFolderSummary *s,
                         CamelFIRecord *record)
 {
@@ -247,7 +456,7 @@ summary_header_from_db (CamelFolderSummary *s,
 	if ((s->version > 0xff) && (s->version & 0xff) < 12) {
 		io(printf ("Summary header version mismatch"));
 		errno = EINVAL;
-		return -1;
+		return FALSE;
 	}
 
 	if (!(s->version < 0x100 && s->version >= 13))
@@ -257,17 +466,17 @@ summary_header_from_db (CamelFolderSummary *s,
 #endif
 
 	s->flags = record->flags;
-	s->nextuid = record->nextuid;
+	s->priv->nextuid = record->nextuid;
 	s->time = record->time;
-	s->saved_count = record->saved_count;
+	s->priv->saved_count = record->saved_count;
 
-	s->unread_count = record->unread_count;
-	s->deleted_count = record->deleted_count;
-	s->junk_count = record->junk_count;
-	s->visible_count = record->visible_count;
-	s->junk_not_deleted_count = record->jnd_count;
+	s->priv->unread_count = record->unread_count;
+	s->priv->deleted_count = record->deleted_count;
+	s->priv->junk_count = record->junk_count;
+	s->priv->visible_count = record->visible_count;
+	s->priv->junk_not_deleted_count = record->jnd_count;
 
-	return 0;
+	return TRUE;
 }
 
 static	CamelFIRecord *
@@ -281,8 +490,8 @@ summary_header_to_db (CamelFolderSummary *s,
 
 	/* Though we are going to read, we do this during write,
 	 * so lets use it that way. */
-	table_name = camel_folder_get_full_name (s->folder);
-	parent_store = camel_folder_get_parent_store (s->folder);
+	table_name = camel_folder_get_full_name (s->priv->folder);
+	parent_store = camel_folder_get_parent_store (s->priv->folder);
 	db = parent_store->cdb_w;
 
 	io(printf("Savining header to db\n"));
@@ -292,7 +501,7 @@ summary_header_to_db (CamelFolderSummary *s,
 	/* we always write out the current version */
 	record->version = CAMEL_FOLDER_SUMMARY_VERSION;
 	record->flags  = s->flags;
-	record->nextuid = s->nextuid;
+	record->nextuid = s->priv->nextuid;
 	record->time = s->time;
 
 	/* FIXME: Ever heard of Constructors and initializing ? */
@@ -309,11 +518,11 @@ summary_header_to_db (CamelFolderSummary *s,
 	if (camel_db_count_junk_not_deleted_message_info (db, table_name, &(record->jnd_count), NULL))
 		record->jnd_count = 0;
 
-	s->unread_count = record->unread_count;
-	s->deleted_count = record->deleted_count;
-	s->junk_count = record->junk_count;
-	s->visible_count = record->visible_count;
-	s->junk_not_deleted_count = record->jnd_count;
+	s->priv->unread_count = record->unread_count;
+	s->priv->deleted_count = record->deleted_count;
+	s->priv->junk_count = record->junk_count;
+	s->priv->visible_count = record->visible_count;
+	s->priv->junk_not_deleted_count = record->jnd_count;
 
 	return record;
 }
@@ -527,7 +736,7 @@ content_info_from_db (CamelFolderSummary *s,
 	return ci;
 }
 
-static gint
+static gboolean
 content_info_to_db (CamelFolderSummary *s,
                     CamelMessageContentInfo *ci,
                     CamelMIRecord *record)
@@ -591,14 +800,15 @@ content_info_to_db (CamelFolderSummary *s,
 		g_string_free (str, FALSE);
 	}
 
-	return 0;
+	return TRUE;
 }
 
 static gint
 summary_header_save (CamelFolderSummary *s,
                      FILE *out)
 {
-	gint unread = 0, deleted = 0, junk = 0, count, i;
+	gint unread = 0, deleted = 0, junk = 0, i;
+	GPtrArray *known_uids;
 
 	fseek (out, 0, SEEK_SET);
 
@@ -607,12 +817,12 @@ summary_header_save (CamelFolderSummary *s,
 	/* we always write out the current version */
 	camel_file_util_encode_fixed_int32 (out, CAMEL_FOLDER_SUMMARY_VERSION);
 	camel_file_util_encode_fixed_int32 (out, s->flags);
-	camel_file_util_encode_fixed_int32 (out, s->nextuid);
+	camel_file_util_encode_fixed_int32 (out, s->priv->nextuid);
 	camel_file_util_encode_time_t (out, s->time);
 
-	count = camel_folder_summary_count (s);
-	for (i = 0; i < count; i++) {
-		CamelMessageInfo *info = camel_folder_summary_index (s, i);
+	known_uids = camel_folder_summary_get_array (s);
+	for (i = 0; known_uids && i < known_uids->len; i++) {
+		CamelMessageInfo *info = camel_folder_summary_get (s, g_ptr_array_index (known_uids, i));
 		guint32 flags;
 
 		if (info == NULL)
@@ -629,13 +839,70 @@ summary_header_save (CamelFolderSummary *s,
 		camel_message_info_free (info);
 	}
 
-	camel_file_util_encode_fixed_int32 (out, count);
+	camel_folder_summary_free_array (known_uids);
+
+	camel_file_util_encode_fixed_int32 (out, i); /* total count */
 	camel_file_util_encode_fixed_int32 (out, unread);
 	camel_file_util_encode_fixed_int32 (out, deleted);
 
 	return camel_file_util_encode_fixed_int32 (out, junk);
 }
 
+static gboolean
+folder_summary_replace_flags (CamelFolderSummary *summary, CamelMessageInfo *info)
+{
+	guint32 used_flags;
+	GObject *summary_object;
+	guint32 old_saved_count, old_unread_count, old_deleted_count, old_junk_count;
+	guint32 old_junk_not_deleted_count, old_visible_count;
+
+	g_return_val_if_fail (summary != NULL, FALSE);
+	g_return_val_if_fail (summary->priv != NULL, FALSE);
+	g_return_val_if_fail (info != NULL, FALSE);
+
+	if (!camel_message_info_uid (info) ||
+	    !camel_folder_summary_check_uid (summary, camel_message_info_uid (info)))
+		return FALSE;
+
+	summary_object = G_OBJECT (summary);
+
+	camel_folder_summary_lock (summary, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
+	g_object_freeze_notify (summary_object);
+
+	used_flags = GPOINTER_TO_UINT (g_hash_table_lookup (summary->priv->uids, camel_message_info_uid (info)));
+
+	old_saved_count = summary->priv->saved_count;
+	old_unread_count = summary->priv->unread_count;
+	old_deleted_count = summary->priv->deleted_count;
+	old_junk_count = summary->priv->junk_count;
+	old_junk_not_deleted_count = summary->priv->junk_not_deleted_count;
+	old_visible_count = summary->priv->visible_count;
+
+	/* decrement counts with old flags */
+	folder_summary_update_counts_by_flags (summary, used_flags, TRUE);
+
+	/* update current flags on the summary */
+	g_hash_table_insert (summary->priv->uids,
+		(gpointer) camel_pstring_strdup (camel_message_info_uid (info)),
+		GUINT_TO_POINTER (camel_message_info_flags (info)));
+
+	/* increment counts with new flags */
+	folder_summary_update_counts_by_flags (summary, camel_message_info_flags (info), FALSE);
+
+	/* this approach generates false notifications at least for "saved-count",
+	   but is it an issue? I suppose not.
+	*/
+	g_object_thaw_notify (summary_object);
+	camel_folder_summary_unlock (summary, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
+
+	return  old_saved_count != summary->priv->saved_count ||
+		old_unread_count != summary->priv->unread_count ||
+		old_deleted_count != summary->priv->deleted_count ||
+		old_junk_count != summary->priv->junk_count ||
+		old_junk_not_deleted_count != summary->priv->junk_not_deleted_count ||
+		old_visible_count != summary->priv->visible_count;
+}
+
 static CamelMessageInfo *
 message_info_clone (CamelFolderSummary *s,
                     const CamelMessageInfo *mi)
@@ -773,15 +1040,15 @@ info_set_user_flag (CamelMessageInfo *info,
 
 	res = camel_flag_set (&mi->user_flags, name, value);
 
-	/* TODO: check this item is still in the summary first */
-	if (mi->summary && res && mi->summary->folder && mi->uid) {
+	if (mi->summary && res && mi->summary->priv->folder && mi->uid
+	    && camel_folder_summary_check_uid (mi->summary, mi->uid)) {
 		CamelFolderChangeInfo *changes = camel_folder_change_info_new ();
 
 		mi->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED;
 		mi->dirty = TRUE;
 		camel_folder_summary_touch (mi->summary);
 		camel_folder_change_info_change_uid (changes, camel_message_info_uid (info));
-		camel_folder_changed (mi->summary->folder, changes);
+		camel_folder_changed (mi->summary->priv->folder, changes);
 		camel_folder_change_info_free (changes);
 	}
 
@@ -798,14 +1065,15 @@ info_set_user_tag (CamelMessageInfo *info,
 
 	res = camel_tag_set (&mi->user_tags, name, value);
 
-	if (mi->summary && res && mi->summary->folder && mi->uid) {
+	if (mi->summary && res && mi->summary->priv->folder && mi->uid
+	    && camel_folder_summary_check_uid (mi->summary, mi->uid)) {
 		CamelFolderChangeInfo *changes = camel_folder_change_info_new ();
 
 		mi->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED;
 		mi->dirty = TRUE;
 		camel_folder_summary_touch (mi->summary);
 		camel_folder_change_info_change_uid (changes, camel_message_info_uid (info));
-		camel_folder_changed (mi->summary->folder, changes);
+		camel_folder_changed (mi->summary->priv->folder, changes);
 		camel_folder_change_info_free (changes);
 	}
 
@@ -819,19 +1087,9 @@ info_set_flags (CamelMessageInfo *info,
 {
 	guint32 old;
 	CamelMessageInfoBase *mi = (CamelMessageInfoBase *) info;
-	gint read = 0, deleted = 0, junk = 0;
-	/* TODO: locking? */
-
-	if (flags & CAMEL_MESSAGE_SEEN && ((set & CAMEL_MESSAGE_SEEN) != (mi->flags & CAMEL_MESSAGE_SEEN)))
-	{ read = set & CAMEL_MESSAGE_SEEN ? 1 : -1; d(printf("Setting read as %d\n", set & CAMEL_MESSAGE_SEEN ? 1 : 0));}
-
-	if (flags & CAMEL_MESSAGE_DELETED && ((set & CAMEL_MESSAGE_DELETED) != (mi->flags & CAMEL_MESSAGE_DELETED)))
-	{ deleted = set & CAMEL_MESSAGE_DELETED ? 1 : -1; d(printf("Setting deleted as %d\n", set & CAMEL_MESSAGE_DELETED ? 1 : 0));}
-
-	if (flags & CAMEL_MESSAGE_JUNK && ((set & CAMEL_MESSAGE_JUNK) != (mi->flags & CAMEL_MESSAGE_JUNK)))
-	{ junk = set & CAMEL_MESSAGE_JUNK ? 1 : -1; d(printf("Setting junk as %d\n", set & CAMEL_MESSAGE_JUNK ? 1 : 0));}
+	gboolean counts_changed = FALSE;
 
-	old = mi->flags;
+	old = camel_message_info_flags (info);
 	mi->flags = (old & ~flags) | (set & flags);
 	if (old != mi->flags) {
 		mi->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED;
@@ -840,38 +1098,33 @@ info_set_flags (CamelMessageInfo *info,
 			camel_folder_summary_touch (mi->summary);
 	}
 
-	if (((old & ~CAMEL_MESSAGE_SYSTEM_MASK) == (mi->flags & ~CAMEL_MESSAGE_SYSTEM_MASK)) && !((set & CAMEL_MESSAGE_JUNK_LEARN) && !(set & CAMEL_MESSAGE_JUNK)))
+	if (mi->summary) {
+		camel_folder_summary_lock (mi->summary, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
+		g_object_freeze_notify (G_OBJECT (mi->summary));
+		counts_changed = folder_summary_replace_flags (mi->summary, info);
+	}
+
+	if (!counts_changed && ((old & ~CAMEL_MESSAGE_SYSTEM_MASK) == (mi->flags & ~CAMEL_MESSAGE_SYSTEM_MASK)) && !((set & CAMEL_MESSAGE_JUNK_LEARN) && !(set & CAMEL_MESSAGE_JUNK))) {
+		if (mi->summary) {
+			g_object_thaw_notify (G_OBJECT (mi->summary));
+			camel_folder_summary_unlock (mi->summary, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
+		}
 		return FALSE;
+	}
 
 	if (mi->summary) {
-		if (read && junk == 0 && !(mi->flags & CAMEL_MESSAGE_JUNK))
-			mi->summary->unread_count -= read;
-		else if (junk > 0)
-			mi->summary->unread_count -= (old & CAMEL_MESSAGE_SEEN) ? 0 : 1;
-		else if (junk < 0)
-			mi->summary->unread_count -= (old & CAMEL_MESSAGE_SEEN) ? 0 : -1;
-
-		if (deleted)
-			mi->summary->deleted_count += deleted;
-		if (junk)
-			mi->summary->junk_count += junk;
-		if (junk && !deleted)
-			mi->summary->junk_not_deleted_count += junk;
-		else if ((mi->flags & CAMEL_MESSAGE_JUNK) && deleted)
-			mi->summary->junk_not_deleted_count -= deleted;
-
-		if (((junk && !(mi->flags & CAMEL_MESSAGE_DELETED))) || (deleted && !(mi->flags & CAMEL_MESSAGE_JUNK)))
-			mi->summary->visible_count -= junk ? junk : deleted;
-	}
-	if (mi->summary && mi->summary->folder && mi->uid) {
+		g_object_thaw_notify (G_OBJECT (mi->summary));
+		camel_folder_summary_unlock (mi->summary, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
+	}
+
+	if (mi->summary && mi->summary->priv->folder && mi->uid) {
 		CamelFolderChangeInfo *changes = camel_folder_change_info_new ();
 
 		camel_folder_change_info_change_uid (changes, camel_message_info_uid (info));
-		camel_folder_changed (mi->summary->folder, changes);
+		camel_folder_changed (mi->summary->priv->folder, changes);
 		camel_folder_change_info_free (changes);
 	}
 
-	d(printf("%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));
 	return TRUE;
 }
 
@@ -883,6 +1136,8 @@ camel_folder_summary_class_init (CamelFolderSummaryClass *class)
 	g_type_class_add_private (class, sizeof (CamelFolderSummaryPrivate));
 
 	object_class = G_OBJECT_CLASS (class);
+	object_class->set_property = folder_summary_set_property;
+	object_class->get_property = folder_summary_get_property;
 	object_class->dispose = folder_summary_dispose;
 	object_class->finalize = folder_summary_finalize;
 
@@ -926,6 +1181,140 @@ camel_folder_summary_class_init (CamelFolderSummaryClass *class)
 
 	class->info_set_flags = info_set_flags;
 
+	/**
+	 * CamelFolderSummary:folder
+	 *
+	 * The #CamelFolder to which the folder summary belongs.
+	 **/
+	g_object_class_install_property (
+		object_class,
+		PROP_FOLDER,
+		g_param_spec_object (
+			"folder",
+			"Folder",
+			"The folder to which the folder summary belongs",
+			CAMEL_TYPE_FOLDER,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT_ONLY));
+
+	/**
+	 * CamelFolderSummary:saved-count
+	 *
+	 * How many infos is saved in a summary.
+	 **/
+	g_object_class_install_property (
+		object_class,
+		PROP_SAVED_COUNT,
+		g_param_spec_uint (
+			"saved-count",
+			"Saved count",
+			"How many infos is savef in a summary",
+			0,  G_MAXUINT32,
+			0, G_PARAM_READABLE));
+
+	/**
+	 * CamelFolderSummary:unread-count
+	 *
+	 * How many unread infos is saved in a summary.
+	 **/
+	g_object_class_install_property (
+		object_class,
+		PROP_UNREAD_COUNT,
+		g_param_spec_uint (
+			"unread-count",
+			"Unread count",
+			"How many unread infos is saved in a summary",
+			0,  G_MAXUINT32,
+			0, G_PARAM_READABLE));
+
+	/**
+	 * CamelFolderSummary:deleted-count
+	 *
+	 * How many deleted infos is saved in a summary.
+	 **/
+	g_object_class_install_property (
+		object_class,
+		PROP_DELETED_COUNT,
+		g_param_spec_uint (
+			"deleted-count",
+			"Deleted count",
+			"How many deleted infos is saved in a summary",
+			0,  G_MAXUINT32,
+			0, G_PARAM_READABLE));
+
+	/**
+	 * CamelFolderSummary:junk-count
+	 *
+	 * How many junk infos is saved in a summary.
+	 **/
+	g_object_class_install_property (
+		object_class,
+		PROP_JUNK_COUNT,
+		g_param_spec_uint (
+			"junk-count",
+			"Junk count",
+			"How many junk infos is saved in a summary",
+			0,  G_MAXUINT32,
+			0, G_PARAM_READABLE));
+
+	/**
+	 * CamelFolderSummary:junk-not-deleted-count
+	 *
+	 * How many junk and not deleted infos is saved in a summary.
+	 **/
+	g_object_class_install_property (
+		object_class,
+		PROP_JUNK_NOT_DELETED_COUNT,
+		g_param_spec_uint (
+			"junk-not-deleted-count",
+			"Junk not deleted count",
+			"How many junk and not deleted infos is saved in a summary",
+			0,  G_MAXUINT32,
+			0, G_PARAM_READABLE));
+
+	/**
+	 * CamelFolderSummary:visible-count
+	 *
+	 * How many visible (not deleted and not junk) infos is saved in a summary.
+	 **/
+	g_object_class_install_property (
+		object_class,
+		PROP_VISIBLE_COUNT,
+		g_param_spec_uint (
+			"visible-count",
+			"Visible count",
+			"How many visible (not deleted and not junk) infos is saved in a summary",
+			0,  G_MAXUINT32,
+			0, G_PARAM_READABLE));
+
+	/**
+	 * CamelFolderSummary:build-content
+	 *
+	 * Whether to build CamelMessageInfo.content.
+	 **/
+	g_object_class_install_property (
+		object_class,
+		PROP_BUILD_CONTENT,
+		g_param_spec_boolean (
+			"build-content",
+			"Build content",
+			"Whether to build CamelMessageInfo.content",
+			FALSE,
+			G_PARAM_READWRITE));
+
+	/**
+	 * CamelFolderSummary:need-preview
+	 *
+	 **/
+	g_object_class_install_property (
+		object_class,
+		PROP_NEED_PREVIEW,
+		g_param_spec_boolean (
+			"need-preview",
+			"Need preview",
+			"",
+			FALSE,
+			G_PARAM_READWRITE));
 }
 
 static void
@@ -934,24 +1323,19 @@ camel_folder_summary_init (CamelFolderSummary *summary)
 	summary->priv = G_TYPE_INSTANCE_GET_PRIVATE (
 		summary, CAMEL_TYPE_FOLDER_SUMMARY, CamelFolderSummaryPrivate);
 
+	summary->version = CAMEL_FOLDER_SUMMARY_VERSION;
+	summary->flags = 0;
+	summary->time = 0;
+
 	summary->priv->filter_charset = g_hash_table_new (
 		camel_strcase_hash, camel_strcase_equal);
 
-	summary->message_info_chunks = NULL;
-	summary->content_info_chunks = NULL;
 	summary->priv->need_preview = FALSE;
 	summary->priv->preview_updates = g_hash_table_new (g_str_hash, g_str_equal);
-#if defined (DOESTRV) || defined (DOEPOOLV)
-	summary->message_info_strings = CAMEL_MESSAGE_INFO_LAST;
-#endif
 
-	summary->version = CAMEL_FOLDER_SUMMARY_VERSION;
-	summary->flags = 0;
-	summary->time = 0;
-	summary->nextuid = 1;
-
-	summary->uids = g_ptr_array_new ();
-	summary->loaded_infos = g_hash_table_new (g_str_hash, g_str_equal);
+	summary->priv->nextuid = 1;
+	summary->priv->uids = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) camel_pstring_free, NULL);
+	summary->priv->loaded_infos = g_hash_table_new (g_str_hash, g_str_equal);
 
 	g_static_rec_mutex_init (&summary->priv->summary_lock);
 	g_static_rec_mutex_init (&summary->priv->io_lock);
@@ -959,14 +1343,8 @@ camel_folder_summary_init (CamelFolderSummary *summary)
 	g_static_rec_mutex_init (&summary->priv->alloc_lock);
 	g_static_rec_mutex_init (&summary->priv->ref_lock);
 
-	summary->meta_summary = g_malloc0 (sizeof (CamelFolderMetaSummary));
-
-	/* Default is 20, any implementor having UIDs that has length
-	 * exceeding 20, has to override this value
-	*/
-	summary->meta_summary->uid_len = 20;
-	summary->cache_load_time = 0;
-	summary->timeout_handle = 0;
+	summary->priv->cache_load_time = 0;
+	summary->priv->timeout_handle = 0;
 }
 
 /**
@@ -978,284 +1356,535 @@ camel_folder_summary_init (CamelFolderSummary *summary)
  * Returns: a new #CamelFolderSummary object
  **/
 CamelFolderSummary *
-camel_folder_summary_new (struct _CamelFolder *folder)
+camel_folder_summary_new (CamelFolder *folder)
 {
-	CamelFolderSummary *new;
-
-	new = g_object_new (CAMEL_TYPE_FOLDER_SUMMARY, NULL);
-	new->folder = folder;
-
-	return new;
+	return g_object_new (CAMEL_TYPE_FOLDER_SUMMARY, "folder", folder, NULL);
 }
 
 /**
- * camel_folder_summary_set_filename:
+ * camel_folder_summary_get_index:
  * @summary: a #CamelFolderSummary object
- * @filename: a filename
  *
- * Set the filename where the summary will be loaded to/saved from.
+ * Returns: a #CamelFolder to which the summary if associated.
+ *
+ * Since: 3.4
  **/
-void
-camel_folder_summary_set_filename (CamelFolderSummary *s,
-                                   const gchar *name)
+CamelFolder *
+camel_folder_summary_get_folder	(CamelFolderSummary *summary)
 {
-	camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
+	CamelFolderSummaryPrivate *priv;
 
-	g_free (s->summary_path);
-	s->summary_path = g_strdup (name);
+	g_return_val_if_fail (summary != NULL, NULL);
+	g_return_val_if_fail (summary->priv != NULL, NULL);
 
-	g_free (s->meta_summary->path);
-	s->meta_summary->path = g_strconcat(name, "-meta", NULL);
+	priv = summary->priv;
 
-	camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
+	return priv->folder;
 }
 
 /**
- * camel_folder_summary_set_index:
+ * camel_folder_summary_get_saved_count:
  * @summary: a #CamelFolderSummary object
- * @index: a #CamelIndex
  *
- * Set the index used to index body content.  If the index is %NULL, or
- * not set (the default), no indexing of body content will take place.
+ * Returns: Count of saved infos.
  *
- * Unlike earlier behaviour, build_content need not be set to perform indexing.
+ * Since: 3.4
  **/
-void
-camel_folder_summary_set_index (CamelFolderSummary *s,
-                                CamelIndex *index)
+guint32
+camel_folder_summary_get_saved_count (CamelFolderSummary *summary)
 {
-	struct _CamelFolderSummaryPrivate *p = s->priv;
+	CamelFolderSummaryPrivate *priv;
 
-	if (p->index)
-		g_object_unref (p->index);
+	g_return_val_if_fail (summary != NULL, 0);
+	g_return_val_if_fail (summary->priv != NULL, 0);
 
-	p->index = index;
-	if (index)
-		g_object_ref (index);
-}
+	priv = summary->priv;
 
-/**
- * camel_folder_summary_set_build_content:
- * @summary: a #CamelFolderSummary object
- * @state: to build or not to build the content
- *
- * Set a flag to tell the summary to build the content info summary
- * (#CamelMessageInfo.content).  The default is not to build content
- * info summaries.
- **/
-void
-camel_folder_summary_set_build_content (CamelFolderSummary *s,
-                                        gboolean state)
-{
-	s->build_content = state;
+	return priv->saved_count;
 }
 
 /**
- * camel_folder_summary_count:
+ * camel_folder_summary_get_saved_count:
  * @summary: a #CamelFolderSummary object
  *
- * Get the number of summary items stored in this summary.
+ * Returns: Count of unread infos.
  *
- * Returns: the number of items in the summary
+ * Since: 3.4
  **/
-guint
-camel_folder_summary_count (CamelFolderSummary *s)
+guint32
+camel_folder_summary_get_unread_count (CamelFolderSummary *summary)
 {
-	return s->uids->len;
+	CamelFolderSummaryPrivate *priv;
+
+	g_return_val_if_fail (summary != NULL, 0);
+	g_return_val_if_fail (summary->priv != NULL, 0);
+
+	priv = summary->priv;
+
+	return priv->unread_count;
 }
 
 /**
- * camel_folder_summary_index:
+ * camel_folder_summary_get_deleted_count:
  * @summary: a #CamelFolderSummary object
- * @index: item index
  *
- * Retrieve a summary item by index number.
+ * Returns: Count of deleted infos.
  *
- * A referenced to the summary item is returned, which may be
- * ref'd or free'd as appropriate.
- *
- * Returns: the summary item, or %NULL if @index is out of range
+ * Since: 3.4
  **/
-CamelMessageInfo *
-camel_folder_summary_index (CamelFolderSummary *s,
-                            gint i)
+guint32
+camel_folder_summary_get_deleted_count (CamelFolderSummary *summary)
 {
-	CamelMessageInfo *info = NULL;
-
-	camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
-	camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_REF_LOCK);
-
-	if (i < s->uids->len) {
-		gchar *uid;
-		uid = g_ptr_array_index (s->uids, i);
-
-		/* FIXME: Get exception from caller
-		and pass it on below */
-
-		camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_REF_LOCK);
-		camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
+	CamelFolderSummaryPrivate *priv;
 
-		return camel_folder_summary_uid (s, uid);
-	}
+	g_return_val_if_fail (summary != NULL, 0);
+	g_return_val_if_fail (summary->priv != NULL, 0);
 
-	camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_REF_LOCK);
-	camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
+	priv = summary->priv;
 
-	return info;
+	return priv->deleted_count;
 }
 
-/* FIXME[disk-summary] Implement - camel_folder_summary_uid_exist -
- * directly through db than manual strcmp */
-
 /**
- * camel_folder_summary_uid_from_index:
- * @s: a #CamelFolderSummary object
- * @i: item index
- *
- * Retrieve a summary item's uid  by index number.
- *
- * A newly allocated uid is returned, which must be
- * free'd as appropriate.
+ * camel_folder_summary_get_junk_count:
+ * @summary: a #CamelFolderSummary object
  *
- * Returns: the summary item's uid , or %NULL if @index is out of range
+ * Returns: Count of junk infos.
  *
- * Since: 2.24
+ * Since: 3.4
  **/
-gchar *
-camel_folder_summary_uid_from_index (CamelFolderSummary *s,
-                                     gint i)
+guint32
+camel_folder_summary_get_junk_count (CamelFolderSummary *summary)
 {
-	gchar *uid = NULL;
-	camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
-
-	if (i < s->uids->len)
-		uid = g_strdup (g_ptr_array_index (s->uids, i));
+	CamelFolderSummaryPrivate *priv;
 
-	camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
+	g_return_val_if_fail (summary != NULL, 0);
+	g_return_val_if_fail (summary->priv != NULL, 0);
 
-	return uid;
+	priv = summary->priv;
 
+	return priv->junk_count;
 }
 
 /**
- * camel_folder_summary_check_uid
- * @s: a #CamelFolderSummary object
- * @uid: a uid
- *
- * Check if the uid is valid. This isn't very efficient, so it shouldn't be called iteratively.
- *
+ * camel_folder_summary_get_junk_not_deleted_count:
+ * @summary: a #CamelFolderSummary object
  *
- * Returns: if the uid is present in the summary or not  (%TRUE or %FALSE)
+ * Returns: Count of junk and not deleted infos.
  *
- * Since: 2.24
+ * Since: 3.4
  **/
-gboolean
-camel_folder_summary_check_uid (CamelFolderSummary *s,
-                                const gchar *uid)
+guint32
+camel_folder_summary_get_junk_not_deleted_count (CamelFolderSummary *summary)
 {
-	gboolean ret = FALSE;
-	gint i;
-
-	camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
+	CamelFolderSummaryPrivate *priv;
 
-	for (i = 0; i < s->uids->len; i++) {
-		if (strcmp (s->uids->pdata[i], uid) == 0) {
-			camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
-			return TRUE;
-		}
-	}
+	g_return_val_if_fail (summary != NULL, 0);
+	g_return_val_if_fail (summary->priv != NULL, 0);
 
-	camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
+	priv = summary->priv;
 
-	return ret;
+	return priv->junk_not_deleted_count;
 }
 
 /**
- * camel_folder_summary_array:
+ * camel_folder_summary_get_visible_count:
  * @summary: a #CamelFolderSummary object
  *
- * Obtain a copy of the summary array.  This is done atomically,
- * so cannot contain empty entries.
- *
- * It must be freed using g_ptr_array_free
+ * Returns: Count of visible (not junk and not deleted) infos.
  *
- * Returns: a #GPtrArray of uids
+ * Since: 3.4
  **/
-GPtrArray *
-camel_folder_summary_array (CamelFolderSummary *s)
+guint32
+camel_folder_summary_get_visible_count (CamelFolderSummary *summary)
 {
-	GPtrArray *res = g_ptr_array_new ();
-	gint i;
-
-	camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
+	CamelFolderSummaryPrivate *priv;
 
-	g_ptr_array_set_size (res, s->uids->len);
-	for (i = 0; i < s->uids->len; i++)
-		res->pdata[i] = (gpointer) camel_pstring_strdup ((gchar *) g_ptr_array_index (s->uids, i));
+	g_return_val_if_fail (summary != NULL, 0);
+	g_return_val_if_fail (summary->priv != NULL, 0);
 
-	camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
+	priv = summary->priv;
 
-	return res;
+	return priv->visible_count;
 }
 
 /**
- * camel_folder_summary_get_hashtable:
+ * camel_folder_summary_set_index:
  * @summary: a #CamelFolderSummary object
+ * @index: a #CamelIndex
  *
- * Obtain a copy of the summary array in the hashtable.  This is done atomically,
+ * Set the index used to index body content.  If the index is %NULL, or
+ * not set (the default), no indexing of body content will take place.
+ *
+ * Unlike earlier behaviour, build_content need not be set to perform indexing.
+ **/
+void
+camel_folder_summary_set_index (CamelFolderSummary *summary,
+                                CamelIndex *index)
+{
+	CamelFolderSummaryPrivate *priv;
+
+	g_return_if_fail (summary != NULL);
+	g_return_if_fail (summary->priv != NULL);
+
+	priv = summary->priv;
+
+	if (index)
+		g_object_ref (index);
+
+	if (priv->index)
+		g_object_unref (priv->index);
+
+	priv->index = index;
+}
+
+/**
+ * camel_folder_summary_get_index:
+ * @summary: a #CamelFolderSummary object
+ *
+ * Returns: a #CamelIndex used to index body content.
+ *
+ * Since: 3.4
+ **/
+CamelIndex *
+camel_folder_summary_get_index (CamelFolderSummary *summary)
+{
+	CamelFolderSummaryPrivate *priv;
+
+	g_return_val_if_fail (summary != NULL, NULL);
+	g_return_val_if_fail (summary->priv != NULL, NULL);
+
+	priv = summary->priv;
+
+	return priv->index;
+}
+
+/**
+ * camel_folder_summary_set_build_content:
+ * @summary: a #CamelFolderSummary object
+ * @state: to build or not to build the content
+ *
+ * Set a flag to tell the summary to build the content info summary
+ * (#CamelMessageInfo.content).  The default is not to build content
+ * info summaries.
+ **/
+void
+camel_folder_summary_set_build_content (CamelFolderSummary *summary,
+                                        gboolean state)
+{
+	CamelFolderSummaryPrivate *priv;
+
+	g_return_if_fail (summary != NULL);
+	g_return_if_fail (summary->priv != NULL);
+
+	priv = summary->priv;
+
+	if ((priv->build_content ? 1 : 0) == (state ? 1 : 0))
+		return;
+
+	priv->build_content = state;
+
+	g_object_notify (G_OBJECT (summary), "build-content");
+}
+
+/**
+ * camel_folder_summary_get_build_content:
+ * @summary: a #CamelFolderSummary object
+ *
+ * Returns: Whether to build #CamelMessageInfo.content.
+ *
+ * Since: 3.4
+ **/
+gboolean
+camel_folder_summary_get_build_content (CamelFolderSummary *summary)
+{
+	CamelFolderSummaryPrivate *priv;
+
+	g_return_val_if_fail (summary != NULL, FALSE);
+	g_return_val_if_fail (summary->priv != NULL, FALSE);
+
+	priv = summary->priv;
+
+	return priv->build_content;
+}
+
+/**
+ * camel_folder_summary_set_need_preview:
+ *
+ * Since: 2.28
+ **/
+void
+camel_folder_summary_set_need_preview (CamelFolderSummary *summary,
+                                       gboolean preview)
+{
+	CamelFolderSummaryPrivate *priv;
+
+	g_return_if_fail (summary != NULL);
+	g_return_if_fail (summary->priv != NULL);
+
+	priv = summary->priv;
+
+	priv->need_preview = preview;
+}
+
+/**
+ * camel_folder_summary_get_need_preview:
+ *
+ * Since: 2.28
+ **/
+gboolean
+camel_folder_summary_get_need_preview (CamelFolderSummary *summary)
+{
+	CamelFolderSummaryPrivate *priv;
+
+	g_return_val_if_fail (summary != NULL, FALSE);
+	g_return_val_if_fail (summary->priv != NULL, FALSE);
+
+	priv = summary->priv;
+
+	return priv->need_preview;
+}
+
+/**
+ * camel_folder_summary_next_uid:
+ * @summary: a #CamelFolderSummary object
+ *
+ * Generate a new unique uid value as an integer.  This
+ * may be used to create a unique sequence of numbers.
+ *
+ * Returns: the next unique uid value
+ **/
+guint32
+camel_folder_summary_next_uid (CamelFolderSummary *s)
+{
+	guint32 uid;
+
+	camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
+
+	uid = s->priv->nextuid++;
+	camel_folder_summary_touch (s);
+
+	camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
+
+	return uid;
+}
+
+/**
+ * camel_folder_summary_set_next_uid:
+ * @summary: a #CamelFolderSummary object
+ * @uid: The next minimum uid to assign.  To avoid clashing
+ * uid's, set this to the uid of a given messages + 1.
+ *
+ * Set the next minimum uid available.  This can be used to
+ * ensure new uid's do not clash with existing uid's.
+ **/
+void
+camel_folder_summary_set_next_uid (CamelFolderSummary *s,
+				   guint32 uid)
+{
+	camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
+
+	s->priv->nextuid = MAX (s->priv->nextuid, uid);
+	camel_folder_summary_touch (s);
+
+	camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
+}
+
+/**
+ * camel_folder_summary_get_next_uid:
+ * @summary: a #CamelFolderSummary object
+ *
+ * Returns: Next uid currently awaiting for assignment. The difference from
+ *    camel_folder_summary_next_uid() is that this function returns actual
+ *    value and doesn't increment it before returning.
+ *
+ * Since: 3.4
+ **/
+guint32
+camel_folder_summary_get_next_uid (CamelFolderSummary *summary)
+{
+	guint32 res;
+
+	g_return_val_if_fail (summary != NULL, 0);
+	g_return_val_if_fail (summary->priv != NULL, 0);
+
+	camel_folder_summary_lock (summary, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
+
+	res = summary->priv->nextuid;
+
+	camel_folder_summary_unlock (summary, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
+
+	return res;
+}
+
+/**
+ * camel_folder_summary_next_uid_string:
+ * @summary: a #CamelFolderSummary object
+ *
+ * Retrieve the next uid, but as a formatted string.
+ *
+ * Returns: the next uid as an unsigned integer string.
+ * This string must be freed by the caller.
+ **/
+gchar *
+camel_folder_summary_next_uid_string (CamelFolderSummary *summary)
+{
+	CamelFolderSummaryClass *class;
+
+	g_return_val_if_fail (CAMEL_IS_FOLDER_SUMMARY (summary), NULL);
+
+	class = CAMEL_FOLDER_SUMMARY_GET_CLASS (summary);
+	g_return_val_if_fail (class->next_uid_string != NULL, NULL);
+
+	return class->next_uid_string (summary);
+}
+
+/**
+ * camel_folder_summary_set_filename:
+ * @summary: a #CamelFolderSummary object
+ * @filename: a filename
+ *
+ * Set the filename where the summary will be loaded to/saved from.
+ **/
+void
+camel_folder_summary_set_filename (CamelFolderSummary *s,
+                                   const gchar *name)
+{
+	camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
+
+	g_free (s->priv->summary_path);
+	s->priv->summary_path = g_strdup (name);
+
+	camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
+}
+
+/**
+ * camel_folder_summary_count:
+ * @summary: a #CamelFolderSummary object
+ *
+ * Get the number of summary items stored in this summary.
+ *
+ * Returns: the number of items in the summary
+ **/
+guint
+camel_folder_summary_count (CamelFolderSummary *summary)
+{
+	g_return_val_if_fail (summary != NULL, 0);
+	g_return_val_if_fail (summary->priv != NULL, 0);
+
+	return g_hash_table_size (summary->priv->uids);
+}
+
+/**
+ * camel_folder_summary_check_uid
+ * @s: a #CamelFolderSummary object
+ * @uid: a uid
+ *
+ * Check if the uid is valid. This isn't very efficient, so it shouldn't be called iteratively.
+ *
+ *
+ * Returns: if the uid is present in the summary or not  (%TRUE or %FALSE)
+ *
+ * Since: 2.24
+ **/
+gboolean
+camel_folder_summary_check_uid (CamelFolderSummary *s,
+                                const gchar *uid)
+{
+	gboolean ret;
+
+	g_return_val_if_fail (s != NULL, FALSE);
+	g_return_val_if_fail (s->priv != NULL, FALSE);
+	g_return_val_if_fail (uid != NULL, FALSE);
+
+	camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
+
+	ret = g_hash_table_lookup_extended (s->priv->uids, uid, NULL, NULL);
+
+	camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
+
+	return ret;
+}
+
+static void
+folder_summary_dupe_uids_to_array (gpointer key_uid, gpointer value_flags, gpointer user_data)
+{
+	g_ptr_array_add (user_data, (gpointer) camel_pstring_strdup (key_uid));
+}
+
+/**
+ * camel_folder_summary_get_array:
+ * @summary: a #CamelFolderSummary object
+ *
+ * Obtain a copy of the summary array.  This is done atomically,
  * so cannot contain empty entries.
  *
- * It must be freed using camel_folder_summary_free_hashtable
+ * Free with camel_folder_summary_free_array()
  *
- * Returns: a #GHashTable of uids
+ * Returns: a #GPtrArray of uids
  *
- * Since: 2.26
+ * Since: 3.4
  **/
-GHashTable *
-camel_folder_summary_get_hashtable (CamelFolderSummary *s)
+GPtrArray *
+camel_folder_summary_get_array (CamelFolderSummary *s)
 {
-	GHashTable *hash = g_hash_table_new (g_str_hash, g_str_equal);
-	gint i;
+	GPtrArray *res;
+
+	g_return_val_if_fail (s != NULL, NULL);
+	g_return_val_if_fail (s->priv != NULL, NULL);
 
 	camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
 
-	for (i = 0; i < s->uids->len; i++)
-		g_hash_table_insert (hash, (gpointer) camel_pstring_strdup ((gchar *) g_ptr_array_index (s->uids, i)), GINT_TO_POINTER (1));
+	res = g_ptr_array_sized_new (g_hash_table_size (s->priv->uids));
+	g_hash_table_foreach (s->priv->uids, folder_summary_dupe_uids_to_array, res);
 
 	camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
 
-	return hash;
+	return res;
 }
 
 /**
- * camel_folder_summary_free_hashtable:
+ * camel_folder_summary_free_array:
+ * @array: a #GPtrArray returned from camel_folder_summary_get_array()
  *
- * Since: 2.26
+ * Free's array and its elements returned from camel_folder_summary_get_array().
+ *
+ * Since: 3.4
  **/
 void
-camel_folder_summary_free_hashtable (GHashTable *ht)
+camel_folder_summary_free_array	(GPtrArray *array)
 {
-	g_hash_table_foreach (ht, (GHFunc) camel_pstring_free, NULL);
-	g_hash_table_destroy (ht);
+	if (!array)
+		return;
+
+	g_ptr_array_foreach (array, (GFunc) camel_pstring_free, NULL);
+	g_ptr_array_free (array, TRUE);
 }
 
 /**
- * camel_folder_summary_peek_info:
+ * camel_folder_summary_peek_loaded:
  *
  * Since: 2.26
  **/
 CamelMessageInfo *
-camel_folder_summary_peek_info (CamelFolderSummary *s,
-                                const gchar *uid)
+camel_folder_summary_peek_loaded (CamelFolderSummary *s,
+				  const gchar *uid)
 {
-	CamelMessageInfo *info = g_hash_table_lookup (s->loaded_infos, uid);
+	CamelMessageInfo *info;
+
+	g_return_val_if_fail (s != NULL, NULL);
+	g_return_val_if_fail (s->priv != NULL, NULL);
+
+	info = g_hash_table_lookup (s->priv->loaded_infos, uid);
 
 	if (info)
 		camel_message_info_ref (info);
+
 	return info;
 }
 
 struct _db_pass_data {
+	GHashTable *columns_hash;
 	CamelFolderSummary *summary;
 	gboolean add; /* or just insert to hashtable */
 };
@@ -1269,7 +1898,7 @@ message_info_from_uid (CamelFolderSummary *s,
 
 	camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
 
-	info = g_hash_table_lookup (s->loaded_infos, uid);
+	info = g_hash_table_lookup (s->priv->loaded_infos, uid);
 
 	if (!info) {
 		CamelDB *cdb;
@@ -1277,25 +1906,27 @@ message_info_from_uid (CamelFolderSummary *s,
 		const gchar *folder_name;
 		struct _db_pass_data data;
 
-		d(printf ("\ncamel_folder_summary_uid called \n"));
-
-		folder_name = camel_folder_get_full_name (s->folder);
-		parent_store = camel_folder_get_parent_store (s->folder);
+		folder_name = camel_folder_get_full_name (s->priv->folder);
+		parent_store = camel_folder_get_parent_store (s->priv->folder);
 		cdb = parent_store->cdb_r;
 
+		data.columns_hash = NULL;
 		data.summary = s;
 		data.add = FALSE;
 
 		ret = camel_db_read_message_info_record_with_uid (
 			cdb, folder_name, uid, &data,
 			camel_read_mir_callback, NULL);
+		if (data.columns_hash)
+			g_hash_table_destroy (data.columns_hash);
+
 		if (ret != 0) {
 			camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
 			return NULL;
 		}
 
 		/* We would have double reffed at camel_read_mir_callback */
-		info = g_hash_table_lookup (s->loaded_infos, uid);
+		info = g_hash_table_lookup (s->priv->loaded_infos, uid);
 
 		cfs_schedule_info_release_timer (s);
 	}
@@ -1309,7 +1940,7 @@ message_info_from_uid (CamelFolderSummary *s,
 }
 
 /**
- * camel_folder_summary_uid:
+ * camel_folder_summary_get:
  * @summary: a #CamelFolderSummary object
  * @uid: a uid
  *
@@ -1321,8 +1952,8 @@ message_info_from_uid (CamelFolderSummary *s,
  * Returns: the summary item, or %NULL if the uid @uid is not available
  **/
 CamelMessageInfo *
-camel_folder_summary_uid (CamelFolderSummary *summary,
-                          const gchar *uid)
+camel_folder_summary_get (CamelFolderSummary *summary,
+			      const gchar *uid)
 {
 	CamelFolderSummaryClass *class;
 
@@ -1335,74 +1966,6 @@ camel_folder_summary_uid (CamelFolderSummary *summary,
 	return class->message_info_from_uid (summary, uid);
 }
 
-/**
- * camel_folder_summary_next_uid:
- * @summary: a #CamelFolderSummary object
- *
- * Generate a new unique uid value as an integer.  This
- * may be used to create a unique sequence of numbers.
- *
- * Returns: the next unique uid value
- **/
-guint32
-camel_folder_summary_next_uid (CamelFolderSummary *s)
-{
-	guint32 uid;
-
-	camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
-
-	uid = s->nextuid++;
-
-	camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
-
-	/* FIXME: sync this to disk */
-/*	summary_header_save(s);*/
-	return uid;
-}
-
-/**
- * camel_folder_summary_set_uid:
- * @summary: a #CamelFolderSummary object
- * @uid: The next minimum uid to assign.  To avoid clashing
- * uid's, set this to the uid of a given messages + 1.
- *
- * Set the next minimum uid available.  This can be used to
- * ensure new uid's do not clash with existing uid's.
- **/
-void
-camel_folder_summary_set_uid (CamelFolderSummary *s,
-                              guint32 uid)
-{
-	/* TODO: sync to disk? */
-	camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
-
-	s->nextuid = MAX (s->nextuid, uid);
-
-	camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
-}
-
-/**
- * camel_folder_summary_next_uid_string:
- * @summary: a #CamelFolderSummary object
- *
- * Retrieve the next uid, but as a formatted string.
- *
- * Returns: the next uid as an unsigned integer string.
- * This string must be freed by the caller.
- **/
-gchar *
-camel_folder_summary_next_uid_string (CamelFolderSummary *summary)
-{
-	CamelFolderSummaryClass *class;
-
-	g_return_val_if_fail (CAMEL_IS_FOLDER_SUMMARY (summary), NULL);
-
-	class = CAMEL_FOLDER_SUMMARY_GET_CLASS (summary);
-	g_return_val_if_fail (class->next_uid_string != NULL, NULL);
-
-	return class->next_uid_string (summary);
-}
-
 static CamelMessageContentInfo *
 perform_content_info_load_from_db (CamelFolderSummary *s,
                                    CamelMIRecord *mir)
@@ -1492,7 +2055,7 @@ camel_folder_summary_get_changed (CamelFolderSummary *s)
 	 * from DB and merge */
 
 	camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
-	g_hash_table_foreach (s->loaded_infos, (GHFunc) append_changed_uids, res);
+	g_hash_table_foreach (s->priv->loaded_infos, (GHFunc) append_changed_uids, res);
 	camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
 
 	return res;
@@ -1513,23 +2076,22 @@ cfs_count_dirty (CamelFolderSummary *s)
 	gint count = 0;
 
 	camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
-	g_hash_table_foreach (s->loaded_infos, (GHFunc) count_changed_uids, &count);
+	g_hash_table_foreach (s->priv->loaded_infos, (GHFunc) count_changed_uids, &count);
 	camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
 
 	return count;
 }
 
-/* FIXME[disk-summary] I should have a better LRU algorithm  */
 static gboolean
-remove_item (gchar *key,
+remove_item (gchar *uid,
              CamelMessageInfoBase *info,
-             GList **to_free_list)
+             GSList **to_remove_infos)
 {
-	d(printf("%d(%d)\t", info->refcount, info->dirty)); /* camel_message_info_dump (info); */
-	if (info->refcount == 1 && !info->dirty && !(info->flags & CAMEL_MESSAGE_FOLDER_FLAGGED)) {
-		*to_free_list = g_list_prepend (*to_free_list, info);
+	if (info->refcount == 1 && !info->dirty && (info->flags & CAMEL_MESSAGE_FOLDER_FLAGGED) == 0) {
+		*to_remove_infos = g_slist_prepend (*to_remove_infos, info);
 		return TRUE;
 	}
+
 	return FALSE;
 }
 
@@ -1539,32 +2101,25 @@ remove_cache (CamelSession *session,
               CamelFolderSummary *summary,
               GError **error)
 {
-	GList *to_free_list = NULL, *l;
+	GSList *to_remove_infos = NULL;
 
 	CAMEL_DB_RELEASE_SQLITE_MEMORY;
 
-	if (time (NULL) - summary->cache_load_time < SUMMARY_CACHE_DROP)
+	if (time (NULL) - summary->priv->cache_load_time < SUMMARY_CACHE_DROP)
 		return;
 
-	/* FIXME[disk-summary] hack. fix it */
-	camel_folder_summary_lock (
-		summary, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
+	camel_folder_summary_lock (summary, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
 
 	camel_folder_summary_lock (summary, CAMEL_FOLDER_SUMMARY_REF_LOCK);
-	g_hash_table_foreach_remove (
-		summary->loaded_infos, (GHRFunc) remove_item, &to_free_list);
+	g_hash_table_foreach_remove (summary->priv->loaded_infos, (GHRFunc) remove_item, &to_remove_infos);
 	camel_folder_summary_unlock (summary, CAMEL_FOLDER_SUMMARY_REF_LOCK);
 
-	/* Deferred freeing as _free function will try to remove
-	 * entries from the hash_table in foreach_remove otherwise */
-	for (l = to_free_list; l; l = l->next)
-		camel_message_info_free (l->data);
-	g_list_free (to_free_list);
+	g_slist_foreach (to_remove_infos, (GFunc) camel_message_info_free, NULL);
+	g_slist_free (to_remove_infos);
 
-	camel_folder_summary_unlock (
-		summary, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
+	camel_folder_summary_unlock (summary, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
 
-	summary->cache_load_time = time (NULL);
+	summary->priv->cache_load_time = time (NULL);
 }
 
 static gboolean
@@ -1574,16 +2129,16 @@ cfs_try_release_memory (CamelFolderSummary *summary)
 	CamelSession *session;
 
 	/* If folder is freed or if the cache is nil then clean up */
-	if (!summary->folder || !g_hash_table_size (summary->loaded_infos)) {
-		summary->cache_load_time = 0;
-		summary->timeout_handle = 0;
+	if (!summary->priv->folder || !g_hash_table_size (summary->priv->loaded_infos)) {
+		summary->priv->cache_load_time = 0;
+		summary->priv->timeout_handle = 0;
 		return FALSE;
 	}
 
-	parent_store = camel_folder_get_parent_store (summary->folder);
+	parent_store = camel_folder_get_parent_store (summary->priv->folder);
 	session = camel_service_get_session (CAMEL_SERVICE (parent_store));
 
-	if (time (NULL) - summary->cache_load_time < SUMMARY_CACHE_DROP)
+	if (time (NULL) - summary->priv->cache_load_time < SUMMARY_CACHE_DROP)
 		return TRUE;
 
 	camel_session_submit_job (
@@ -1600,7 +2155,7 @@ cfs_schedule_info_release_timer (CamelFolderSummary *s)
 {
 	g_return_if_fail (CAMEL_IS_FOLDER_SUMMARY (s));
 
-	if (!s->timeout_handle) {
+	if (!s->priv->timeout_handle) {
 		static gboolean know_can_do = FALSE, can_do = TRUE;
 
 		if (!know_can_do) {
@@ -1610,21 +2165,21 @@ cfs_schedule_info_release_timer (CamelFolderSummary *s)
 
 		/* FIXME[disk-summary] LRU please and not timeouts */
 		if (can_do)
-			s->timeout_handle = g_timeout_add_seconds (SUMMARY_CACHE_DROP, (GSourceFunc) cfs_try_release_memory, s);
+			s->priv->timeout_handle = g_timeout_add_seconds (SUMMARY_CACHE_DROP, (GSourceFunc) cfs_try_release_memory, s);
 	}
 
 	/* update also cache load time to the actual, to not release something just loaded */
-	s->cache_load_time = time (NULL);
+	s->priv->cache_load_time = time (NULL);
 }
 
 static gint
 cfs_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);
+	if (!CAMEL_IS_VEE_FOLDER (s->priv->folder))
+		return g_hash_table_size (s->priv->loaded_infos);
 	else
-		return s->uids->len;
+		return g_hash_table_size (s->priv->uids);
 }
 
 /* Update preview of cached messages */
@@ -1634,7 +2189,7 @@ msg_update_preview (const gchar *uid,
                     gpointer value,
                     CamelFolder *folder)
 {
-	CamelMessageInfoBase *info = (CamelMessageInfoBase *) camel_folder_summary_uid (folder->summary, uid);
+	CamelMessageInfoBase *info = (CamelMessageInfoBase *) camel_folder_summary_get (folder->summary, uid);
 	CamelMimeMessage *msg;
 	CamelStore *parent_store;
 	const gchar *full_name;
@@ -1660,6 +2215,15 @@ pick_uids (const gchar *uid,
 		g_ptr_array_add (array, (gchar *) camel_pstring_strdup (uid));
 }
 
+static void
+copy_all_uids_to_hash (gpointer uid,
+		       gpointer hash)
+{
+	g_return_if_fail (uid != NULL);
+
+	g_hash_table_insert (hash, (gchar *) camel_pstring_strdup (uid), GINT_TO_POINTER (1));
+}
+
 static gboolean
 fill_mi (const gchar *uid,
          const gchar *msg,
@@ -1667,7 +2231,7 @@ fill_mi (const gchar *uid,
 {
 	CamelMessageInfoBase *info;
 
-	info = g_hash_table_lookup (folder->summary->loaded_infos, uid);
+	info = g_hash_table_lookup (folder->summary->priv->loaded_infos, uid);
 	if (info) /* We re assign the memory of msg */
 		info->preview = (gchar *) msg;
 	camel_pstring_free (uid); /* unref the uid */
@@ -1682,13 +2246,19 @@ preview_update (CamelSession *session,
                 GError **error)
 {
 	/* FIXME: Either lock & use or copy & use.*/
-	GPtrArray *uids_uncached= camel_folder_get_uncached_uids (folder, folder->summary->uids, NULL);
-	GHashTable *hash = camel_folder_summary_get_hashtable (folder->summary);
-	GHashTable *preview_data;
+	GPtrArray *uids_uncached, *uids_array;
+	GHashTable *preview_data, *uids_hash;
 	CamelStore *parent_store;
 	const gchar *full_name;
 	gint i;
 
+	uids_array = camel_folder_summary_get_array (folder->summary);
+	uids_hash = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) camel_pstring_free, NULL);
+	g_ptr_array_foreach (uids_array, copy_all_uids_to_hash, uids_hash);
+	uids_uncached = camel_folder_get_uncached_uids (folder, uids_array, NULL);
+	camel_folder_summary_free_array (uids_array);
+	uids_array = NULL;
+
 	full_name = camel_folder_get_full_name (folder);
 	parent_store = camel_folder_get_parent_store (folder);
 	preview_data = camel_db_get_folder_preview (parent_store->cdb_r, full_name, NULL);
@@ -1698,21 +2268,20 @@ preview_update (CamelSession *session,
 	}
 
 	camel_folder_summary_lock (folder->summary, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
-	g_hash_table_foreach (folder->summary->loaded_infos, (GHFunc) pick_uids, uids_uncached);
+	g_hash_table_foreach (folder->summary->priv->loaded_infos, (GHFunc) pick_uids, uids_uncached);
 	camel_folder_summary_unlock (folder->summary, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
 
 	for (i = 0; i < uids_uncached->len; i++) {
-		g_hash_table_remove (hash, uids_uncached->pdata[i]);
-		camel_pstring_free (uids_uncached->pdata[i]); /* unref the hash table key */
+		g_hash_table_remove (uids_hash, uids_uncached->pdata[i]);
 	}
 
 	camel_folder_lock (folder, CAMEL_FOLDER_REC_LOCK);
 	camel_db_begin_transaction (parent_store->cdb_w, NULL);
-	g_hash_table_foreach (hash, (GHFunc) msg_update_preview, folder);
+	g_hash_table_foreach (uids_hash, (GHFunc) msg_update_preview, folder);
 	camel_db_end_transaction (parent_store->cdb_w, NULL);
 	camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
 	camel_folder_free_uids (folder, uids_uncached);
-	camel_folder_summary_free_hashtable (hash);
+	g_hash_table_destroy (uids_hash);
 }
 
 /* end */
@@ -1732,25 +2301,29 @@ cfs_reload_from_db (CamelFolderSummary *s,
 	 * load better. */
 	d(printf ("\ncamel_folder_summary_reload_from_db called \n"));
 
-	folder_name = camel_folder_get_full_name (s->folder);
-	parent_store = camel_folder_get_parent_store (s->folder);
+	folder_name = camel_folder_get_full_name (s->priv->folder);
+	parent_store = camel_folder_get_parent_store (s->priv->folder);
 	session = camel_service_get_session (CAMEL_SERVICE (parent_store));
 	cdb = parent_store->cdb_r;
 
-	/* FIXME FOR SANKAR: No need to pass the address of summary here. */
+	data.columns_hash = NULL;
 	data.summary = s;
 	data.add = FALSE;
+
 	ret = camel_db_read_message_info_records (
 		cdb, folder_name, (gpointer) &data,
 		camel_read_mir_callback, NULL);
 
+	if (data.columns_hash)
+		g_hash_table_destroy (data.columns_hash);
+
 	cfs_schedule_info_release_timer (s);
 
 	if (s->priv->need_preview)
 		camel_session_submit_job (
 			session,
 			(CamelSessionCallback) preview_update,
-			g_object_ref (s->folder),
+			g_object_ref (s->priv->folder),
 			(GDestroyNotify) g_object_unref);
 
 	return ret == 0 ? 0 : -1;
@@ -1800,7 +2373,7 @@ camel_folder_summary_prepare_fetch_all (CamelFolderSummary *s,
 	}
 
 	/* update also cache load time, even when not loaded anything */
-	s->cache_load_time = time (NULL);
+	s->priv->cache_load_time = time (NULL);
 }
 
 /**
@@ -1808,7 +2381,7 @@ camel_folder_summary_prepare_fetch_all (CamelFolderSummary *s,
  *
  * Since: 2.24
  **/
-gint
+gboolean
 camel_folder_summary_load_from_db (CamelFolderSummary *s,
                                    GError **error)
 {
@@ -1818,23 +2391,24 @@ camel_folder_summary_load_from_db (CamelFolderSummary *s,
 	gint ret = 0;
 	GError *local_error = NULL;
 
+	g_return_val_if_fail (s != NULL, FALSE);
+	g_return_val_if_fail (s->priv != NULL, FALSE);
+
 	camel_folder_summary_save_to_db (s, NULL);
 
 	/* struct _db_pass_data data; */
 	d(printf ("\ncamel_folder_summary_load_from_db called \n"));
 
-	full_name = camel_folder_get_full_name (s->folder);
-	parent_store = camel_folder_get_parent_store (s->folder);
-	ret = camel_folder_summary_header_load_from_db (s, parent_store, full_name, error);
-
-	if (ret)
-		return ret;
+	full_name = camel_folder_get_full_name (s->priv->folder);
+	parent_store = camel_folder_get_parent_store (s->priv->folder);
+	if (!camel_folder_summary_header_load_from_db (s, parent_store, full_name, error))
+		return FALSE;
 
 	cdb = parent_store->cdb_r;
 
 	ret = camel_db_get_folder_uids (
 		cdb, full_name, s->sort_by, s->collate,
-		s->uids, &local_error);
+		s->priv->uids, &local_error);
 
 	if (local_error != NULL && local_error->message != NULL &&
 		strstr (local_error->message, "no such table") != NULL) {
@@ -1843,12 +2417,13 @@ camel_folder_summary_load_from_db (CamelFolderSummary *s,
 	} else if (local_error != NULL)
 		g_propagate_error (error, local_error);
 
-	return ret == 0 ? 0 : -1;
+	return ret == 0;
 }
 
 static void
 mir_from_cols (CamelMIRecord *mir,
                CamelFolderSummary *s,
+	       GHashTable **columns_hash,
                gint ncol,
                gchar **cols,
                gchar **name)
@@ -1859,58 +2434,87 @@ mir_from_cols (CamelMIRecord *mir,
 		if (!name[i] || !cols[i])
 			continue;
 
-		if (!strcmp (name [i], "uid"))
-			mir->uid = (gchar *) 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"))
-			mir->read =  (cols[i]) ? ( ((strtoul (cols[i], NULL, 10)) ? TRUE : FALSE)) : FALSE;
-		else if (!strcmp (name [i], "deleted"))
-			mir->deleted = (cols[i]) ? ( ((strtoul (cols[i], NULL, 10)) ? TRUE : FALSE)) : FALSE;
-		else if (!strcmp (name [i], "replied"))
-			mir->replied = (cols[i]) ? ( ((strtoul (cols[i], NULL, 10)) ? TRUE : FALSE)) : FALSE;
-		else if (!strcmp (name [i], "important"))
-			mir->important = (cols[i]) ? ( ((strtoul (cols[i], NULL, 10)) ? TRUE : FALSE)) : FALSE;
-		else if (!strcmp (name [i], "junk"))
-			mir->junk = (cols[i]) ? ( ((strtoul (cols[i], NULL, 10)) ? TRUE : FALSE)) : FALSE;
-		else if (!strcmp (name [i], "attachment"))
-			mir->attachment = (cols[i]) ? ( ((strtoul (cols[i], NULL, 10)) ? TRUE : FALSE)) : FALSE;
-		else if (!strcmp (name [i], "size"))
-			mir->size =  cols[i] ? strtoul (cols[i], NULL, 10) : 0;
-		else if (!strcmp (name [i], "dsent"))
-			mir->dsent = cols[i] ? strtol (cols[i], NULL, 10) : 0;
-		else if (!strcmp (name [i], "dreceived"))
-			mir->dreceived = cols[i] ? strtol (cols[i], NULL, 10) : 0;
-		else if (!strcmp (name [i], "subject"))
-			mir->subject = (gchar *) camel_pstring_strdup (cols[i]);
-		else if (!strcmp (name [i], "mail_from"))
-			mir->from = (gchar *) camel_pstring_strdup (cols[i]);
-		else if (!strcmp (name [i], "mail_to"))
-			mir->to = (gchar *) camel_pstring_strdup (cols[i]);
-		else if (!strcmp (name [i], "mail_cc"))
-			mir->cc = (gchar *) camel_pstring_strdup (cols[i]);
-		else if (!strcmp (name [i], "mlist"))
-			mir->mlist = (gchar *) camel_pstring_strdup (cols[i]);
-		else if (!strcmp (name [i], "followup_flag"))
-			mir->followup_flag = (gchar *) camel_pstring_strdup (cols[i]);
-		else if (!strcmp (name [i], "followup_completed_on"))
-			mir->followup_completed_on = (gchar *) camel_pstring_strdup (cols[i]);
-		else if (!strcmp (name [i], "followup_due_by"))
-			mir->followup_due_by = (gchar *) camel_pstring_strdup (cols[i]);
-		else if (!strcmp (name [i], "part"))
-			mir->part = g_strdup (cols[i]);
-		else if (!strcmp (name [i], "labels"))
-			mir->labels = g_strdup (cols[i]);
-		else if (!strcmp (name [i], "usertags"))
-			mir->usertags = g_strdup (cols[i]);
-		else if (!strcmp (name [i], "cinfo"))
-			mir->cinfo = g_strdup (cols[i]);
-		else if (!strcmp (name [i], "bdata"))
-			mir->bdata = g_strdup (cols[i]);
-		/* Evolution itself doesn't yet use this, ignoring
-		else if (!strcmp (name [i], "bodystructure"))
-			mir->bodystructure = g_strdup (cols[i]); */
-
+		switch (camel_db_get_column_ident (columns_hash, i, ncol, name)) {
+			case CAMEL_DB_COLUMN_UID:
+				mir->uid = (gchar *) camel_pstring_strdup (cols[i]);
+				break;
+			case CAMEL_DB_COLUMN_FLAGS:
+				mir->flags = cols[i] ? strtoul (cols[i], NULL, 10) : 0;
+				break;
+			case CAMEL_DB_COLUMN_READ:
+				mir->read =  (cols[i]) ? ( ((strtoul (cols[i], NULL, 10)) ? TRUE : FALSE)) : FALSE;
+				break;
+			case CAMEL_DB_COLUMN_DELETED:
+				mir->deleted = (cols[i]) ? ( ((strtoul (cols[i], NULL, 10)) ? TRUE : FALSE)) : FALSE;
+				break;
+			case CAMEL_DB_COLUMN_REPLIED:
+				mir->replied = (cols[i]) ? ( ((strtoul (cols[i], NULL, 10)) ? TRUE : FALSE)) : FALSE;
+				break;
+			case CAMEL_DB_COLUMN_IMPORTANT:
+				mir->important = (cols[i]) ? ( ((strtoul (cols[i], NULL, 10)) ? TRUE : FALSE)) : FALSE;
+				break;
+			case CAMEL_DB_COLUMN_JUNK:
+				mir->junk = (cols[i]) ? ( ((strtoul (cols[i], NULL, 10)) ? TRUE : FALSE)) : FALSE;
+				break;
+			case CAMEL_DB_COLUMN_ATTACHMENT:
+				mir->attachment = (cols[i]) ? ( ((strtoul (cols[i], NULL, 10)) ? TRUE : FALSE)) : FALSE;
+				break;
+			case CAMEL_DB_COLUMN_SIZE:
+				mir->size =  cols[i] ? strtoul (cols[i], NULL, 10) : 0;
+				break;
+			case CAMEL_DB_COLUMN_DSENT:
+				mir->dsent = cols[i] ? strtol (cols[i], NULL, 10) : 0;
+				break;
+			case CAMEL_DB_COLUMN_DRECEIVED:
+				mir->dreceived = cols[i] ? strtol (cols[i], NULL, 10) : 0;
+				break;
+			case CAMEL_DB_COLUMN_SUBJECT:
+				mir->subject = (gchar *) camel_pstring_strdup (cols[i]);
+				break;
+			case CAMEL_DB_COLUMN_MAIL_FROM:
+				mir->from = (gchar *) camel_pstring_strdup (cols[i]);
+				break;
+			case CAMEL_DB_COLUMN_MAIL_TO:
+				mir->to = (gchar *) camel_pstring_strdup (cols[i]);
+				break;
+			case CAMEL_DB_COLUMN_MAIL_CC:
+				mir->cc = (gchar *) camel_pstring_strdup (cols[i]);
+				break;
+			case CAMEL_DB_COLUMN_MLIST:
+				mir->mlist = (gchar *) camel_pstring_strdup (cols[i]);
+				break;
+			case CAMEL_DB_COLUMN_FOLLOWUP_FLAG:
+				mir->followup_flag = (gchar *) camel_pstring_strdup (cols[i]);
+				break;
+			case CAMEL_DB_COLUMN_FOLLOWUP_COMPLETED_ON:
+				mir->followup_completed_on = (gchar *) camel_pstring_strdup (cols[i]);
+				break;
+			case CAMEL_DB_COLUMN_FOLLOWUP_DUE_BY:
+				mir->followup_due_by = (gchar *) camel_pstring_strdup (cols[i]);
+				break;
+			case CAMEL_DB_COLUMN_PART:
+				mir->part = g_strdup (cols[i]);
+				break;
+			case CAMEL_DB_COLUMN_LABELS:
+				mir->labels = g_strdup (cols[i]);
+				break;
+			case CAMEL_DB_COLUMN_USERTAGS:
+				mir->usertags = g_strdup (cols[i]);
+				break;
+			case CAMEL_DB_COLUMN_CINFO:
+				mir->cinfo = g_strdup (cols[i]);
+				break;
+			case CAMEL_DB_COLUMN_BDATA:
+				mir->bdata = g_strdup (cols[i]);
+				break;
+			case CAMEL_DB_COLUMN_BODYSTRUCTURE:
+				/* Evolution itself doesn't yet use this, ignoring */
+				/* mir->bodystructure = g_strdup (cols[i]); */
+				break;
+			default:
+				g_warn_if_reached ();
+				break;
+		}
 	}
 }
 
@@ -1927,10 +2531,10 @@ camel_read_mir_callback (gpointer ref,
 	gint ret = 0;
 
 	mir = g_new0 (CamelMIRecord , 1);
-	mir_from_cols (mir, s, ncol, cols, name);
+	mir_from_cols (mir, s, &data->columns_hash, ncol, cols, name);
 
 	camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
-	if (!mir->uid || g_hash_table_lookup (s->loaded_infos, mir->uid)) {
+	if (!mir->uid || g_hash_table_lookup (s->priv->loaded_infos, mir->uid)) {
 		/* Unlock and better return */
 		camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
 		camel_db_camel_mir_free (mir);
@@ -1942,7 +2546,7 @@ camel_read_mir_callback (gpointer ref,
 
 	if (info) {
 
-		if (s->build_content) {
+		if (s->priv->build_content) {
 			gchar *tmp;
 			tmp = mir->cinfo;
 			/* FIXME: this should be done differently, how i don't know */
@@ -1993,22 +2597,22 @@ camel_folder_summary_migrate_infos (CamelFolderSummary *s)
 	CamelDB *cdb;
 	CamelFIRecord *record;
 
-	parent_store = camel_folder_get_parent_store (s->folder);
+	parent_store = camel_folder_get_parent_store (s->priv->folder);
 	cdb = parent_store->cdb_w;
 
 	/* Kick off the gc thread cycle. */
-	if (s->timeout_handle)
-		g_source_remove (s->timeout_handle);
-	s->timeout_handle = 0;
+	if (s->priv->timeout_handle)
+		g_source_remove (s->priv->timeout_handle);
+	s->priv->timeout_handle = 0;
 
 	d(g_print ("\ncamel_folder_summary_load from FLAT FILE called \n"));
 
-	if (s->summary_path == NULL) {
+	if (s->priv->summary_path == NULL) {
 		g_warning ("No summary path set. Unable to migrate\n");
 		return -1;
 	}
 
-	in = g_fopen(s->summary_path, "rb");
+	in = g_fopen (s->priv->summary_path, "rb");
 	if (in == NULL)
 		return -1;
 
@@ -2016,7 +2620,7 @@ camel_folder_summary_migrate_infos (CamelFolderSummary *s)
 		goto error;
 
 	/* now read in each message ... */
-	for (i = 0; i < s->saved_count; i++) {
+	for (i = 0; i < s->priv->saved_count; i++) {
 		CamelTag *tag;
 
 		mi = CAMEL_FOLDER_SUMMARY_GET_CLASS (s)->message_info_migrate (s, in);
@@ -2025,7 +2629,7 @@ camel_folder_summary_migrate_infos (CamelFolderSummary *s)
 			goto error;
 
 		/* FIXME: this should be done differently, how i don't know */
-		if (s->build_content) {
+		if (s->priv->build_content) {
 			((CamelMessageInfoBase *) mi)->content = perform_content_info_migrate (s, in);
 			if (((CamelMessageInfoBase *) mi)->content == NULL) {
 				camel_message_info_free (mi);
@@ -2043,7 +2647,7 @@ camel_folder_summary_migrate_infos (CamelFolderSummary *s)
 		}
 
 		mi->dirty = TRUE;
-		g_hash_table_insert (s->loaded_infos, (gpointer) mi->uid, mi);
+		g_hash_table_insert (s->priv->loaded_infos, (gpointer) mi->uid, mi);
 	}
 
 	if (fclose (in) != 0)
@@ -2079,7 +2683,7 @@ camel_folder_summary_migrate_infos (CamelFolderSummary *s)
 
 error:
 	if (errno != EINVAL)
-		g_warning ("Cannot load summary file: '%s': %s", s->summary_path, g_strerror (errno));
+		g_warning ("Cannot load summary file: '%s': %s", s->priv->summary_path, g_strerror (errno));
 
 	fclose (in);
 
@@ -2088,7 +2692,7 @@ error:
 }
 
 /* saves the content descriptions, recursively */
-static gint
+static gboolean
 perform_content_info_save_to_db (CamelFolderSummary *s,
                                  CamelMessageContentInfo *ci,
                                  CamelMIRecord *record)
@@ -2096,8 +2700,8 @@ perform_content_info_save_to_db (CamelFolderSummary *s,
 	CamelMessageContentInfo *part;
 	gchar *oldr;
 
-	if (CAMEL_FOLDER_SUMMARY_GET_CLASS (s)->content_info_to_db (s, ci, record) == -1)
-		return -1;
+	if (!CAMEL_FOLDER_SUMMARY_GET_CLASS (s)->content_info_to_db (s, ci, record))
+		return FALSE;
 
 	oldr = record->cinfo;
 	record->cinfo = g_strdup_printf ("%s %d", oldr, my_list_size ((struct _node **)&ci->childs));
@@ -2106,11 +2710,11 @@ perform_content_info_save_to_db (CamelFolderSummary *s,
 	part = ci->childs;
 	while (part) {
 		if (perform_content_info_save_to_db (s, part, record) == -1)
-			return -1;
+			return FALSE;
 		part = part->next;
 	}
 
-	return 0;
+	return TRUE;
 }
 
 typedef struct {
@@ -2133,8 +2737,8 @@ save_to_db_cb (gpointer key,
 	CamelDB *cdb;
 	CamelMIRecord *mir;
 
-	full_name = camel_folder_get_full_name (s->folder);
-	parent_store = camel_folder_get_parent_store (s->folder);
+	full_name = camel_folder_get_full_name (s->priv->folder);
+	parent_store = camel_folder_get_parent_store (s->priv->folder);
 	cdb = parent_store->cdb_w;
 
 	if (!args->migration && !mi->dirty)
@@ -2142,8 +2746,8 @@ save_to_db_cb (gpointer key,
 
 	mir = CAMEL_FOLDER_SUMMARY_GET_CLASS (s)->message_info_to_db (s, (CamelMessageInfo *) mi);
 
-	if (mir && s->build_content) {
-		if (perform_content_info_save_to_db (s, ((CamelMessageInfoBase *) mi)->content, mir) == -1) {
+	if (mir && s->priv->build_content) {
+		if (!perform_content_info_save_to_db (s, ((CamelMessageInfoBase *) mi)->content, mir)) {
 			g_warning ("unable to save mir+cinfo for uid: %s\n", mir->uid);
 			camel_db_camel_mir_free (mir);
 			/* FIXME: Add exception here */
@@ -2152,24 +2756,24 @@ save_to_db_cb (gpointer key,
 	}
 
 	if (!args->migration) {
-			if (camel_db_write_message_info_record (cdb, full_name, mir, error) != 0) {
-					camel_db_camel_mir_free (mir);
-					return;
-			}
+		if (camel_db_write_message_info_record (cdb, full_name, mir, error) != 0) {
+				camel_db_camel_mir_free (mir);
+				return;
+		}
 	} else {
-			if (camel_db_write_fresh_message_info_record (cdb, CAMEL_DB_IN_MEMORY_TABLE, mir, error) != 0) {
-					camel_db_camel_mir_free (mir);
-					return;
-			}
+		if (camel_db_write_fresh_message_info_record (cdb, CAMEL_DB_IN_MEMORY_TABLE, mir, error) != 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, full_name, error);
-				camel_db_start_in_memory_transactions (cdb, error);
-				args->progress = 0;
-			} else {
-				args->progress++;
-			}
+		if (args->progress > CAMEL_DB_IN_MEMORY_TABLE_LIMIT) {
+		    g_print ("BULK INsert limit reached \n");
+			camel_db_flush_in_memory_transactions (cdb, full_name, error);
+			camel_db_start_in_memory_transactions (cdb, error);
+			args->progress = 0;
+		} else {
+			args->progress++;
+		}
 	}
 
 	/* Reset the dirty flag which decides if the changes are synced to the DB or not.
@@ -2194,8 +2798,8 @@ save_message_infos_to_db (CamelFolderSummary *s,
 	args.migration = fresh_mirs;
 	args.progress = 0;
 
-	full_name = camel_folder_get_full_name (s->folder);
-	parent_store = camel_folder_get_parent_store (s->folder);
+	full_name = camel_folder_get_full_name (s->priv->folder);
+	parent_store = camel_folder_get_parent_store (s->priv->folder);
 	cdb = parent_store->cdb_w;
 
 	if (camel_db_prepare_message_info_table (cdb, full_name, error) != 0)
@@ -2205,12 +2809,11 @@ save_message_infos_to_db (CamelFolderSummary *s,
 
 	/* Push MessageInfo-es */
 	camel_db_begin_transaction (cdb, NULL);
-	g_hash_table_foreach (s->loaded_infos, save_to_db_cb, &args);
+	g_hash_table_foreach (s->priv->loaded_infos, save_to_db_cb, &args);
 	camel_db_end_transaction (cdb, NULL);
 
 	camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_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? */
+	cfs_schedule_info_release_timer (s);
 
 	return 0;
 }
@@ -2235,7 +2838,7 @@ msg_save_preview (const gchar *uid,
  *
  * Since: 2.24
  **/
-gint
+gboolean
 camel_folder_summary_save_to_db (CamelFolderSummary *s,
                                  GError **error)
 {
@@ -2245,9 +2848,9 @@ camel_folder_summary_save_to_db (CamelFolderSummary *s,
 	gint ret, count;
 
 	if (!(s->flags & CAMEL_SUMMARY_DIRTY))
-		return 0;
+		return TRUE;
 
-	parent_store = camel_folder_get_parent_store (s->folder);
+	parent_store = camel_folder_get_parent_store (s->priv->folder);
 	cdb = parent_store->cdb_w;
 
 	d(printf ("\ncamel_folder_summary_save_to_db called \n"));
@@ -2255,7 +2858,7 @@ camel_folder_summary_save_to_db (CamelFolderSummary *s,
 		camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
 
 		camel_db_begin_transaction (parent_store->cdb_w, NULL);
-		g_hash_table_foreach (s->priv->preview_updates, (GHFunc) msg_save_preview, s->folder);
+		g_hash_table_foreach (s->priv->preview_updates, (GHFunc) msg_save_preview, s->priv->folder);
 		g_hash_table_remove_all (s->priv->preview_updates);
 		camel_db_end_transaction (parent_store->cdb_w, NULL);
 
@@ -2272,7 +2875,7 @@ camel_folder_summary_save_to_db (CamelFolderSummary *s,
 	if (ret != 0) {
 		/* Failed, so lets reset the flag */
 		s->flags |= CAMEL_SUMMARY_DIRTY;
-		return -1;
+		return FALSE;
 	}
 
 	/* XXX So... if an error is set, how do we even reach this point
@@ -2281,7 +2884,7 @@ camel_folder_summary_save_to_db (CamelFolderSummary *s,
 		strstr ((*error)->message, "26 columns but 28 values") != NULL) {
 		const gchar *full_name;
 
-		full_name = camel_folder_get_full_name (s->folder);
+		full_name = camel_folder_get_full_name (s->priv->folder);
 		g_warning ("Fixing up a broken summary migration on %s\n", full_name);
 
 		/* Begin everything again. */
@@ -2292,14 +2895,14 @@ camel_folder_summary_save_to_db (CamelFolderSummary *s,
 		ret = save_message_infos_to_db (s, FALSE, error);
 		if (ret != 0) {
 			s->flags |= CAMEL_SUMMARY_DIRTY;
-			return -1;
+			return FALSE;
 		}
 	}
 
 	record = CAMEL_FOLDER_SUMMARY_GET_CLASS (s)->summary_header_to_db (s, error);
 	if (!record) {
 		s->flags |= CAMEL_SUMMARY_DIRTY;
-		return -1;
+		return FALSE;
 	}
 
 	camel_db_begin_transaction (cdb, NULL);
@@ -2311,12 +2914,12 @@ camel_folder_summary_save_to_db (CamelFolderSummary *s,
 	if (ret != 0) {
 		camel_db_abort_transaction (cdb, NULL);
 		s->flags |= CAMEL_SUMMARY_DIRTY;
-		return -1;
+		return FALSE;
 	}
 
 	camel_db_end_transaction (cdb, NULL);
 
-	return ret;
+	return ret == 0;
 }
 
 /**
@@ -2324,7 +2927,7 @@ camel_folder_summary_save_to_db (CamelFolderSummary *s,
  *
  * Since: 2.24
  **/
-gint
+gboolean
 camel_folder_summary_header_save_to_db (CamelFolderSummary *s,
                                         GError **error)
 {
@@ -2333,14 +2936,14 @@ camel_folder_summary_header_save_to_db (CamelFolderSummary *s,
 	CamelDB *cdb;
 	gint ret;
 
-	parent_store = camel_folder_get_parent_store (s->folder);
+	parent_store = camel_folder_get_parent_store (s->priv->folder);
 	cdb = parent_store->cdb_w;
 
 	d(printf ("\ncamel_folder_summary_header_save_to_db called \n"));
 
 	record = CAMEL_FOLDER_SUMMARY_GET_CLASS (s)->summary_header_to_db (s, error);
 	if (!record) {
-		return -1;
+		return FALSE;
 	}
 
 	camel_db_begin_transaction (cdb, NULL);
@@ -2351,12 +2954,12 @@ camel_folder_summary_header_save_to_db (CamelFolderSummary *s,
 
 	if (ret != 0) {
 		camel_db_abort_transaction (cdb, NULL);
-		return -1;
+		return FALSE;
 	}
 
 	camel_db_end_transaction (cdb, NULL);
 
-	return ret;
+	return ret == 0;
 }
 
 /**
@@ -2364,7 +2967,7 @@ camel_folder_summary_header_save_to_db (CamelFolderSummary *s,
  *
  * Since: 2.24
  **/
-gint
+gboolean
 camel_folder_summary_header_load_from_db (CamelFolderSummary *s,
                                           CamelStore *store,
                                           const gchar *folder_name,
@@ -2372,22 +2975,21 @@ camel_folder_summary_header_load_from_db (CamelFolderSummary *s,
 {
 	CamelDB *cdb;
 	CamelFIRecord *record;
-	gint ret = 0;
+	gboolean ret = FALSE;
 
-	d(printf ("\ncamel_folder_summary_load_from_db called \n"));
+	d(printf ("\ncamel_folder_summary_header_load_from_db called \n"));
 
 	camel_folder_summary_save_to_db (s, NULL);
 
 	cdb = store->cdb_r;
 
 	record = g_new0 (CamelFIRecord, 1);
-	camel_db_read_folder_info_record (cdb, folder_name, &record, error);
+	camel_db_read_folder_info_record (cdb, folder_name, record, error);
 
 	if (record) {
-		if (CAMEL_FOLDER_SUMMARY_GET_CLASS (s)->summary_header_from_db (s, record) == -1)
-			ret = -1;
+		ret = CAMEL_FOLDER_SUMMARY_GET_CLASS (s)->summary_header_from_db (s, record);
 	} else {
-		ret = -1;
+		ret = FALSE;
 	}
 
 	g_free (record->folder_name);
@@ -2397,7 +2999,7 @@ camel_folder_summary_header_load_from_db (CamelFolderSummary *s,
 	return ret;
 }
 
-static gint
+static gboolean
 summary_assign_uid (CamelFolderSummary *s,
                     CamelMessageInfo *info)
 {
@@ -2413,11 +3015,11 @@ summary_assign_uid (CamelFolderSummary *s,
 
 	camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
 
-	while ((mi = g_hash_table_lookup (s->loaded_infos, uid))) {
+	while ((mi = g_hash_table_lookup (s->priv->loaded_infos, uid))) {
 		camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
 
 		if (mi == info)
-			return 0;
+			return FALSE;
 
 		d(printf ("Trying to insert message with clashing uid (%s).  new uid re-assigned", camel_message_info_uid (info)));
 
@@ -2430,7 +3032,7 @@ summary_assign_uid (CamelFolderSummary *s,
 
 	camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
 
-	return 1;
+	return TRUE;
 }
 
 /**
@@ -2450,21 +3052,32 @@ void
 camel_folder_summary_add (CamelFolderSummary *s,
                           CamelMessageInfo *info)
 {
+	CamelMessageInfoBase *base_info;
+
+	g_return_if_fail (s != NULL);
+	g_return_if_fail (s->priv != NULL);
+
 	if (info == NULL)
 		return;
 
-	if (summary_assign_uid (s, info) == 0)
+	camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
+	if (!summary_assign_uid (s, info)) {
+		camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
 		return;
+	}
 
-	camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
+	base_info = (CamelMessageInfoBase *) info;
+	folder_summary_update_counts_by_flags (s, camel_message_info_flags (info), FALSE);
+	base_info->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED;
+	base_info->dirty = TRUE;
+
+	g_hash_table_insert (s->priv->uids,
+		(gpointer) camel_pstring_strdup (camel_message_info_uid (info)),
+		GUINT_TO_POINTER (camel_message_info_flags (info)));
 
 	/* Summary always holds a ref for the loaded infos */
-	/* camel_message_info_ref(info); FIXME: Check how things are loaded. */
-	/* FIXME[disk-summary] SHould we ref it or redesign it later on */
-	/* The uid array should have its own memory. We will unload the infos when not reqd.*/
-	g_ptr_array_add (s->uids, (gpointer) camel_pstring_strdup ((camel_message_info_uid (info))));
+	g_hash_table_insert (s->priv->loaded_infos, (gpointer) camel_message_info_uid (info), info);
 
-	g_hash_table_insert (s->loaded_infos, (gpointer) camel_message_info_uid (info), info);
 	s->flags |= CAMEL_SUMMARY_DIRTY;
 
 	camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
@@ -2480,92 +3093,32 @@ camel_folder_summary_insert (CamelFolderSummary *s,
                              CamelMessageInfo *info,
                              gboolean load)
 {
+	g_return_if_fail (s != NULL);
+	g_return_if_fail (s->priv != NULL);
+
 	if (info == NULL)
 		return;
 
 	camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
 
-	/* Summary always holds a ref for the loaded infos */
-	/* camel_message_info_ref(info); FIXME: Check how things are loaded. */
-	/* FIXME[disk-summary] SHould we ref it or redesign it later on */
-	/* The uid array should have its own memory. We will unload the infos when not reqd.*/
-	if (!load)
-		g_ptr_array_add (s->uids, (gchar *) camel_pstring_strdup (camel_message_info_uid (info)));
-
-	g_hash_table_insert (s->loaded_infos, (gchar *) camel_message_info_uid (info), info);
-
-	if (!load)
-		s->flags |= CAMEL_SUMMARY_DIRTY;
-
-	camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
-}
-
-/**
- * camel_folder_summary_update_counts_by_flags:
- *
- * Since: 3.0
- **/
-void
-camel_folder_summary_update_counts_by_flags (CamelFolderSummary *summary,
-                                             guint32 flags,
-                                             gboolean subtract)
-{
-	gint unread = 0, deleted = 0, junk = 0;
-	gboolean is_junk_folder = FALSE, is_trash_folder = FALSE;
+	if (!load) {
+		CamelMessageInfoBase *base_info = (CamelMessageInfoBase *) info;
 
-	g_return_if_fail (summary != NULL);
+		folder_summary_update_counts_by_flags (s, camel_message_info_flags (info), FALSE);
+		base_info->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED;
+		base_info->dirty = TRUE;
 
-	if (summary->folder && CAMEL_IS_VTRASH_FOLDER (summary->folder)) {
-		CamelVTrashFolder *vtrash = CAMEL_VTRASH_FOLDER (summary->folder);
+		g_hash_table_insert (s->priv->uids,
+			(gpointer) camel_pstring_strdup (camel_message_info_uid (info)),
+			GUINT_TO_POINTER (camel_message_info_flags (info)));
 
-		is_junk_folder = vtrash && vtrash->type == CAMEL_VTRASH_FOLDER_JUNK;
-		is_trash_folder = vtrash && vtrash->type == CAMEL_VTRASH_FOLDER_TRASH;
+		s->flags |= CAMEL_SUMMARY_DIRTY;
 	}
 
-	if (!(flags & CAMEL_MESSAGE_SEEN))
-		unread = subtract ? -1 : 1;
-
-	if (flags & CAMEL_MESSAGE_DELETED)
-		deleted = subtract ? -1 : 1;
-
-	if (flags & CAMEL_MESSAGE_JUNK)
-		junk = subtract ? -1 : 1;
-
-	dd(printf("%p: %d %d %d | %d %d %d \n", (gpointer) summary, unread, deleted, junk, summary->unread_count, summary->visible_count, summary->saved_count));
-
-	if (deleted)
-		summary->deleted_count += deleted;
-	if (junk)
-		summary->junk_count += junk;
-	if (junk && !deleted)
-		summary->junk_not_deleted_count += junk;
-	if (!junk && !deleted)
-		summary->visible_count += subtract ? -1 : 1;
-
-	if (junk && !is_junk_folder)
-		unread = 0;
-	if (deleted && !is_trash_folder)
-		unread = 0;
-
-	if (unread)
-		summary->unread_count += unread;
-
-	summary->saved_count += subtract ? -1 : 1;
-	camel_folder_summary_touch (summary);
-
-	dd(printf("%p: %d %d %d | %d %d %d\n", (gpointer) summary, unread, deleted, junk, summary->unread_count, summary->visible_count, summary->saved_count));
-}
-
-static void
-update_summary (CamelFolderSummary *summary,
-                CamelMessageInfoBase *info)
-{
-	g_return_if_fail (summary != NULL);
-	g_return_if_fail (info != NULL);
+	/* Summary always holds a ref for the loaded infos */
+	g_hash_table_insert (s->priv->loaded_infos, (gchar *) camel_message_info_uid (info), info);
 
-	camel_folder_summary_update_counts_by_flags (summary, info->flags, FALSE);
-	info->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED;
-	info->dirty = TRUE;
+	camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
 }
 
 /**
@@ -2592,7 +3145,6 @@ camel_folder_summary_add_from_header (CamelFolderSummary *summary,
 	info = camel_folder_summary_info_new_from_header (summary, h);
 
 	camel_folder_summary_add (summary, info);
-	update_summary (summary, (CamelMessageInfoBase *) info);
 
 	return info;
 }
@@ -2622,7 +3174,7 @@ camel_folder_summary_add_from_parser (CamelFolderSummary *s,
 	info = camel_folder_summary_info_new_from_parser (s, mp);
 
 	camel_folder_summary_add (s, info);
-	update_summary (s, (CamelMessageInfoBase *) info);
+
 	return info;
 }
 
@@ -2642,7 +3194,7 @@ camel_folder_summary_add_from_message (CamelFolderSummary *s,
 	CamelMessageInfo *info = camel_folder_summary_info_new_from_message (s, msg, NULL);
 
 	camel_folder_summary_add (s, info);
-	update_summary (s, (CamelMessageInfoBase *) info);
+
 	return info;
 }
 
@@ -2844,103 +3396,55 @@ camel_folder_summary_touch (CamelFolderSummary *s)
  *
  * Empty the summary contents.
  **/
-void
-camel_folder_summary_clear (CamelFolderSummary *s)
-{
-	d(printf ("\ncamel_folder_summary_clearcalled \n"));
-	s->flags &= ~CAMEL_SUMMARY_DIRTY;
-
-	camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
-	if (camel_folder_summary_count (s) == 0) {
-		camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
-		return;
-	}
-
-	g_ptr_array_foreach (s->uids, (GFunc) camel_pstring_free, NULL);
-	g_ptr_array_free (s->uids, TRUE);
-	s->uids = g_ptr_array_new ();
-	s->saved_count = 0;
-	s->unread_count = 0;
-	s->deleted_count = 0;
-	s->junk_count = 0;
-	s->junk_not_deleted_count = 0;
-	s->visible_count = 0;
-
-	g_hash_table_destroy (s->loaded_infos);
-	s->loaded_infos = g_hash_table_new (g_str_hash, g_str_equal);
-
-	camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
-}
-
-/**
- * camel_folder_summary_clear_db:
- *
- * Since: 2.24
- **/
-void
-camel_folder_summary_clear_db (CamelFolderSummary *s)
+gboolean
+camel_folder_summary_clear (CamelFolderSummary *s, GError **error)
 {
+	GObject *summary_object;
 	CamelStore *parent_store;
 	CamelDB *cdb;
 	const gchar *folder_name;
+	gboolean res;
 
-	/* FIXME: This is non-sense. Neither an exception is passed,
-	nor a value returned. How is the caller supposed to know,
-	whether the operation is succesful */
-
-	d(printf ("\ncamel_folder_summary_load_from_db called \n"));
-	s->flags &= ~CAMEL_SUMMARY_DIRTY;
-
-	folder_name = camel_folder_get_full_name (s->folder);
-	parent_store = camel_folder_get_parent_store (s->folder);
-	cdb = parent_store->cdb_w;
+	g_return_val_if_fail (s != NULL, FALSE);
+	g_return_val_if_fail (s->priv != NULL, FALSE);
 
 	camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
 	if (camel_folder_summary_count (s) == 0) {
 		camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
-		return;
+		return TRUE;
 	}
 
-	g_ptr_array_foreach (s->uids, (GFunc) camel_pstring_free, NULL);
-	g_ptr_array_free (s->uids, TRUE);
-	s->uids = g_ptr_array_new ();
-	s->saved_count = 0;
-	s->unread_count = 0;
-	s->deleted_count = 0;
-	s->junk_count = 0;
-	s->junk_not_deleted_count = 0;
-	s->visible_count = 0;
-
-	g_hash_table_destroy (s->loaded_infos);
-	s->loaded_infos = g_hash_table_new (g_str_hash, g_str_equal);
+	g_hash_table_remove_all (s->priv->uids);
+	g_hash_table_remove_all (s->priv->loaded_infos);
 
-	camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
+	s->priv->saved_count = 0;
+	s->priv->unread_count = 0;
+	s->priv->deleted_count = 0;
+	s->priv->junk_count = 0;
+	s->priv->junk_not_deleted_count = 0;
+	s->priv->visible_count = 0;
 
-	camel_db_clear_folder_summary (cdb, folder_name, NULL);
-}
+	camel_folder_summary_touch (s);
 
-/* This function returns 0 on success. So the caller should not bother,
- * deleting the uid from db when the return value is non-zero */
-static gint
-summary_remove_uid (CamelFolderSummary *s,
-                    const gchar *uid)
-{
-	gint i;
+	folder_name = camel_folder_get_full_name (s->priv->folder);
+	parent_store = camel_folder_get_parent_store (s->priv->folder);
+	cdb = parent_store->cdb_w;
 
-	d(printf ("\nsummary_remove_uid called \n"));
+	res = camel_db_clear_folder_summary (cdb, folder_name, error) == 0;
 
-	/* This could be slower, but no otherway really. FIXME: Callers have to effective and shouldn't call it recursively. */
-	for (i = 0; i < s->uids->len; i++) {
-		if (strcmp (s->uids->pdata[i], uid) == 0) {
-			/* FIXME: Does using fast remove affect anything ? */
-			g_ptr_array_remove_index (s->uids, i);
-			camel_pstring_free (uid);
-			return 0;
-		}
+	summary_object = G_OBJECT (s);
+	g_object_freeze_notify (summary_object);
+	g_object_notify (summary_object, "saved-count");
+	g_object_notify (summary_object, "unread-count");
+	g_object_notify (summary_object, "deleted-count");
+	g_object_notify (summary_object, "junk-count");
+	g_object_notify (summary_object, "junk-not-deleted-count");
+	g_object_notify (summary_object, "visible-count");
+	g_object_thaw_notify (summary_object);
 
-	}
+	camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
 
-	return -1;
+	return res;
 }
 
 /**
@@ -2949,34 +3453,23 @@ summary_remove_uid (CamelFolderSummary *s,
  * @info: a #CamelMessageInfo
  *
  * Remove a specific @info record from the summary.
+ *
+ * Returns: Whether the @info was found and removed from the @summary.
  **/
-void
+gboolean
 camel_folder_summary_remove (CamelFolderSummary *s,
                              CamelMessageInfo *info)
 {
-	CamelStore *parent_store;
-	const gchar *full_name;
-	gboolean found;
-	gint ret;
-
-	camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
-
-	found = g_hash_table_lookup (s->loaded_infos, camel_message_info_uid (info)) != NULL;
-	g_hash_table_remove (s->loaded_infos, camel_message_info_uid (info));
-	ret = summary_remove_uid (s, camel_message_info_uid (info));
-
-	s->flags |= CAMEL_SUMMARY_DIRTY;
-	s->meta_summary->msg_expunged = TRUE;
-	camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
-
-	full_name = camel_folder_get_full_name (s->folder);
-	parent_store = camel_folder_get_parent_store (s->folder);
-
-	if (!ret && camel_db_delete_uid (parent_store->cdb_w, full_name, camel_message_info_uid (info), NULL) != 0)
-		return;
+	g_return_val_if_fail (s != NULL, FALSE);
+	g_return_val_if_fail (s->priv != NULL, FALSE);
+	g_return_val_if_fail (info != NULL, FALSE);
 
-	if (found)
+	if (camel_folder_summary_remove_uid (s, camel_message_info_uid (info))) {
 		camel_message_info_free (info);
+		return TRUE;
+	}
+
+	return FALSE;
 }
 
 /**
@@ -2985,193 +3478,45 @@ camel_folder_summary_remove (CamelFolderSummary *s,
  * @uid: a uid
  *
  * Remove a specific info record from the summary, by @uid.
+ *
+ * Returns: Whether the @uid was found and removed from the @summary.
  **/
-void
+gboolean
 camel_folder_summary_remove_uid (CamelFolderSummary *s,
                                  const gchar *uid)
 {
-	CamelMessageInfo *oldinfo;
-	gchar *olduid;
-
-	camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
-	camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_REF_LOCK);
-	if (g_hash_table_lookup_extended (s->loaded_infos, uid, (gpointer) &olduid, (gpointer) &oldinfo)) {
-		/* make sure it doesn't vanish while we're removing it */
-		camel_message_info_ref (oldinfo);
-		camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_REF_LOCK);
-		camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
-		camel_folder_summary_remove (s, oldinfo);
-		camel_message_info_free (oldinfo);
-	} else {
-		CamelStore *parent_store;
-		const gchar *full_name;
-		gchar *tmpid = g_strdup (uid);
-		gint ret;
-		/* Info isn't loaded into the memory. We must just remove the UID*/
-		ret = summary_remove_uid (s, uid);
-		camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_REF_LOCK);
-		camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
-
-		full_name = camel_folder_get_full_name (s->folder);
-		parent_store = camel_folder_get_parent_store (s->folder);
-		if (!ret && camel_db_delete_uid (parent_store->cdb_w, full_name, tmpid, NULL) != 0) {
-			g_free (tmpid);
-			return;
-		}
-		g_free (tmpid);
-	}
-}
-
-/* _fast doesn't deal with db and leaves it to the caller. */
-
-/**
- * camel_folder_summary_remove_uid_fast:
- *
- * Since: 2.24
- **/
-void
-camel_folder_summary_remove_uid_fast (CamelFolderSummary *s,
-                                      const gchar *uid)
-{
-	CamelMessageInfo *oldinfo;
-	gchar *olduid;
-
-	camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
-	camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_REF_LOCK);
-	if (g_hash_table_lookup_extended (s->loaded_infos, uid, (gpointer) &olduid, (gpointer) &oldinfo)) {
-		/* make sure it doesn't vanish while we're removing it */
-		camel_message_info_ref (oldinfo);
-		camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_REF_LOCK);
-		g_hash_table_remove (s->loaded_infos, olduid);
-		summary_remove_uid (s, olduid);
-		s->flags |= CAMEL_SUMMARY_DIRTY;
-		s->meta_summary->msg_expunged = TRUE;
-		camel_message_info_free (oldinfo);
-		camel_message_info_free (oldinfo);
-		camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
-	} else {
-		gchar *tmpid = g_strdup (uid);
-		/* Info isn't loaded into the memory. We must just remove the UID*/
-		summary_remove_uid (s, uid);
-		camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_REF_LOCK);
-		camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
-		g_free (tmpid);
-	}
-}
+	gpointer ptr_uid = NULL, ptr_flags = NULL;
+	CamelStore *parent_store;
+	const gchar *full_name;
+	const gchar *uid_copy;
+	gboolean res = TRUE;
 
-/**
- * camel_folder_summary_remove_index_fast:
- *
- * Since: 2.24
- **/
-void
-camel_folder_summary_remove_index_fast (CamelFolderSummary *s,
-                                        gint index)
-{
-	const gchar *uid = s->uids->pdata[index];
-	CamelMessageInfo *oldinfo;
-	gchar *olduid;
+	g_return_val_if_fail (s != NULL, FALSE);
+	g_return_val_if_fail (s->priv != NULL, FALSE);
+	g_return_val_if_fail (uid != NULL, FALSE);
 
 	camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
-	camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_REF_LOCK);
-
-	if (g_hash_table_lookup_extended (s->loaded_infos, uid, (gpointer) &olduid, (gpointer) &oldinfo)) {
-		/* make sure it doesn't vanish while we're removing it */
-		g_hash_table_remove (s->loaded_infos, uid);
-		camel_pstring_free (uid);
-		g_ptr_array_remove_index (s->uids, index);
-		camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_REF_LOCK);
-		camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
-		camel_message_info_free (oldinfo);
-	} else {
-		/* Info isn't loaded into the memory. We must just remove the UID*/
-		g_ptr_array_remove_index (s->uids, index);
-		camel_pstring_free (uid);
-		camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_REF_LOCK);
+	if (!g_hash_table_lookup_extended (s->priv->uids, uid, &ptr_uid, &ptr_flags)) {
 		camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
+		return FALSE;
 	}
-}
-
-/**
- * camel_folder_summary_remove_index:
- * @summary: a #CamelFolderSummary object
- * @index: record index
- *
- * Remove a specific info record from the summary, by index.
- **/
-void
-camel_folder_summary_remove_index (CamelFolderSummary *s,
-                                   gint index)
-{
-	const gchar *uid = s->uids->pdata[index];
-
-	camel_folder_summary_remove_uid (s, uid);
-}
-
-/**
- * camel_folder_summary_remove_range:
- * @summary: a #CamelFolderSummary object
- * @start: initial index
- * @end: last index to remove
- *
- * Removes an indexed range of info records.
- **/
-void
-camel_folder_summary_remove_range (CamelFolderSummary *s,
-                                   gint start,
-                                   gint end)
-{
-	d(g_print ("\ncamel_folder_summary_remove_range called \n"));
-	if (end < start)
-		return;
-
-	camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
-
-	if (start < s->uids->len) {
-
-		gint i;
-		CamelDB *cdb;
-		CamelStore *parent_store;
-		const gchar *folder_name;
-		GList *uids = NULL;
-
-		end = MIN (end + 1, s->uids->len);
-
-		for (i = start; i < end; i++) {
-			const gchar *uid = s->uids->pdata[i];
-			gpointer olduid, oldinfo;
-
-			/* the uid will be freed below and will not be used because of changing size of the s->uids array */
-			uids = g_list_prepend (uids, (gpointer) uid);
-
-			if (g_hash_table_lookup_extended (s->loaded_infos, uid, &olduid, &oldinfo)) {
-				camel_message_info_free (oldinfo);
-				g_hash_table_remove (s->loaded_infos, uid);
-			}
-		}
 
-		folder_name = camel_folder_get_full_name (s->folder);
-		parent_store = camel_folder_get_parent_store (s->folder);
-		cdb = parent_store->cdb_w;
+	folder_summary_update_counts_by_flags (s, GPOINTER_TO_UINT (ptr_flags), TRUE);
 
-		/* FIXME[disk-summary] lifecycle of infos should be checked.
-		 * Add should add to db and del should del to db. Sync only
-		 * the changes at interval and remove those full sync on
-		 * folder switch */
-		camel_db_delete_uids (cdb, folder_name, uids, NULL);
+	uid_copy = camel_pstring_strdup (uid);
+	g_hash_table_remove (s->priv->uids, uid_copy);
+	g_hash_table_remove (s->priv->loaded_infos, uid_copy);
 
-		g_list_foreach (uids, (GFunc) camel_pstring_free, NULL);
-		g_list_free (uids);
+	full_name = camel_folder_get_full_name (s->priv->folder);
+	parent_store = camel_folder_get_parent_store (s->priv->folder);
+	if (camel_db_delete_uid (parent_store->cdb_w, full_name, uid_copy, NULL) != 0)
+		res = FALSE;
 
-		memmove (s->uids->pdata + start, s->uids->pdata + end, (s->uids->len - end) * sizeof (s->uids->pdata[0]));
-		g_ptr_array_set_size (s->uids, s->uids->len - (end - start));
+	camel_pstring_free (uid_copy);
 
-		s->flags |= CAMEL_SUMMARY_DIRTY;
+	camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
 
-		camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
-	} else {
-		camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
-	}
+	return res;
 }
 
 /* should be sorted, for binary search */
@@ -3366,7 +3711,7 @@ static gint
 summary_header_load (CamelFolderSummary *s,
                      FILE *in)
 {
-	if (!s->summary_path)
+	if (!s->priv->summary_path)
 		return -1;
 
 	fseek (in, 0, SEEK_SET);
@@ -3391,17 +3736,17 @@ summary_header_load (CamelFolderSummary *s,
 
 	/* legacy version */
 	if (camel_file_util_decode_fixed_int32 (in, (gint32 *) &s->flags) == -1
-	    || camel_file_util_decode_fixed_int32 (in, (gint32 *) &s->nextuid) == -1
+	    || camel_file_util_decode_fixed_int32 (in, (gint32 *) &s->priv->nextuid) == -1
 	    || camel_file_util_decode_time_t (in, &s->time) == -1
-	    || camel_file_util_decode_fixed_int32 (in, (gint32 *) &s->saved_count) == -1) {
+	    || camel_file_util_decode_fixed_int32 (in, (gint32 *) &s->priv->saved_count) == -1) {
 		return -1;
 	}
 
 	/* version 13 */
 	if (s->version < 0x100 && s->version >= 13
-	    && (camel_file_util_decode_fixed_int32 (in, (gint32 *) &s->unread_count) == -1
-		|| camel_file_util_decode_fixed_int32 (in, (gint32 *) &s->deleted_count) == -1
-		|| camel_file_util_decode_fixed_int32 (in, (gint32 *) &s->junk_count) == -1)) {
+	    && (camel_file_util_decode_fixed_int32 (in, (gint32 *) &s->priv->unread_count) == -1
+		|| camel_file_util_decode_fixed_int32 (in, (gint32 *) &s->priv->deleted_count) == -1
+		|| camel_file_util_decode_fixed_int32 (in, (gint32 *) &s->priv->junk_count) == -1)) {
 		return -1;
 	}
 
@@ -3746,8 +4091,12 @@ message_info_free (CamelFolderSummary *s,
 	CamelMessageInfoBase *mi = (CamelMessageInfoBase *) info;
 
 	if (mi->uid) {
-		if (s && g_hash_table_lookup (s->loaded_infos, mi->uid) == mi) {
-			g_hash_table_remove (s->loaded_infos, mi->uid);
+		if (s) {
+			camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
+			if (g_hash_table_lookup (s->priv->loaded_infos, mi->uid) == mi) {
+				g_hash_table_remove (s->priv->loaded_infos, mi->uid);
+			}
+			camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
 		}
 		camel_pstring_free (mi->uid);
 	}
@@ -3890,7 +4239,7 @@ summary_build_content_info (CamelFolderSummary *s,
 	/* start of this part */
 	state = camel_mime_parser_step (mp, &buffer, &len);
 
-	if (s->build_content)
+	if (s->priv->build_content)
 		info = CAMEL_FOLDER_SUMMARY_GET_CLASS (s)->content_info_new_from_parser (s, mp);
 
 	switch (state) {
@@ -4049,7 +4398,7 @@ summary_build_content_info_message (CamelFolderSummary *s,
 	CamelContentType *ct;
 	const struct _camel_header_raw *header;
 
-	if (s->build_content)
+	if (s->priv->build_content)
 		info = CAMEL_FOLDER_SUMMARY_GET_CLASS (s)->content_info_new_from_message (s, object);
 
 	containee = camel_medium_get_content (CAMEL_MEDIUM (object));
@@ -4619,7 +4968,7 @@ camel_message_info_free (gpointer o)
 		camel_folder_summary_unlock (mi->summary, CAMEL_FOLDER_SUMMARY_REF_LOCK);
 
 		/* FIXME: this is kinda busted, should really be handled by message info free */
-		if (mi->summary->build_content
+		if (mi->summary->priv->build_content
 		    && ((CamelMessageInfoBase *) mi)->content) {
 			camel_folder_summary_content_info_free (mi->summary, ((CamelMessageInfoBase *) mi)->content);
 		}
@@ -4863,29 +5212,6 @@ camel_message_info_dump (CamelMessageInfo *mi)
 	camel_content_info_dump (((CamelMessageInfoBase *) mi)->content, 0);
 }
 
-/**
- * camel_folder_summary_set_need_preview:
- *
- * Since: 2.28
- **/
-void
-camel_folder_summary_set_need_preview (CamelFolderSummary *summary,
-                                       gboolean preview)
-{
-	summary->priv->need_preview = preview;
-}
-
-/**
- * camel_folder_summary_get_need_preview:
- *
- * Since: 2.28
- **/
-gboolean
-camel_folder_summary_get_need_preview (CamelFolderSummary *summary)
-{
-	return summary->priv->need_preview;
-}
-
 static gboolean
 compare_strings (const gchar *str1,
                  const gchar *str2)
@@ -5063,4 +5389,3 @@ bdata_extract_string (/* const */ gchar **part)
 
 	return val;
 }
-
diff --git a/camel/camel-folder-summary.h b/camel/camel-folder-summary.h
index aaba7ae..01a795b 100644
--- a/camel/camel-folder-summary.h
+++ b/camel/camel-folder-summary.h
@@ -65,8 +65,6 @@ typedef struct _CamelFolderSummaryPrivate CamelFolderSummaryPrivate;
 typedef struct _CamelMessageInfo CamelMessageInfo;
 typedef struct _CamelMessageInfoBase CamelMessageInfoBase;
 
-typedef struct _CamelFolderMetaSummary CamelFolderMetaSummary;
-
 typedef struct _CamelMessageContentInfo CamelMessageContentInfo;
 
 /* A tree of message content info structures
@@ -239,31 +237,8 @@ struct _CamelFolderSummary {
 
 	/* header info */
 	guint32 version;	/* version of file loaded/loading */
-	CamelFolderSummaryFlags flags;
-	guint32 nextuid;	/* next uid? */
 	time_t time;		/* timestamp for this summary (for implementors to use) */
-	guint32 saved_count;	/* how many were saved/loaded */
-	guint32 unread_count;	/* handy totals */
-	guint32 deleted_count;
-	guint32 junk_count;
-	guint32 junk_not_deleted_count;
-	guint32 visible_count;
-
-	/* memory allocators (setup automatically) */
-	CamelMemChunk *message_info_chunks;
-	CamelMemChunk *content_info_chunks;
-
-	gchar *summary_path;
-	gboolean build_content;	/* do we try and parse/index the content, or not? */
-
-	/* New members to replace the above depreacted members */
-	GPtrArray *uids;
-	GHashTable *loaded_infos;
-
-	struct _CamelFolder *folder; /* parent folder, for events */
-	struct _CamelFolderMetaSummary *meta_summary; /* Meta summary */
-	time_t cache_load_time;
-	guint timeout_handle;
+	CamelFolderSummaryFlags flags;
 
 	const gchar *collate;
 	const gchar *sort_by;
@@ -287,12 +262,12 @@ struct _CamelFolderSummaryClass {
 	gint (*summary_header_save)(CamelFolderSummary *, FILE *);
 
 	/* Load/Save folder summary from DB*/
-	gint (*summary_header_from_db)(CamelFolderSummary *, struct _CamelFIRecord *);
+	gboolean (*summary_header_from_db)(CamelFolderSummary *, struct _CamelFIRecord *);
 	struct _CamelFIRecord * (*summary_header_to_db)(CamelFolderSummary *, GError **error);
 	CamelMessageInfo * (*message_info_from_db) (CamelFolderSummary *, struct _CamelMIRecord *);
 	struct _CamelMIRecord * (*message_info_to_db) (CamelFolderSummary *, CamelMessageInfo *);
 	CamelMessageContentInfo * (*content_info_from_db) (CamelFolderSummary *, struct _CamelMIRecord *);
-	gint (*content_info_to_db) (CamelFolderSummary *, CamelMessageContentInfo *, struct _CamelMIRecord *);
+	gboolean (*content_info_to_db) (CamelFolderSummary *, CamelMessageContentInfo *, struct _CamelMIRecord *);
 
 	/* create/save/load an individual message info */
 	CamelMessageInfo * (*message_info_new_from_header)(CamelFolderSummary *, struct _camel_header_raw *);
@@ -326,126 +301,204 @@ struct _CamelFolderSummaryClass {
 	gboolean (*info_set_flags)(CamelMessageInfo *mi, guint32 mask, guint32 set);
 };
 
-/* Meta-summary info */
-struct _CamelFolderMetaSummary {
-	guint32 major;		/* Major version of meta-summary */
-	guint32 minor;		/* Minor version of meta-summary */
-	guint32 uid_len;	/* Length of UID (for implementors to use) */
-	gboolean msg_expunged;	/* Whether any message is expunged or not */
-	gchar *path;		/* Path to meta-summary-file */
-};
-
-GType			 camel_folder_summary_get_type	(void);
-CamelFolderSummary      *camel_folder_summary_new	(struct _CamelFolder *folder);
-
-/* Deprecated */
-void camel_folder_summary_set_filename (CamelFolderSummary *summary, const gchar *filename);
-
-void camel_folder_summary_set_index (CamelFolderSummary *summary, CamelIndex *index);
-void camel_folder_summary_set_build_content (CamelFolderSummary *summary, gboolean state);
-
-guint32  camel_folder_summary_next_uid        (CamelFolderSummary *summary);
-gchar    *camel_folder_summary_next_uid_string (CamelFolderSummary *summary);
-void	 camel_folder_summary_set_uid	      (CamelFolderSummary *summary, guint32 uid);
+GType			camel_folder_summary_get_type	(void);
+CamelFolderSummary *	camel_folder_summary_new	(struct _CamelFolder *folder);
+
+struct _CamelFolder *	camel_folder_summary_get_folder	(CamelFolderSummary *summary);
+CamelFolderSummaryFlags	camel_folder_summary_get_flags	(CamelFolderSummary *summary);
+
+guint32			camel_folder_summary_get_saved_count
+							(CamelFolderSummary *summary);
+guint32			camel_folder_summary_get_unread_count
+							(CamelFolderSummary *summary);
+guint32			camel_folder_summary_get_deleted_count
+							(CamelFolderSummary *summary);
+guint32			camel_folder_summary_get_junk_count
+							(CamelFolderSummary *summary);
+guint32			camel_folder_summary_get_junk_not_deleted_count
+							(CamelFolderSummary *summary);
+guint32			camel_folder_summary_get_visible_count
+							(CamelFolderSummary *summary);
+
+void			camel_folder_summary_set_index	(CamelFolderSummary *summary,
+							 CamelIndex *index);
+CamelIndex *		camel_folder_summary_get_index	(CamelFolderSummary *summary);
+void			camel_folder_summary_set_build_content
+							(CamelFolderSummary *summary,
+							 gboolean state);
+gboolean		camel_folder_summary_get_build_content
+							(CamelFolderSummary *summary);
+void			camel_folder_summary_set_need_preview
+							(CamelFolderSummary *summary,
+							 gboolean preview);
+gboolean		camel_folder_summary_get_need_preview
+							(CamelFolderSummary *summary);
+guint32			camel_folder_summary_next_uid	(CamelFolderSummary *summary);
+void			camel_folder_summary_set_next_uid
+							(CamelFolderSummary *summary,
+							 guint32 uid);
+guint32			camel_folder_summary_get_next_uid
+							(CamelFolderSummary *summary);
+gchar *			camel_folder_summary_next_uid_string
+							(CamelFolderSummary *summary);
 
 /* load/save the full summary from/to the db */
-gint camel_folder_summary_save_to_db (CamelFolderSummary *s, GError **error);
-gint camel_folder_summary_load_from_db (CamelFolderSummary *s, GError **error);
+gboolean		camel_folder_summary_save_to_db	(CamelFolderSummary *s,
+							 GError **error);
+gboolean		camel_folder_summary_load_from_db
+							(CamelFolderSummary *s,
+							 GError **error);
 
 /* only load the header */
-gint camel_folder_summary_header_load_from_db (CamelFolderSummary *s, struct _CamelStore *store, const gchar *folder_name, GError **error);
-gint camel_folder_summary_header_save_to_db (CamelFolderSummary *s, GError **error);
+gboolean		camel_folder_summary_header_load_from_db
+							(CamelFolderSummary *s,
+							 struct _CamelStore *store,
+							 const gchar *folder_name,
+							 GError **error);
+gboolean		camel_folder_summary_header_save_to_db
+							(CamelFolderSummary *s,
+							 GError **error);
 
 /* set the dirty bit on the summary */
-void camel_folder_summary_touch (CamelFolderSummary *summary);
+void			camel_folder_summary_touch	(CamelFolderSummary *summary);
 
-/* add a new raw summary item */
-void camel_folder_summary_add (CamelFolderSummary *summary, CamelMessageInfo *info);
+/* Just build raw summary items */
+CamelMessageInfo *	camel_folder_summary_info_new_from_header
+							(CamelFolderSummary *summary,
+							 struct _camel_header_raw *headers);
+CamelMessageInfo *	camel_folder_summary_info_new_from_parser
+							(CamelFolderSummary *summary,
+							 CamelMimeParser *parser);
+CamelMessageInfo *	camel_folder_summary_info_new_from_message
+							(CamelFolderSummary *summary,
+							 CamelMimeMessage *message,
+							 const gchar *bodystructure);
+
+CamelMessageContentInfo *camel_folder_summary_content_info_new
+							(CamelFolderSummary *summary);
+void			camel_folder_summary_content_info_free
+							(CamelFolderSummary *summary,
+							 CamelMessageContentInfo *ci);
+
+void			camel_folder_summary_add_preview
+							(CamelFolderSummary *s,
+							 CamelMessageInfo *info);
 
-/* Peek from mem only */
-CamelMessageInfo * camel_folder_summary_peek_info (CamelFolderSummary *s, const gchar *uid);
+/* Migration code */
+gint			camel_folder_summary_migrate_infos
+							(CamelFolderSummary *s);
+
+/* build/add raw summary items */
+CamelMessageInfo *	camel_folder_summary_add_from_header
+							(CamelFolderSummary *summary,
+							 struct _camel_header_raw *headers);
+CamelMessageInfo *	camel_folder_summary_add_from_parser
+							(CamelFolderSummary *summary,
+							 CamelMimeParser *parser);
+CamelMessageInfo *	camel_folder_summary_add_from_message
+							(CamelFolderSummary *summary,
+							 CamelMimeMessage *message);
+
+/* add a new raw summary item */
+void			camel_folder_summary_add	(CamelFolderSummary *summary,
+							 CamelMessageInfo *info);
 
-/* Get only the uids of dirty/changed things to sync to server/db */
-GPtrArray * camel_folder_summary_get_changed (CamelFolderSummary *s);
-/* reload the summary at any required point if required */
-void camel_folder_summary_prepare_fetch_all (CamelFolderSummary *s, GError **error);
 /* insert mi to summary */
-void camel_folder_summary_insert (CamelFolderSummary *s, CamelMessageInfo *info, gboolean load);
+void			camel_folder_summary_insert	(CamelFolderSummary *s,
+							 CamelMessageInfo *info,
+							 gboolean load);
 
-void camel_folder_summary_remove_index_fast (CamelFolderSummary *s, gint index);
-void camel_folder_summary_remove_uid_fast (CamelFolderSummary *s, const gchar *uid);
+gboolean		camel_folder_summary_remove	(CamelFolderSummary *summary,
+							 CamelMessageInfo *info);
 
-/* build/add raw summary items */
-CamelMessageInfo *camel_folder_summary_add_from_header (CamelFolderSummary *summary, struct _camel_header_raw *headers);
-CamelMessageInfo *camel_folder_summary_add_from_parser (CamelFolderSummary *summary, CamelMimeParser *parser);
-CamelMessageInfo *camel_folder_summary_add_from_message (CamelFolderSummary *summary, CamelMimeMessage *message);
+gboolean		camel_folder_summary_remove_uid	(CamelFolderSummary *summary,
+							 const gchar *uid);
 
-/* Just build raw summary items */
-CamelMessageInfo *camel_folder_summary_info_new_from_header (CamelFolderSummary *summary, struct _camel_header_raw *headers);
-CamelMessageInfo *camel_folder_summary_info_new_from_parser (CamelFolderSummary *summary, CamelMimeParser *parser);
-CamelMessageInfo *camel_folder_summary_info_new_from_message (CamelFolderSummary *summary, CamelMimeMessage *message, const gchar *bodystructure);
+/* remove all items */
+gboolean		camel_folder_summary_clear	(CamelFolderSummary *summary,
+							 GError **error);
 
-CamelMessageContentInfo *camel_folder_summary_content_info_new (CamelFolderSummary *summary);
-void camel_folder_summary_content_info_free (CamelFolderSummary *summary, CamelMessageContentInfo *ci);
+/* lookup functions */
+guint			camel_folder_summary_count	(CamelFolderSummary *summary);
 
-/* removes a summary item, doesn't fix content offsets */
-void camel_folder_summary_remove (CamelFolderSummary *summary, CamelMessageInfo *info);
-void camel_folder_summary_remove_uid (CamelFolderSummary *summary, const gchar *uid);
-void camel_folder_summary_remove_index (CamelFolderSummary *summary, gint index);
-void camel_folder_summary_remove_range (CamelFolderSummary *summary, gint start, gint end);
+gboolean		camel_folder_summary_check_uid	(CamelFolderSummary *s,
+							 const gchar *uid);
+CamelMessageInfo *	camel_folder_summary_get	(CamelFolderSummary *summary,
+							 const gchar *uid);
+GPtrArray *		camel_folder_summary_get_array	(CamelFolderSummary *summary);
+void			camel_folder_summary_free_array	(GPtrArray *array);
 
-/* remove all items */
-void camel_folder_summary_clear (CamelFolderSummary *summary);
-void camel_folder_summary_clear_db (CamelFolderSummary *s);
+/* Peek from mem only */
+CamelMessageInfo *	camel_folder_summary_peek_loaded
+							(CamelFolderSummary *s,
+							 const gchar *uid);
 
-/* update visible/unread/... counts based on message flags */
-void camel_folder_summary_update_counts_by_flags (CamelFolderSummary *summary, guint32 flags, gboolean subtract);
+/* Get only the uids of dirty/changed things to sync to server/db */
+GPtrArray *		camel_folder_summary_get_changed
+							(CamelFolderSummary *s);
 
-/* lookup functions */
-guint camel_folder_summary_count (CamelFolderSummary *summary);
-CamelMessageInfo *camel_folder_summary_index (CamelFolderSummary *summary, gint index);
-CamelMessageInfo *camel_folder_summary_uid (CamelFolderSummary *summary, const gchar *uid);
-gchar * camel_folder_summary_uid_from_index (CamelFolderSummary *s, gint i);
-gboolean camel_folder_summary_check_uid (CamelFolderSummary *s, const gchar *uid);
+/* reload the summary at any required point if required */
+void			camel_folder_summary_prepare_fetch_all
+							(CamelFolderSummary *s,
+							 GError **error);
 
-GPtrArray *camel_folder_summary_array (CamelFolderSummary *summary);
-GHashTable *camel_folder_summary_get_hashtable (CamelFolderSummary *s);
-void camel_folder_summary_free_hashtable (GHashTable *ht);
+/* summary locking */
+void			camel_folder_summary_lock	(CamelFolderSummary *summary,
+							 CamelFolderSummaryLock lock);
+void			camel_folder_summary_unlock	(CamelFolderSummary *summary,
+							 CamelFolderSummaryLock lock);
 
 /* basically like strings, but certain keywords can be compressed and de-cased */
-gint camel_folder_summary_encode_token (FILE *out, const gchar *str);
-gint camel_folder_summary_decode_token (FILE *in, gchar **str);
+gint			camel_folder_summary_encode_token
+							(FILE *out,
+							 const gchar *str);
+gint			camel_folder_summary_decode_token
+							(FILE *in,
+							 gchar **str);
 
 /* message flag operations */
-gboolean	camel_flag_get (CamelFlag **list, const gchar *name);
-gboolean	camel_flag_set (CamelFlag **list, const gchar *name, gboolean value);
-gboolean	camel_flag_list_copy (CamelFlag **to, CamelFlag **from);
-gint		camel_flag_list_size (CamelFlag **list);
-void		camel_flag_list_free (CamelFlag **list);
-
-CamelMessageFlags
-		camel_system_flag (const gchar *name);
-gboolean	camel_system_flag_get (CamelMessageFlags flags, const gchar *name);
+gboolean		camel_flag_get			(CamelFlag **list,
+							 const gchar *name);
+gboolean		camel_flag_set			(CamelFlag **list,
+							 const gchar *name,
+							 gboolean value);
+gboolean		camel_flag_list_copy		(CamelFlag **to,
+							 CamelFlag **from);
+gint			camel_flag_list_size		(CamelFlag **list);
+void			camel_flag_list_free		(CamelFlag **list);
+
+CamelMessageFlags	camel_system_flag		(const gchar *name);
+gboolean		camel_system_flag_get		(CamelMessageFlags flags,
+							 const gchar *name);
 
 /* message tag operations */
-const gchar	*camel_tag_get (CamelTag **list, const gchar *name);
-gboolean	camel_tag_set (CamelTag **list, const gchar *name, const gchar *value);
-gboolean	camel_tag_list_copy (CamelTag **to, CamelTag **from);
-gint		camel_tag_list_size (CamelTag **list);
-void		camel_tag_list_free (CamelTag **list);
+const gchar *		camel_tag_get			(CamelTag **list,
+							 const gchar *name);
+gboolean		camel_tag_set			(CamelTag **list,
+							 const gchar *name,
+							 const gchar *value);
+gboolean		camel_tag_list_copy		(CamelTag **to,
+							 CamelTag **from);
+gint			camel_tag_list_size		(CamelTag **list);
+void			camel_tag_list_free		(CamelTag **list);
 
 /* Summary may be null */
 /* Use anonymous pointers to avoid tons of cast crap */
-gpointer camel_message_info_new (CamelFolderSummary *summary);
-gpointer camel_message_info_ref (gpointer info);
-CamelMessageInfo *camel_message_info_new_from_header (CamelFolderSummary *summary, struct _camel_header_raw *header);
-void camel_message_info_free (gpointer info);
-gpointer camel_message_info_clone (gconstpointer info);
+gpointer		camel_message_info_new		(CamelFolderSummary *summary);
+gpointer		camel_message_info_ref		(gpointer info);
+CamelMessageInfo *	camel_message_info_new_from_header
+							(CamelFolderSummary *summary,
+							 struct _camel_header_raw *header);
+void			camel_message_info_free		(gpointer info);
+gpointer		camel_message_info_clone	(gconstpointer info);
 
 /* accessors */
-gconstpointer camel_message_info_ptr (const CamelMessageInfo *mi, gint id);
-guint32 camel_message_info_uint32 (const CamelMessageInfo *mi, gint id);
-time_t camel_message_info_time (const CamelMessageInfo *mi, gint id);
+gconstpointer		camel_message_info_ptr		(const CamelMessageInfo *mi,
+							 gint id);
+guint32			camel_message_info_uint32	(const CamelMessageInfo *mi,
+							 gint id);
+time_t			camel_message_info_time		(const CamelMessageInfo *mi,
+							 gint id);
 
 #define camel_message_info_uid(mi) ((const gchar *)((const CamelMessageInfo *)mi)->uid)
 
@@ -497,33 +550,37 @@ time_t camel_message_info_time (const CamelMessageInfo *mi, gint id);
  **/
 #define camel_message_info_content(mi) ((const CamelMessageContentInfo *)camel_message_info_ptr((const CamelMessageInfo *)mi, CAMEL_MESSAGE_INFO_CONTENT))
 
-gboolean camel_message_info_user_flag (const CamelMessageInfo *mi, const gchar *id);
-const gchar *camel_message_info_user_tag (const CamelMessageInfo *mi, const gchar *id);
-
-gboolean camel_message_info_set_flags (CamelMessageInfo *mi, CamelMessageFlags flags, guint32 set);
-gboolean camel_message_info_set_user_flag (CamelMessageInfo *mi, const gchar *id, gboolean state);
-gboolean camel_message_info_set_user_tag (CamelMessageInfo *mi, const gchar *id, const gchar *val);
-
-void camel_folder_summary_set_need_preview (CamelFolderSummary *summary, gboolean preview);
-void camel_folder_summary_add_preview (CamelFolderSummary *s, CamelMessageInfo *info);
-gboolean camel_folder_summary_get_need_preview (CamelFolderSummary *summary);
+gboolean		camel_message_info_user_flag	(const CamelMessageInfo *mi,
+							 const gchar *id);
+const gchar *		camel_message_info_user_tag	(const CamelMessageInfo *mi,
+							 const gchar *id);
+
+gboolean		camel_message_info_set_flags	(CamelMessageInfo *mi,
+							 CamelMessageFlags flags,
+							 guint32 set);
+gboolean		camel_message_info_set_user_flag
+							(CamelMessageInfo *mi,
+							 const gchar *id,
+							 gboolean state);
+gboolean		camel_message_info_set_user_tag	(CamelMessageInfo *mi,
+							 const gchar *id,
+							 const gchar *val);
 
 const CamelMessageContentInfo * camel_folder_summary_guess_content_info (CamelMessageInfo *mi, CamelContentType *ctype);
 
-/* debugging functions */
-void camel_content_info_dump (CamelMessageContentInfo *ci, gint depth);
-
-void camel_message_info_dump (CamelMessageInfo *mi);
-
-/* Migration code */
-gint camel_folder_summary_migrate_infos (CamelFolderSummary *s);
+/* Deprecated */
+void			camel_folder_summary_set_filename
+							(CamelFolderSummary *summary,
+							 const gchar *filename);
 
-void camel_folder_summary_lock   (CamelFolderSummary *summary, CamelFolderSummaryLock lock);
-void camel_folder_summary_unlock (CamelFolderSummary *summary, CamelFolderSummaryLock lock);
+/* debugging functions */
+void			camel_content_info_dump		(CamelMessageContentInfo *ci,
+							 gint depth);
+void			camel_message_info_dump		(CamelMessageInfo *mi);
 
 /* utility functions for bdata string decomposition */
-gint   bdata_extract_digit (/* const */ gchar **part);
-gchar *bdata_extract_string (/* const */ gchar **part);
+gint			bdata_extract_digit		(/* const */ gchar **part);
+gchar *			bdata_extract_string		(/* const */ gchar **part);
 
 G_END_DECLS
 
diff --git a/camel/camel-folder-thread.c b/camel/camel-folder-thread.c
index 0c3f9b9..d8d5586 100644
--- a/camel/camel-folder-thread.c
+++ b/camel/camel-folder-thread.c
@@ -620,7 +620,7 @@ camel_folder_thread_messages_new (CamelFolder *folder,
 {
 	CamelFolderThread *thread;
 	GPtrArray *summary;
-	GPtrArray *fsummary;
+	GPtrArray *fsummary = NULL;
 	gint i;
 
 	thread = g_malloc (sizeof (*thread));
@@ -631,12 +631,13 @@ camel_folder_thread_messages_new (CamelFolder *folder,
 	thread->folder = g_object_ref (folder);
 
 	camel_folder_summary_prepare_fetch_all (folder->summary, NULL);
-	fsummary = camel_folder_summary_array (folder->summary);
 	thread->summary = summary = g_ptr_array_new ();
 
 	/* prefer given order from the summary order */
-	if (!uids)
+	if (!uids) {
+		fsummary = camel_folder_summary_get_array (folder->summary);
 		uids = fsummary;
+	}
 
 	for (i = 0; i < uids->len; i++) {
 		CamelMessageInfo *info;
@@ -648,7 +649,8 @@ camel_folder_thread_messages_new (CamelFolder *folder,
 		/* FIXME: Check if the info is leaking */
 	}
 
-	camel_folder_free_summary (folder, fsummary);
+	if (fsummary)
+		camel_folder_summary_free_array (fsummary);
 
 	thread_summary (thread, summary);
 
diff --git a/camel/camel-folder.c b/camel/camel-folder.c
index 549f15e..015d621 100644
--- a/camel/camel-folder.c
+++ b/camel/camel-folder.c
@@ -528,7 +528,6 @@ folder_dispose (GObject *object)
 	}
 
 	if (folder->summary) {
-		folder->summary->folder = NULL;
 		g_object_unref (folder->summary);
 		folder->summary = NULL;
 	}
@@ -580,7 +579,7 @@ folder_get_message_flags (CamelFolder *folder,
 
 	g_return_val_if_fail (folder->summary != NULL, 0);
 
-	info = camel_folder_summary_uid (folder->summary, uid);
+	info = camel_folder_summary_get (folder->summary, uid);
 	if (info == NULL)
 		return 0;
 
@@ -601,7 +600,7 @@ folder_set_message_flags (CamelFolder *folder,
 
 	g_return_val_if_fail (folder->summary != NULL, FALSE);
 
-	info = camel_folder_summary_uid (folder->summary, uid);
+	info = camel_folder_summary_get (folder->summary, uid);
 	if (info == NULL)
 		return FALSE;
 
@@ -621,7 +620,7 @@ folder_get_message_user_flag (CamelFolder *folder,
 
 	g_return_val_if_fail (folder->summary != NULL, FALSE);
 
-	info = camel_folder_summary_uid (folder->summary, uid);
+	info = camel_folder_summary_get (folder->summary, uid);
 	if (info == NULL)
 		return FALSE;
 
@@ -641,7 +640,7 @@ folder_set_message_user_flag (CamelFolder *folder,
 
 	g_return_if_fail (folder->summary != NULL);
 
-	info = camel_folder_summary_uid (folder->summary, uid);
+	info = camel_folder_summary_get (folder->summary, uid);
 	if (info == NULL)
 		return;
 
@@ -659,7 +658,7 @@ folder_get_message_user_tag (CamelFolder *folder,
 
 	g_return_val_if_fail (folder->summary != NULL, NULL);
 
-	info = camel_folder_summary_uid (folder->summary, uid);
+	info = camel_folder_summary_get (folder->summary, uid);
 	if (info == NULL)
 		return NULL;
 
@@ -679,7 +678,7 @@ folder_set_message_user_tag (CamelFolder *folder,
 
 	g_return_if_fail (folder->summary != NULL);
 
-	info = camel_folder_summary_uid (folder->summary, uid);
+	info = camel_folder_summary_get (folder->summary, uid);
 	if (info == NULL)
 		return;
 
@@ -692,7 +691,7 @@ folder_get_uids (CamelFolder *folder)
 {
 	g_return_val_if_fail (folder->summary != NULL, NULL);
 
-	return camel_folder_summary_array (folder->summary);
+	return camel_folder_summary_get_array (folder->summary);
 }
 
 static GPtrArray *
@@ -717,11 +716,7 @@ static void
 folder_free_uids (CamelFolder *folder,
                   GPtrArray *array)
 {
-	gint i;
-
-	for (i = 0; i < array->len; i++)
-		camel_pstring_free (array->pdata[i]);
-	g_ptr_array_free (array, TRUE);
+	camel_folder_summary_free_array (array);
 }
 
 static gint
@@ -749,15 +744,14 @@ folder_get_summary (CamelFolder *folder)
 {
 	g_return_val_if_fail (folder->summary != NULL, NULL);
 
-	return camel_folder_summary_array (folder->summary);
+	return camel_folder_summary_get_array (folder->summary);
 }
 
 static void
 folder_free_summary (CamelFolder *folder,
-                     GPtrArray *summary)
+                     GPtrArray *array)
 {
-	g_ptr_array_foreach (summary, (GFunc) camel_pstring_free, NULL);
-	g_ptr_array_free (summary, TRUE);
+	camel_folder_summary_free_array (array);
 }
 
 static void
@@ -777,7 +771,7 @@ folder_get_message_info (CamelFolder *folder,
 {
 	g_return_val_if_fail (folder->summary != NULL, NULL);
 
-	return camel_folder_summary_uid (folder->summary, uid);
+	return camel_folder_summary_get (folder->summary, uid);
 }
 
 static void
@@ -802,7 +796,7 @@ static void
 folder_delete (CamelFolder *folder)
 {
 	if (folder->summary)
-		camel_folder_summary_clear (folder->summary);
+		camel_folder_summary_clear (folder->summary, NULL);
 }
 
 static void
@@ -1959,7 +1953,7 @@ camel_folder_get_unread_message_count (CamelFolder *folder)
 	g_return_val_if_fail (CAMEL_IS_FOLDER (folder), -1);
 	g_return_val_if_fail (folder->summary != NULL, -1);
 
-	return folder->summary->unread_count;
+	return camel_folder_summary_get_unread_count (folder->summary);
 }
 
 /**
@@ -1975,7 +1969,7 @@ camel_folder_get_deleted_message_count (CamelFolder *folder)
 	g_return_val_if_fail (CAMEL_IS_FOLDER (folder), -1);
 	g_return_val_if_fail (folder->summary != NULL, -1);
 
-	return folder->summary->deleted_count;
+	return camel_folder_summary_get_deleted_count (folder->summary);
 }
 
 /**
diff --git a/camel/camel-store-summary.c b/camel/camel-store-summary.c
index 5a90759..8b51e77 100644
--- a/camel/camel-store-summary.c
+++ b/camel/camel-store-summary.c
@@ -36,6 +36,7 @@
 
 #include "camel-file-utils.h"
 #include "camel-store-summary.h"
+#include "camel-folder-summary.h"
 #include "camel-url.h"
 #include "camel-win32.h"
 
@@ -50,9 +51,11 @@
 #define CAMEL_STORE_SUMMARY_VERSION (2)
 
 struct _CamelStoreSummaryPrivate {
-	GMutex *summary_lock;	/* for the summary hashtable/array */
-	GMutex *io_lock;	/* load/save lock, for access to saved_count, etc */
-	GMutex *ref_lock;	/* for reffing/unreffing messageinfo's ALWAYS obtain before CAMEL_STORE_SUMMARY_SUMMARY_LOCK */
+	GStaticRecMutex summary_lock;	/* for the summary hashtable/array */
+	GStaticRecMutex io_lock;	/* load/save lock, for access to saved_count, etc */
+	GStaticRecMutex ref_lock;	/* for reffing/unreffing messageinfo's ALWAYS obtain before CAMEL_STORE_SUMMARY_SUMMARY_LOCK */
+
+	GHashTable *folder_summaries; /* CamelFolderSummary->path; doesn't add reference to CamelFolderSummary */
 };
 
 G_DEFINE_TYPE (CamelStoreSummary, camel_store_summary, CAMEL_TYPE_OBJECT)
@@ -65,15 +68,16 @@ store_summary_finalize (GObject *object)
 	camel_store_summary_clear (summary);
 	g_ptr_array_free (summary->folders, TRUE);
 	g_hash_table_destroy (summary->folders_path);
+	g_hash_table_destroy (summary->priv->folder_summaries);
 
 	g_free (summary->summary_path);
 
 	if (summary->store_info_chunks != NULL)
 		camel_memchunk_destroy (summary->store_info_chunks);
 
-	g_mutex_free (summary->priv->summary_lock);
-	g_mutex_free (summary->priv->io_lock);
-	g_mutex_free (summary->priv->ref_lock);
+	g_static_rec_mutex_free (&summary->priv->summary_lock);
+	g_static_rec_mutex_free (&summary->priv->io_lock);
+	g_static_rec_mutex_free (&summary->priv->ref_lock);
 
 	/* Chain up to parent's finalize() method. */
 	G_OBJECT_CLASS (camel_store_summary_parent_class)->finalize (object);
@@ -309,10 +313,11 @@ camel_store_summary_init (CamelStoreSummary *summary)
 
 	summary->folders = g_ptr_array_new ();
 	summary->folders_path = g_hash_table_new (g_str_hash, g_str_equal);
+	summary->priv->folder_summaries = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
 
-	summary->priv->summary_lock = g_mutex_new ();
-	summary->priv->io_lock = g_mutex_new ();
-	summary->priv->ref_lock = g_mutex_new ();
+	g_static_rec_mutex_init (&summary->priv->summary_lock);
+	g_static_rec_mutex_init (&summary->priv->io_lock);
+	g_static_rec_mutex_init (&summary->priv->ref_lock);
 }
 
 /**
@@ -1051,13 +1056,13 @@ camel_store_summary_lock (CamelStoreSummary *summary,
 
 	switch (lock) {
 		case CAMEL_STORE_SUMMARY_SUMMARY_LOCK:
-			g_mutex_lock (summary->priv->summary_lock);
+			g_static_rec_mutex_lock (&summary->priv->summary_lock);
 			break;
 		case CAMEL_STORE_SUMMARY_IO_LOCK:
-			g_mutex_lock (summary->priv->io_lock);
+			g_static_rec_mutex_lock (&summary->priv->io_lock);
 			break;
 		case CAMEL_STORE_SUMMARY_REF_LOCK:
-			g_mutex_lock (summary->priv->ref_lock);
+			g_static_rec_mutex_lock (&summary->priv->ref_lock);
 			break;
 		default:
 			g_return_if_reached ();
@@ -1081,15 +1086,138 @@ camel_store_summary_unlock (CamelStoreSummary *summary,
 
 	switch (lock) {
 		case CAMEL_STORE_SUMMARY_SUMMARY_LOCK:
-			g_mutex_unlock (summary->priv->summary_lock);
+			g_static_rec_mutex_unlock (&summary->priv->summary_lock);
 			break;
 		case CAMEL_STORE_SUMMARY_IO_LOCK:
-			g_mutex_unlock (summary->priv->io_lock);
+			g_static_rec_mutex_unlock (&summary->priv->io_lock);
 			break;
 		case CAMEL_STORE_SUMMARY_REF_LOCK:
-			g_mutex_unlock (summary->priv->ref_lock);
+			g_static_rec_mutex_unlock (&summary->priv->ref_lock);
 			break;
 		default:
 			g_return_if_reached ();
 	}
 }
+
+static void
+store_summary_sync_folder_summary_count_cb (CamelFolderSummary *folder_summary, GParamSpec *param, CamelStoreSummary *summary)
+{
+	const gchar *path;
+	CamelStoreInfo *si;
+
+	g_return_if_fail (folder_summary != NULL);
+	g_return_if_fail (param != NULL);
+	g_return_if_fail (summary != NULL);
+	g_return_if_fail (summary->priv != NULL);
+
+	path = g_hash_table_lookup (summary->priv->folder_summaries, folder_summary);
+	g_return_if_fail (path != NULL);
+
+	camel_store_summary_lock (summary, CAMEL_STORE_SUMMARY_SUMMARY_LOCK);
+	si = camel_store_summary_path (summary, path);
+	if (!si) {
+		camel_store_summary_unlock (summary, CAMEL_STORE_SUMMARY_SUMMARY_LOCK);
+		g_warning ("%s: Store summary %p doesn't hold path '%s'", G_STRFUNC, summary, path);
+		return;
+	}
+
+	if (g_strcmp0 (g_param_spec_get_name (param), "saved-count") == 0) {
+		si->total = camel_folder_summary_get_saved_count (folder_summary);
+		camel_store_summary_touch (summary);
+	} else if (g_strcmp0 (g_param_spec_get_name (param), "unread-count") == 0) {
+		si->unread = camel_folder_summary_get_unread_count (folder_summary);
+		camel_store_summary_touch (summary);
+	} else {
+		g_warn_if_reached ();
+	}
+
+	camel_store_summary_info_free (summary, si);
+
+	camel_store_summary_unlock (summary, CAMEL_STORE_SUMMARY_SUMMARY_LOCK);
+}
+
+/**
+ * camel_store_summary_connect_folder_summary:
+ * @summary: a #CamelStoreSummary object
+ * @path: used path for @folder_summary
+ * @folder_summary: a #CamelFolderSummary object
+ *
+ * Connects listeners for count changes on @folder_summary to keep CamelStoreInfo.total
+ * and CamelStoreInfo.unread in sync transparently. The @folder_summary is stored
+ * in @summary as @path. Use camel_store_summary_disconnect_folder_summary()
+ * to disconnect from listening.
+ *
+ * Returns: Whether successfully connect callbacks for count change notifications.
+ *
+ * Since: 3.4
+ **/
+gboolean
+camel_store_summary_connect_folder_summary (CamelStoreSummary *summary, const gchar *path, CamelFolderSummary *folder_summary)
+{
+	CamelStoreInfo *si;
+
+	g_return_val_if_fail (summary != NULL, FALSE);
+	g_return_val_if_fail (summary->priv != NULL, FALSE);
+	g_return_val_if_fail (path != NULL, FALSE);
+	g_return_val_if_fail (folder_summary != NULL, FALSE);
+
+	camel_store_summary_lock (summary, CAMEL_STORE_SUMMARY_SUMMARY_LOCK);
+
+	si = camel_store_summary_path (summary, path);
+	if (!si) {
+		camel_store_summary_unlock (summary, CAMEL_STORE_SUMMARY_SUMMARY_LOCK);
+		g_warning ("%s: Store summary %p doesn't hold path '%s'", G_STRFUNC, summary, path);
+		return FALSE;
+	}
+
+	camel_store_summary_info_free (summary, si);
+
+	if (g_hash_table_lookup (summary->priv->folder_summaries, folder_summary)) {
+		camel_store_summary_unlock (summary, CAMEL_STORE_SUMMARY_SUMMARY_LOCK);
+		g_warning ("%s: Store summary %p already listens on folder summary %p", G_STRFUNC, summary, folder_summary);
+		return FALSE;
+	}
+
+	g_hash_table_insert (summary->priv->folder_summaries, folder_summary, g_strdup (path));
+	g_signal_connect (folder_summary, "notify::saved-count", G_CALLBACK (store_summary_sync_folder_summary_count_cb), summary);
+	g_signal_connect (folder_summary, "notify::unread-count", G_CALLBACK (store_summary_sync_folder_summary_count_cb), summary);
+
+	camel_store_summary_unlock (summary, CAMEL_STORE_SUMMARY_SUMMARY_LOCK);
+
+	return TRUE;
+}
+
+/**
+ * camel_store_summary_disconnect_folder_summary:
+ * @summary: a #CamelStoreSummary object
+ * @folder_summary: a #CamelFolderSummary object
+ *
+ * Diconnects count change listeners previously connected
+ * by camel_store_summary_connect_folder_summary().
+ *
+ * Returns: Whether such connection existed and whether was successfully removed.
+ *
+ * Since: 3.4
+ **/
+gboolean
+camel_store_summary_disconnect_folder_summary (CamelStoreSummary *summary, CamelFolderSummary *folder_summary)
+{
+	g_return_val_if_fail (summary != NULL, FALSE);
+	g_return_val_if_fail (summary->priv != NULL, FALSE);
+	g_return_val_if_fail (folder_summary != NULL, FALSE);
+
+	camel_store_summary_lock (summary, CAMEL_STORE_SUMMARY_SUMMARY_LOCK);
+
+	if (!g_hash_table_lookup (summary->priv->folder_summaries, folder_summary)) {
+		camel_store_summary_unlock (summary, CAMEL_STORE_SUMMARY_SUMMARY_LOCK);
+		g_warning ("%s: Store summary %p is not connected to folder summary %p", G_STRFUNC, summary, folder_summary);
+		return FALSE;
+	}
+
+	g_signal_handlers_disconnect_by_func (folder_summary, G_CALLBACK (store_summary_sync_folder_summary_count_cb), summary);
+	g_hash_table_remove (summary->priv->folder_summaries, folder_summary);
+
+	camel_store_summary_unlock (summary, CAMEL_STORE_SUMMARY_SUMMARY_LOCK);
+
+	return TRUE;
+}
diff --git a/camel/camel-store-summary.h b/camel/camel-store-summary.h
index 7a2babf..b33a9d6 100644
--- a/camel/camel-store-summary.h
+++ b/camel/camel-store-summary.h
@@ -184,6 +184,10 @@ void camel_store_info_set_string (CamelStoreSummary *summary, CamelStoreInfo *in
 void camel_store_summary_lock   (CamelStoreSummary *summary, CamelStoreSummaryLock lock);
 void camel_store_summary_unlock (CamelStoreSummary *summary, CamelStoreSummaryLock lock);
 
+struct _CamelFolderSummary;
+gboolean camel_store_summary_connect_folder_summary (CamelStoreSummary *summary, const gchar *path, struct _CamelFolderSummary *folder_summary);
+gboolean camel_store_summary_disconnect_folder_summary (CamelStoreSummary *summary, struct _CamelFolderSummary *folder_summary);
+
 G_END_DECLS
 
 #endif /* CAMEL_STORE_SUMMARY_H */
diff --git a/camel/camel-vee-folder.c b/camel/camel-vee-folder.c
index 5a3d275..93c95f9 100644
--- a/camel/camel-vee-folder.c
+++ b/camel/camel-vee-folder.c
@@ -172,13 +172,12 @@ folder_changed_add_uid (CamelFolder *sub,
 		}
 		vinfo = (CamelVeeMessageInfo *) camel_folder_get_message_info ((CamelFolder *) folder_unmatched, vuid);
 		if (vinfo) {
-			camel_folder_summary_update_counts_by_flags (CAMEL_FOLDER (folder_unmatched)->summary, vinfo->old_flags, TRUE);
 			camel_folder_change_info_remove_uid (
 				folder_unmatched->changes, vuid);
 
 			*unm_added_l = g_list_prepend (*unm_added_l, (gpointer) camel_pstring_strdup (vuid));
 
-			camel_folder_summary_remove_uid_fast (
+			camel_folder_summary_remove_uid (
 				CAMEL_FOLDER (folder_unmatched)->summary, vuid);
 			camel_folder_free_message_info (
 				CAMEL_FOLDER (folder_unmatched),
@@ -211,17 +210,11 @@ folder_changed_remove_uid (CamelFolder *sub,
 	memcpy (vuid, hash, 8);
 	strcpy (vuid + 8, uid);
 
-	vinfo = (CamelVeeMessageInfo *) camel_folder_summary_uid (folder->summary, vuid);
-	if (vinfo) {
-		camel_folder_summary_update_counts_by_flags (folder->summary, vinfo->old_flags, TRUE);
-		camel_message_info_free ((CamelMessageInfo *) vinfo);
-	}
-
 	camel_folder_change_info_remove_uid (vf->changes, vuid);
 	if (use_db)
 		*m_removed_l = g_list_prepend (*m_removed_l, (gpointer) camel_pstring_strdup (vuid));
 
-	camel_folder_summary_remove_uid_fast (folder->summary, vuid);
+	camel_folder_summary_remove_uid (folder->summary, vuid);
 
 	if ((vf->flags & CAMEL_STORE_FOLDER_PRIVATE) == 0 && !CAMEL_IS_VEE_FOLDER (sub) && folder_unmatched != NULL) {
 		if (keep) {
@@ -247,13 +240,12 @@ folder_changed_remove_uid (CamelFolder *sub,
 
 			vinfo = (CamelVeeMessageInfo *) camel_folder_get_message_info ((CamelFolder *) folder_unmatched, vuid);
 			if (vinfo) {
-				camel_folder_summary_update_counts_by_flags (CAMEL_FOLDER (folder_unmatched)->summary, vinfo->old_flags, TRUE);
 				camel_folder_change_info_remove_uid (
 					folder_unmatched->changes, vuid);
 
 				*unm_removed_l = g_list_prepend (*unm_removed_l, (gpointer) camel_pstring_strdup (vuid));
 
-				camel_folder_summary_remove_uid_fast (
+				camel_folder_summary_remove_uid (
 					CAMEL_FOLDER (folder_unmatched)->summary, vuid);
 				camel_folder_free_message_info (
 					CAMEL_FOLDER (folder_unmatched),
@@ -264,18 +256,6 @@ folder_changed_remove_uid (CamelFolder *sub,
 }
 
 static void
-update_old_flags (CamelFolderSummary *summary,
-                  CamelVeeMessageInfo *vinfo)
-{
-	g_return_if_fail (summary != NULL);
-	g_return_if_fail (vinfo != NULL);
-
-	camel_folder_summary_update_counts_by_flags (summary, vinfo->old_flags, TRUE);
-	vinfo->old_flags = camel_message_info_flags ((CamelMessageInfo *) vinfo);
-	camel_folder_summary_update_counts_by_flags (summary, vinfo->old_flags, FALSE);
-}
-
-static void
 folder_changed_change_uid (CamelFolder *sub,
                            const gchar *uid,
                            const gchar hash[8],
@@ -294,21 +274,23 @@ folder_changed_change_uid (CamelFolder *sub,
 	memcpy (vuid, hash, 8);
 	strcpy (vuid + 8, uid);
 
-	vinfo = (CamelVeeMessageInfo *) camel_folder_summary_uid (folder->summary, vuid);
+	vinfo = (CamelVeeMessageInfo *) camel_folder_summary_get (folder->summary, vuid);
 	if (folder_unmatched != NULL)
-		uinfo = (CamelVeeMessageInfo *) camel_folder_summary_uid (((CamelFolder *) folder_unmatched)->summary, vuid);
+		uinfo = (CamelVeeMessageInfo *) camel_folder_summary_get (((CamelFolder *) folder_unmatched)->summary, vuid);
 	if (vinfo || uinfo) {
 		info = camel_folder_get_message_info (sub, uid);
 		if (info) {
 			if (vinfo) {
 				camel_folder_change_info_change_uid (vf->changes, vuid);
-				update_old_flags (folder->summary, vinfo);
+				vinfo->old_flags = camel_message_info_flags ((CamelMessageInfo *) vinfo);
+				vinfo->info.flags |= (vinfo->old_flags & ~CAMEL_MESSAGE_FOLDER_FLAGGED);
 				camel_message_info_free ((CamelMessageInfo *) vinfo);
 			}
 
 			if (uinfo) {
 				camel_folder_change_info_change_uid (folder_unmatched->changes, vuid);
-				update_old_flags (CAMEL_FOLDER (folder_unmatched)->summary, uinfo);
+				uinfo->old_flags = camel_message_info_flags ((CamelMessageInfo *) uinfo);
+				uinfo->info.flags |= (uinfo->old_flags & ~CAMEL_MESSAGE_FOLDER_FLAGGED);
 				camel_message_info_free ((CamelMessageInfo *) uinfo);
 			}
 
@@ -414,7 +396,7 @@ folder_changed_change (CamelSession *session,
 				}
 				memcpy (vuid, hash, 8);
 				strcpy (vuid + 8, uid);
-				vinfo = (CamelVeeMessageInfo *) camel_folder_summary_uid (folder->summary, vuid);
+				vinfo = (CamelVeeMessageInfo *) camel_folder_summary_get (folder->summary, vuid);
 				if (vinfo == NULL) {
 					g_ptr_array_add (newchanged, (gchar *) uid);
 				} else {
@@ -526,7 +508,7 @@ folder_changed_change (CamelSession *session,
 			}
 			memcpy (vuid, hash, 8);
 			strcpy (vuid + 8, uid);
-			vinfo = (CamelVeeMessageInfo *) camel_folder_summary_uid (folder->summary, vuid);
+			vinfo = (CamelVeeMessageInfo *) camel_folder_summary_get (folder->summary, vuid);
 			if (vinfo == NULL) {
 				if (g_hash_table_lookup (matches_hash, uid)) {
 					/* A uid we dont have, but now it matches, add it */
@@ -649,37 +631,33 @@ subfolder_renamed_update (CamelVeeFolder *vf,
                           CamelFolder *sub,
                           gchar hash[8])
 {
-	gint count, i;
+	gint i;
 	CamelFolderChangeInfo *changes = NULL;
 	CamelVeeFolder *folder_unmatched = vf->parent_vee_store ? vf->parent_vee_store->folder_unmatched : NULL;
 	GHashTable *unmatched_uids = vf->parent_vee_store ? vf->parent_vee_store->unmatched_uids : NULL;
 	CamelFolderSummary *ssummary = sub->summary;
+	GPtrArray *known_uids;
 
 	camel_vee_folder_lock (vf, CAMEL_VEE_FOLDER_SUMMARY_LOCK);
 
 	camel_folder_summary_prepare_fetch_all (((CamelFolder *) vf)->summary, NULL);
 
-	count = camel_folder_summary_count (((CamelFolder *) vf)->summary);
-	for (i = 0; i < count; i++) {
-		CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *) camel_folder_summary_index (((CamelFolder *) vf)->summary, i);
+	known_uids = camel_folder_summary_get_array (((CamelFolder *) vf)->summary);
+	for (i = 0; known_uids && i < known_uids->len; i++) {
+		CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *) camel_folder_summary_get (((CamelFolder *) vf)->summary, g_ptr_array_index (known_uids, i));
 		CamelVeeMessageInfo *vinfo;
 
 		if (mi == NULL)
 			continue;
 
-		if (mi->summary == ssummary) {
+		if (mi->orig_summary == ssummary) {
 			gchar *uid = (gchar *) camel_message_info_uid (mi);
 			gchar *oldkey;
 			gpointer oldval;
 
 			camel_folder_change_info_remove_uid (vf->changes, uid);
-			camel_folder_summary_update_counts_by_flags (CAMEL_FOLDER (vf)->summary, mi->old_flags, TRUE);
 			camel_folder_summary_remove (((CamelFolder *) vf)->summary, (CamelMessageInfo *) mi);
 
-			/* works since we always append on the end */
-			i--;
-			count--;
-
 			vinfo = vee_folder_add_uid (vf, sub, uid + 8, hash);
 			if (vinfo) {
 				camel_folder_change_info_add_uid (vf->changes, camel_message_info_uid (vinfo));
@@ -699,6 +677,8 @@ subfolder_renamed_update (CamelVeeFolder *vf,
 		camel_message_info_free ((CamelMessageInfo *) mi);
 	}
 
+	camel_folder_summary_free_array (known_uids);
+
 	if (camel_folder_change_info_changed (vf->changes)) {
 		changes = vf->changes;
 		vf->changes = camel_folder_change_info_new ();
@@ -733,14 +713,12 @@ unmatched_check_uid (gchar *uidin,
 		if (vee_folder_add_uid_test (u->folder_unmatched, u->source, uidin, u->hash))
 			camel_folder_change_info_add_uid (u->folder_unmatched->changes, uid);
 	} else {
-		CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *) camel_folder_summary_uid (((CamelFolder *) u->folder_unmatched)->summary, uid);
+		CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *) camel_folder_summary_get (((CamelFolder *) u->folder_unmatched)->summary, uid);
 		if (mi) {
-			camel_folder_summary_update_counts_by_flags (CAMEL_FOLDER (u->folder_unmatched)->summary, mi->old_flags, TRUE);
-
 			if (u->message_uids != NULL)
 				g_queue_push_tail (u->message_uids, g_strdup (uid));
 
-			camel_folder_summary_remove_uid_fast (
+			camel_folder_summary_remove_uid (
 				((CamelFolder *) u->folder_unmatched)->summary, uid);
 			camel_folder_change_info_remove_uid (
 				u->folder_unmatched->changes, uid);
@@ -801,22 +779,22 @@ summary_header_to_db (CamelFolderSummary *s,
 	const gchar *full_name;
 
 	/* We do this during write, so lets use write handle, though we gonna read */
-	full_name = camel_folder_get_full_name (s->folder);
+	full_name = camel_folder_get_full_name (camel_folder_summary_get_folder (s));
 
 	record->folder_name = g_strdup (full_name);
 
 	/* we always write out the current version */
 	record->version = 13;  /* FIXME: CAMEL_FOLDER_SUMMARY_VERSION; */
 	record->flags  = s->flags;
-	record->nextuid = s->nextuid;
+	record->nextuid = camel_folder_summary_get_next_uid (s);
 	record->time = s->time;
 
-	record->saved_count = s->uids->len;
-	record->junk_count = s->junk_count;
-	record->deleted_count = s->deleted_count;
-	record->unread_count = s->unread_count;
-	record->visible_count = s->visible_count;
-	record->jnd_count = s->junk_not_deleted_count;
+	record->saved_count = camel_folder_summary_count (s);
+	record->junk_count = camel_folder_summary_get_junk_count (s);
+	record->deleted_count = camel_folder_summary_get_deleted_count (s);
+	record->unread_count = camel_folder_summary_get_unread_count (s);
+	record->visible_count = camel_folder_summary_get_visible_count (s);
+	record->jnd_count = camel_folder_summary_get_junk_not_deleted_count (s);
 
 	return record;
 }
@@ -1074,13 +1052,13 @@ vee_folder_search_by_expression (CamelFolder *folder,
 	GHashTable *searched = g_hash_table_new (NULL, NULL);
 	CamelVeeFolder *folder_unmatched = vf->parent_vee_store ? vf->parent_vee_store->folder_unmatched : NULL;
 	gboolean is_folder_unmatched = vf == folder_unmatched && folder_unmatched;
-	GHashTable *folder_unmatched_hash = NULL;
+	CamelFolderSummary *folder_unmatched_summary = NULL;
 
 	vee_folder_propagate_skipped_changes (vf);
 
 	if (is_folder_unmatched) {
 		expr = g_strdup (expression);
-		folder_unmatched_hash = camel_folder_summary_get_hashtable (((CamelFolder *) folder_unmatched)->summary);
+		folder_unmatched_summary = ((CamelFolder *) folder_unmatched)->summary;
 	} else {
 		expr = g_strdup_printf ("(and %s %s)", vf->expression ? vf->expression : "", expression);
 	}
@@ -1103,7 +1081,7 @@ vee_folder_search_by_expression (CamelFolder *folder,
 					memcpy (vuid, hash, 8);
 					strcpy (vuid + 8, uid);
 
-					if (!is_folder_unmatched || g_hash_table_lookup (folder_unmatched_hash, vuid) != NULL)
+					if (!is_folder_unmatched || camel_folder_summary_check_uid (folder_unmatched_summary, vuid))
 						g_ptr_array_add (result, (gpointer) camel_pstring_strdup (vuid));
 					g_free (vuid);
 				}
@@ -1114,8 +1092,6 @@ vee_folder_search_by_expression (CamelFolder *folder,
 		node = g_list_next (node);
 	}
 
-	if (folder_unmatched_hash)
-		camel_folder_summary_free_hashtable (folder_unmatched_hash);
 	g_free (expr);
 
 	g_hash_table_destroy (searched);
@@ -1330,10 +1306,10 @@ vee_folder_get_message_sync (CamelFolder *folder,
 	CamelVeeMessageInfo *mi;
 	CamelMimeMessage *msg = NULL;
 
-	mi = (CamelVeeMessageInfo *) camel_folder_summary_uid (folder->summary, uid);
+	mi = (CamelVeeMessageInfo *) camel_folder_summary_get (folder->summary, uid);
 	if (mi) {
 		msg = camel_folder_get_message_sync (
-			mi->summary->folder, camel_message_info_uid (mi) + 8,
+			camel_folder_summary_get_folder (mi->orig_summary), camel_message_info_uid (mi) + 8,
 			cancellable, error);
 		camel_message_info_free ((CamelMessageInfo *) mi);
 	} else {
@@ -1426,22 +1402,21 @@ vee_folder_synchronize_sync (CamelFolder *folder,
 		CamelStore *parent_store;
 		const gchar *full_name;
 		GList *del = NULL;
-		gint i, count;
+		gint i;
+		GPtrArray *known_uids;
 
 		camel_folder_summary_prepare_fetch_all (folder->summary, NULL);
-		count = camel_folder_summary_count (folder->summary);
-		for (i = 0; i < count; i++) {
-			CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *) camel_folder_summary_index (folder->summary, i);
+		known_uids = camel_folder_summary_get_array (folder->summary);
+		for (i = 0; known_uids && i < known_uids->len; i++) {
+			CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *) camel_folder_summary_get (folder->summary, g_ptr_array_index (known_uids, i));
 			if (mi->old_flags & CAMEL_MESSAGE_DELETED) {
 				del = g_list_prepend (del, (gpointer) camel_pstring_strdup (((CamelMessageInfo *) mi)->uid));
-				camel_folder_summary_update_counts_by_flags (folder->summary, mi->old_flags, TRUE);
-				camel_folder_summary_remove_index_fast (folder->summary, i);
-				count--;
-				i--;
+				camel_folder_summary_remove_uid (folder->summary, ((CamelMessageInfo *) mi)->uid);
 
 			}
 			camel_message_info_free (mi);
 		}
+		camel_folder_summary_free_array (known_uids);
 
 		full_name = camel_folder_get_full_name (folder);
 		parent_store = camel_folder_get_parent_store (folder);
@@ -1500,7 +1475,7 @@ vee_folder_set_expression (CamelVeeFolder *vee_folder,
 		parent_store = camel_folder_get_parent_store (folder);
 		summary = folder->summary;
 
-		camel_folder_summary_clear (summary);
+		camel_folder_summary_clear (summary, NULL);
 		camel_db_recreate_vfolder (parent_store->cdb_w, full_name, NULL);
 	}
 
@@ -1537,7 +1512,7 @@ static void
 vee_folder_remove_folder_helper (CamelVeeFolder *vf,
                                  CamelFolder *source)
 {
-	gint i, count, n, still = FALSE, start, last;
+	gint i, n, still = FALSE;
 	gchar *oldkey;
 	CamelFolder *folder = (CamelFolder *) vf;
 	gchar hash[8];
@@ -1547,6 +1522,7 @@ vee_folder_remove_folder_helper (CamelVeeFolder *vf,
 	GHashTable *unmatched_uids = vf->parent_vee_store ? vf->parent_vee_store->unmatched_uids : NULL;
 	CamelFolderSummary *ssummary = source->summary;
 	gint killun = FALSE;
+	GPtrArray *known_uids;
 
 	if (vf == folder_unmatched)
 		return;
@@ -1569,58 +1545,36 @@ vee_folder_remove_folder_helper (CamelVeeFolder *vf,
 
 		/* See if we just blow all uid's from this folder away from unmatched, regardless */
 		if (killun) {
-			start = -1;
-			last = -1;
 			camel_folder_summary_prepare_fetch_all (((CamelFolder *) folder_unmatched)->summary, NULL);
-			count = camel_folder_summary_count (((CamelFolder *) folder_unmatched)->summary);
-			for (i = 0; i < count; i++) {
-				CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *) camel_folder_summary_index (((CamelFolder *) folder_unmatched)->summary, i);
+			known_uids = camel_folder_summary_get_array (((CamelFolder *) folder_unmatched)->summary);
+			for (i = 0; known_uids && i < known_uids->len; i++) {
+				CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *)
+					camel_folder_summary_get (((CamelFolder *) folder_unmatched)->summary, g_ptr_array_index (known_uids, i));
 
 				if (mi) {
-					if (mi->summary == ssummary) {
+					if (mi->orig_summary == ssummary) {
 						camel_folder_change_info_remove_uid (folder_unmatched->changes, camel_message_info_uid (mi));
-						camel_folder_summary_update_counts_by_flags (CAMEL_FOLDER (folder_unmatched)->summary, mi->old_flags, TRUE);
-						if (last == -1) {
-							last = start = i;
-						} else if (last + 1 == i) {
-							last = i;
-						} else {
-							camel_folder_summary_remove_range (((CamelFolder *) folder_unmatched)->summary, start, last);
-							i -= (last - start) + 1;
-							start = last = i;
-						}
+						camel_folder_summary_remove_uid (((CamelFolder *) folder_unmatched)->summary, camel_message_info_uid (mi));
 					}
 					camel_message_info_free ((CamelMessageInfo *) mi);
 				}
 			}
-			if (last != -1)
-				camel_folder_summary_remove_range (((CamelFolder *) folder_unmatched)->summary, start, last);
+			camel_folder_summary_free_array (known_uids);
 		}
 	}
 
 	/*FIXME: This can be optimized a lot like, searching for UID in the summary uids */
-	start = -1;
-	last = -1;
 	camel_folder_summary_prepare_fetch_all (folder->summary, NULL);
-	count = camel_folder_summary_count (folder->summary);
-	for (i = 0; i < count; i++) {
-		CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *) camel_folder_summary_index (folder->summary, i);
+	known_uids = camel_folder_summary_get_array (folder->summary);
+	for (i = 0; known_uids && i < known_uids->len; i++) {
+		CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *) camel_folder_summary_get (folder->summary, g_ptr_array_index (known_uids, i));
 		if (mi) {
-			if (mi->summary == ssummary) {
+			if (mi->orig_summary == ssummary) {
 				const gchar *uid = camel_message_info_uid (mi);
 
 				camel_folder_change_info_remove_uid (vf->changes, uid);
-				camel_folder_summary_update_counts_by_flags (folder->summary, mi->old_flags, TRUE);
+				camel_folder_summary_remove_uid (folder->summary, uid);
 
-				if (last == -1) {
-					last = start = i;
-				} else if (last + 1 == i) {
-					last = i;
-				} else {
-					camel_folder_summary_remove_range (folder->summary, start, last);
-					i -= (last - start) + 1;
-					start = last = i;
-				}
 				if ((vf->flags & CAMEL_STORE_FOLDER_PRIVATE) == 0 && folder_unmatched != NULL) {
 					if (still) {
 						if (g_hash_table_lookup_extended (unmatched_uids, uid, (gpointer *) &oldkey, &oldval)) {
@@ -1646,9 +1600,7 @@ vee_folder_remove_folder_helper (CamelVeeFolder *vf,
 			camel_message_info_free ((CamelMessageInfo *) mi);
 		}
 	}
-
-	if (last != -1)
-		camel_folder_summary_remove_range (folder->summary, start, last);
+	camel_folder_summary_free_array (known_uids);
 
 	if (folder_unmatched) {
 		if (camel_folder_change_info_changed (folder_unmatched->changes)) {
@@ -1711,7 +1663,7 @@ vee_folder_rebuild_folder (CamelVeeFolder *vee_folder,
 	GHashTable *allhash, *matchhash, *fullhash;
 	GList *del_list = NULL;
 	CamelFolder *folder = (CamelFolder *) vee_folder;
-	gint i, n, count, start, last;
+	gint i, n, count;
 	struct _update_data u;
 	CamelFolderChangeInfo *vee_folder_changes = NULL, *unmatched_changes = NULL;
 	CamelVeeFolder *folder_unmatched = vee_folder->parent_vee_store ? vee_folder->parent_vee_store->folder_unmatched : NULL;
@@ -1719,6 +1671,7 @@ vee_folder_rebuild_folder (CamelVeeFolder *vee_folder,
 	CamelFolderSummary *ssummary = source->summary;
 	gboolean rebuilded = FALSE;
 	gchar *shash;
+	GPtrArray *known_uids;
 
 	/* Since the source of a correlating vfolder has to be requeried in
 	 * full every time it changes, caching the results in the db is not
@@ -1774,7 +1727,7 @@ vee_folder_rebuild_folder (CamelVeeFolder *vee_folder,
 
 	allhash = g_hash_table_new (g_str_hash, g_str_equal);
 	fullhash = g_hash_table_new (g_str_hash, g_str_equal);
-	all = camel_folder_summary_array (source->summary);
+	all = camel_folder_summary_get_array (source->summary);
 	for (i = 0; i < all->len; i++) {
 		if (g_hash_table_lookup (matchhash, all->pdata[i]) == NULL)
 			g_hash_table_insert (allhash, all->pdata[i], GINT_TO_POINTER (1));
@@ -1800,31 +1753,20 @@ vee_folder_rebuild_folder (CamelVeeFolder *vee_folder,
 	/* scan, looking for "old" uid's to be removed. "old" uid's
 	 * are those that are from previous added sources (not in
 	 * current source) */
-	start = -1;
-	last = -1;
 	camel_folder_summary_prepare_fetch_all (folder->summary, NULL);
-	count = camel_folder_summary_count (folder->summary);
-	for (i = 0; i < count; i++) {
-		CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *) camel_folder_summary_index (folder->summary, i);
+	known_uids = camel_folder_summary_get_array (folder->summary);
+	for (i = 0; known_uids && i < known_uids->len; i++) {
+		CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *) camel_folder_summary_get (folder->summary, g_ptr_array_index (known_uids, i));
 
 		if (mi) {
-			if (mi->summary == ssummary) {
+			if (mi->orig_summary == ssummary) {
 				gchar *uid = (gchar *) camel_message_info_uid (mi), *oldkey;
 				gpointer oldval;
 
 				if (g_hash_table_lookup (matchhash, uid + 8) == NULL) {
-					if (last == -1) {
-						last = start = i;
-					} else if (last + 1 == i) {
-						last = i;
-					} else {
-						camel_folder_summary_remove_range (folder->summary, start, last);
-						i -= (last - start) + 1;
-						count -= (last - start) + 1;
-						start = last = i;
-					}
 					camel_folder_change_info_remove_uid (vee_folder->changes, camel_message_info_uid (mi));
-					camel_folder_summary_update_counts_by_flags (folder->summary, mi->old_flags, TRUE);
+					camel_folder_summary_remove_uid (folder->summary, uid);
+
 					if (!CAMEL_IS_VEE_FOLDER (source)
 					    && unmatched_uids != NULL
 					    && g_hash_table_lookup_extended (unmatched_uids, uid, (gpointer *) &oldkey, &oldval)) {
@@ -1843,8 +1785,7 @@ vee_folder_rebuild_folder (CamelVeeFolder *vee_folder,
 			camel_message_info_free ((CamelMessageInfo *) mi);
 		}
 	}
-	if (last != -1)
-		camel_folder_summary_remove_range (folder->summary, start, last);
+	camel_folder_summary_free_array (known_uids);
 
 	if (rebuilded && !correlating)
 		u.message_uids = g_queue_new ();
@@ -1878,29 +1819,26 @@ vee_folder_rebuild_folder (CamelVeeFolder *vee_folder,
 
 	if (folder_unmatched != NULL) {
 		/* scan unmatched, remove any that have vanished, etc */
-		count = camel_folder_summary_count (((CamelFolder *) folder_unmatched)->summary);
-		for (i = 0; i < count; i++) {
-			gchar *uid = camel_folder_summary_uid_from_index (((CamelFolder *) folder_unmatched)->summary, i);
-
-			if (uid) {
-				if (strncmp (uid, u.hash, 8) == 0) {
-					if (g_hash_table_lookup (allhash, uid + 8) == NULL) {
-						CamelVeeMessageInfo *vinfo = (CamelVeeMessageInfo *) camel_folder_summary_index (CAMEL_FOLDER (folder_unmatched)->summary, i);
-						if (vinfo) {
-							camel_folder_summary_update_counts_by_flags (CAMEL_FOLDER (folder_unmatched)->summary, vinfo->old_flags, TRUE);
-							camel_message_info_free (vinfo);
+		GPtrArray *known_uids;
+
+		known_uids = camel_folder_summary_get_array (((CamelFolder *) folder_unmatched)->summary);
+		if (known_uids != NULL) {
+			for (i = 0; i < known_uids->len; i++) {
+				const gchar *uid = g_ptr_array_index (known_uids, i);
+
+				if (uid) {
+					if (strncmp (uid, u.hash, 8) == 0) {
+						if (g_hash_table_lookup (allhash, uid + 8) == NULL) {
+							/* no longer exists at all, just remove it entirely */
+							camel_folder_summary_remove_uid (((CamelFolder *) folder_unmatched)->summary, uid);
+							camel_folder_change_info_remove_uid (folder_unmatched->changes, uid);
+						} else {
+							g_hash_table_remove (allhash, uid + 8);
 						}
-						/* no longer exists at all, just remove it entirely */
-						camel_folder_summary_remove_index_fast (((CamelFolder *) folder_unmatched)->summary, i);
-						camel_folder_change_info_remove_uid (folder_unmatched->changes, uid);
-						i--;
-						count--;
-					} else {
-						g_hash_table_remove (allhash, uid + 8);
 					}
 				}
-				g_free (uid);
 			}
+			camel_folder_summary_free_array (known_uids);
 		}
 
 		/* now allhash contains all potentially new uid's for the unmatched folder, process */
@@ -1976,7 +1914,7 @@ vee_folder_rebuild_folder (CamelVeeFolder *vee_folder,
 		g_ptr_array_free (match, TRUE);
 	} else
 		camel_folder_search_free (source, match);
-	camel_folder_free_summary (source, all);
+	camel_folder_summary_free_array (all);
 
 	if (unmatched_changes) {
 		camel_folder_changed (
@@ -2466,7 +2404,7 @@ camel_vee_folder_get_location (CamelVeeFolder *vf,
 {
 	CamelFolder *folder;
 
-	folder = vinfo->summary->folder;
+	folder = camel_folder_summary_get_folder (vinfo->orig_summary);
 
 	/* locking?  yes?  no?  although the vfolderinfo is valid when obtained
 	 * the folder in it might not necessarily be so ...? */
diff --git a/camel/camel-vee-summary.c b/camel/camel-vee-summary.c
index 612874c..e638ed7 100644
--- a/camel/camel-vee-summary.c
+++ b/camel/camel-vee-summary.c
@@ -50,7 +50,7 @@ vee_message_info_free (CamelFolderSummary *s,
 	CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *) info;
 
 	camel_pstring_free (info->uid);
-	g_object_unref (mi->summary);
+	g_object_unref (mi->orig_summary);
 }
 
 static CamelMessageInfo *
@@ -62,7 +62,7 @@ vee_message_info_clone (CamelFolderSummary *s,
 
 	to = (CamelVeeMessageInfo *) camel_message_info_new (s);
 
-	to->summary = g_object_ref (from->summary);
+	to->orig_summary = g_object_ref (from->orig_summary);
 	to->info.summary = s;
 	to->info.uid = camel_pstring_strdup (from->info.uid);
 
@@ -79,7 +79,7 @@ vee_info_ptr (const CamelMessageInfo *mi,
 	CamelMessageInfo *rmi;
 	gpointer p;
 
-	rmi = camel_folder_summary_uid (vmi->summary, mi->uid + 8);
+	rmi = camel_folder_summary_get (vmi->orig_summary, mi->uid + 8);
 	HANDLE_NULL_INFO (NULL);
 	p = (gpointer) camel_message_info_ptr (rmi, id);
 	camel_message_info_free (rmi);
@@ -91,7 +91,7 @@ static guint32
 vee_info_uint32 (const CamelMessageInfo *mi,
                  gint id)
 {
-	CamelMessageInfo *rmi = camel_folder_summary_uid (((CamelVeeMessageInfo *) mi)->summary, mi->uid + 8);
+	CamelMessageInfo *rmi = camel_folder_summary_get (((CamelVeeMessageInfo *) mi)->orig_summary, mi->uid + 8);
 	guint32 ret;
 
 	HANDLE_NULL_INFO (0);
@@ -106,7 +106,7 @@ static time_t
 vee_info_time (const CamelMessageInfo *mi,
                gint id)
 {
-	CamelMessageInfo *rmi = camel_folder_summary_uid (((CamelVeeMessageInfo *) mi)->summary, mi->uid + 8);
+	CamelMessageInfo *rmi = camel_folder_summary_get (((CamelVeeMessageInfo *) mi)->orig_summary, mi->uid + 8);
 	time_t ret;
 
 	HANDLE_NULL_INFO (0);
@@ -120,7 +120,7 @@ static gboolean
 vee_info_user_flag (const CamelMessageInfo *mi,
                     const gchar *id)
 {
-	CamelMessageInfo *rmi = camel_folder_summary_uid (((CamelVeeMessageInfo *) mi)->summary, mi->uid + 8);
+	CamelMessageInfo *rmi = camel_folder_summary_get (((CamelVeeMessageInfo *) mi)->orig_summary, mi->uid + 8);
 	gboolean ret;
 
 	HANDLE_NULL_INFO (FALSE);
@@ -134,7 +134,7 @@ static const gchar *
 vee_info_user_tag (const CamelMessageInfo *mi,
                    const gchar *id)
 {
-	CamelMessageInfo *rmi = camel_folder_summary_uid (((CamelVeeMessageInfo *) mi)->summary, mi->uid + 8);
+	CamelMessageInfo *rmi = camel_folder_summary_get (((CamelVeeMessageInfo *) mi)->orig_summary, mi->uid + 8);
 	const gchar *ret;
 
 	HANDLE_NULL_INFO("");
@@ -150,22 +150,23 @@ vee_info_set_user_flag (CamelMessageInfo *mi,
                         gboolean value)
 {
 	gint res = FALSE;
-	CamelVeeFolder *vf = (CamelVeeFolder *) mi->summary->folder;
+	CamelVeeFolder *vf = (CamelVeeFolder *) camel_folder_summary_get_folder (mi->summary);
 
 	if (camel_debug("vfolderexp"))
 		printf (
 			"Expression for vfolder '%s' is '%s'\n",
-			camel_folder_get_full_name (mi->summary->folder),
+			camel_folder_get_full_name (camel_folder_summary_get_folder (mi->summary)),
 			g_strescape (vf->expression, ""));
 
 	if (mi->uid) {
-		CamelMessageInfo *rmi = camel_folder_summary_uid (((CamelVeeMessageInfo *) mi)->summary, mi->uid + 8);
+		CamelMessageInfo *rmi = camel_folder_summary_get (((CamelVeeMessageInfo *) mi)->orig_summary, mi->uid + 8);
+
 		HANDLE_NULL_INFO (FALSE);
 
 		/* ignore changes done in the folder itself,
 		 * unless it's a vTrash or vJunk folder */
 		if (!CAMEL_IS_VTRASH_FOLDER (vf))
-			camel_vee_folder_ignore_next_changed_event (vf, rmi->summary->folder);
+			camel_vee_folder_ignore_next_changed_event (vf, camel_folder_summary_get_folder (rmi->summary));
 
 		res = camel_message_info_set_user_flag (rmi, name, value);
 
@@ -183,13 +184,15 @@ vee_info_set_user_tag (CamelMessageInfo *mi,
 	gint res = FALSE;
 
 	if (mi->uid) {
-		CamelMessageInfo *rmi = camel_folder_summary_uid (((CamelVeeMessageInfo *) mi)->summary, mi->uid + 8);
+		CamelMessageInfo *rmi = camel_folder_summary_get (((CamelVeeMessageInfo *) mi)->orig_summary, mi->uid + 8);
+		CamelFolder *folder = camel_folder_summary_get_folder (mi->summary);
+
 		HANDLE_NULL_INFO (FALSE);
 
 		/* ignore changes done in the folder itself,
 		 * unless it's a vTrash or vJunk folder */
-		if (!CAMEL_IS_VTRASH_FOLDER (mi->summary->folder))
-			camel_vee_folder_ignore_next_changed_event ((CamelVeeFolder *) mi->summary->folder, rmi->summary->folder);
+		if (!CAMEL_IS_VTRASH_FOLDER (folder))
+			camel_vee_folder_ignore_next_changed_event ((CamelVeeFolder *) folder, camel_folder_summary_get_folder (rmi->summary));
 
 		res = camel_message_info_set_user_tag (rmi, name, value);
 		camel_message_info_free (rmi);
@@ -204,47 +207,36 @@ vee_info_set_flags (CamelMessageInfo *mi,
                     guint32 set)
 {
 	gint res = FALSE;
-	CamelVeeFolder *vf = (CamelVeeFolder *) mi->summary->folder;
+	CamelVeeFolder *vf = CAMEL_VEE_FOLDER (camel_folder_summary_get_folder (mi->summary));
 
 	if (camel_debug("vfolderexp"))
 		printf (
 			"Expression for vfolder '%s' is '%s'\n",
-			camel_folder_get_full_name (mi->summary->folder),
+			camel_folder_get_full_name (CAMEL_FOLDER (vf)),
 			g_strescape (vf->expression, ""));
 
+	/* first update original message info... */
 	if (mi->uid) {
-		CamelMessageInfo *rmi = camel_folder_summary_uid (((CamelVeeMessageInfo *) mi)->summary, mi->uid + 8);
+		CamelMessageInfo *rmi = camel_folder_summary_get (((CamelVeeMessageInfo *) mi)->orig_summary, mi->uid + 8);
 
 		HANDLE_NULL_INFO (FALSE);
 
-		camel_folder_summary_update_counts_by_flags (mi->summary, camel_message_info_flags (rmi), TRUE);
-
 		/* ignore changes done in the folder itself,
 		 * unless it's a vTrash or vJunk folder */
 		if (!CAMEL_IS_VTRASH_FOLDER (vf))
-			camel_vee_folder_ignore_next_changed_event (vf, rmi->summary->folder);
+			camel_vee_folder_ignore_next_changed_event (vf, camel_folder_summary_get_folder (rmi->summary));
 
-		camel_folder_freeze (rmi->summary->folder);
+		camel_folder_freeze (camel_folder_summary_get_folder (rmi->summary));
 		res = camel_message_info_set_flags (rmi, flags, set);
 		((CamelVeeMessageInfo *) mi)->old_flags = camel_message_info_flags (rmi);
-		camel_folder_thaw (rmi->summary->folder);
-
-		/* Keep the summary in sync */
-		camel_folder_summary_update_counts_by_flags (mi->summary, camel_message_info_flags (rmi), FALSE);
-
-		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));
-
-		if (res && mi->summary && mi->summary->folder) {
-			CamelFolderChangeInfo *changes = camel_folder_change_info_new ();
-
-			camel_folder_change_info_change_uid (changes, camel_message_info_uid (mi));
-			camel_folder_changed (mi->summary->folder, changes);
-			camel_folder_change_info_free (changes);
-		}
+		camel_folder_thaw (camel_folder_summary_get_folder (rmi->summary));
 
 		camel_message_info_free (rmi);
 	}
 
+	if (res)
+		CAMEL_FOLDER_SUMMARY_CLASS (camel_vee_summary_parent_class)->info_set_flags (mi, flags, set);
+
 	return res;
 }
 
@@ -254,17 +246,7 @@ message_info_from_uid (CamelFolderSummary *s,
 {
 	CamelMessageInfo *info;
 
-	/* FIXME[disk-summary] too bad design. Need to peek it from cfs
-	 * instead of hacking ugly like this */
-	camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
-
-	info = g_hash_table_lookup (s->loaded_infos, uid);
-
-	if (info)
-		camel_message_info_ref (info);
-
-	camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
-
+	info = camel_folder_summary_peek_loaded (s, uid);
 	if (!info) {
 		CamelVeeMessageInfo *vinfo;
 		gchar tmphash[9];
@@ -275,7 +257,8 @@ message_info_from_uid (CamelFolderSummary *s,
 		 * 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));
+			d(g_message ("Unable to find %s in the summary of %s", uid,
+				camel_folder_get_full_name (camel_folder_summary_get_folder (s->folder))));
 			return NULL;
 		}
 
@@ -287,10 +270,11 @@ message_info_from_uid (CamelFolderSummary *s,
 		info->uid = camel_pstring_strdup (uid);
 		strncpy (tmphash, uid, 8);
 		tmphash[8] = 0;
-		vinfo->summary = g_hash_table_lookup (((CamelVeeFolder *) s->folder)->hashes, tmphash);
-		g_object_ref (vinfo->summary);
+		vinfo->orig_summary = g_hash_table_lookup (((CamelVeeFolder *) camel_folder_summary_get_folder (s))->hashes, tmphash);
+		g_object_ref (vinfo->orig_summary);
 		camel_folder_summary_insert (s, info, FALSE);
 	}
+
 	return info;
 }
 
@@ -336,17 +320,13 @@ camel_vee_summary_new (CamelFolder *parent)
 	CamelStore *parent_store;
 	const gchar *full_name;
 
-	s = g_object_new (CAMEL_TYPE_VEE_SUMMARY, NULL);
-	s->summary.folder = parent;
+	s = g_object_new (CAMEL_TYPE_VEE_SUMMARY, "folder", parent, NULL);
 
-        /* FIXME[disk-summary] fix exceptions and note return values */
-	/* FIXME[disk-summary] if Evo's junk/trash vfolders make it VJunk
-	 * VTrash instead of .#evolution/Junk-or-whatever */
 	full_name = camel_folder_get_full_name (parent);
 	parent_store = camel_folder_get_parent_store (parent);
 	camel_db_create_vfolder (parent_store->cdb_w, full_name, NULL);
 
-	return &s->summary;
+	return (CamelFolderSummary *) s;
 }
 
 /**
@@ -365,8 +345,8 @@ camel_vee_summary_get_ids (CamelVeeSummary *summary,
 	const gchar *full_name;
 
 	/* FIXME[disk-summary] fix exception passing */
-	full_name = camel_folder_get_full_name (cfs->folder);
-	parent_store = camel_folder_get_parent_store (cfs->folder);
+	full_name = camel_folder_get_full_name (camel_folder_summary_get_folder (cfs));
+	parent_store = camel_folder_get_parent_store (camel_folder_summary_get_folder (cfs));
 	array = camel_db_get_vuids_from_vfolder (parent_store->cdb_r, full_name, shash, NULL);
 
 	g_free (shash);
@@ -387,36 +367,30 @@ camel_vee_summary_add (CamelVeeSummary *s,
 	memcpy (vuid, hash, 8);
 	strcpy (vuid + 8, uid);
 
-	camel_folder_summary_lock (CAMEL_FOLDER_SUMMARY (s), CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
-	mi = (CamelVeeMessageInfo *) g_hash_table_lookup (((CamelFolderSummary *) s)->loaded_infos, vuid);
-	camel_folder_summary_unlock (CAMEL_FOLDER_SUMMARY (s), CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
-
+	mi = (CamelVeeMessageInfo *) camel_folder_summary_peek_loaded (&s->summary, vuid);
 	if (mi) {
 		/* Possible that the entry is loaded, see if it has the summary */
 		d(g_message ("%s - already there\n", vuid));
 		g_free (vuid);
-		if (!mi->summary)
-			mi->summary = g_object_ref (summary);
-
-		camel_message_info_ref (mi);
+		if (!mi->orig_summary)
+			mi->orig_summary = g_object_ref (summary);
 		return mi;
 	}
 
 	mi = (CamelVeeMessageInfo *) camel_message_info_new (&s->summary);
-	mi->summary = g_object_ref (summary);
+	mi->orig_summary = g_object_ref (summary);
 	mi->info.uid = (gchar *) camel_pstring_strdup (vuid);
 	g_free (vuid);
 	camel_message_info_ref (mi);
 
 	/* Get actual flags and store it */
-	rmi = camel_folder_summary_uid (summary, uid);
+	rmi = camel_folder_summary_get (summary, uid);
 	if (rmi) {
 		mi->old_flags = camel_message_info_flags (rmi);
 		camel_message_info_free (rmi);
 	}
 
 	camel_folder_summary_insert (&s->summary, (CamelMessageInfo *) mi, FALSE);
-	camel_folder_summary_update_counts_by_flags (&s->summary, camel_message_info_flags (mi), FALSE);
 
 	return mi;
 }
diff --git a/camel/camel-vee-summary.h b/camel/camel-vee-summary.h
index 688dcf9..2667e7a 100644
--- a/camel/camel-vee-summary.h
+++ b/camel/camel-vee-summary.h
@@ -59,8 +59,8 @@ typedef struct _CamelVeeSummaryClass CamelVeeSummaryClass;
 typedef struct _CamelVeeMessageInfo CamelVeeMessageInfo;
 
 struct _CamelVeeMessageInfo {
-	CamelMessageInfo info;
-	CamelFolderSummary *summary;
+	CamelMessageInfoBase info;
+	CamelFolderSummary *orig_summary;
 	guint32 old_flags;  /* These are just for identifying changed flags */
 };
 
diff --git a/camel/camel-vtrash-folder.c b/camel/camel-vtrash-folder.c
index f3a5038..fff4a39 100644
--- a/camel/camel-vtrash-folder.c
+++ b/camel/camel-vtrash-folder.c
@@ -171,18 +171,18 @@ vtrash_folder_transfer_messages_to_sync (CamelFolder *source,
 			continue;
 		}
 
-		if (dest == mi->summary->folder) {
+		if (dest == camel_folder_summary_get_folder (mi->orig_summary)) {
 			/* Just unset the flag on the original message */
 			camel_folder_set_message_flags (
 				source, uids->pdata[i], sbit, 0);
 		} else {
 			if (batch == NULL)
 				batch = g_hash_table_new (NULL, NULL);
-			md = g_hash_table_lookup (batch, mi->summary->folder);
+			md = g_hash_table_lookup (batch, camel_folder_summary_get_folder (mi->orig_summary));
 			if (md == NULL) {
 				md = g_malloc0 (sizeof (*md));
 				md->cancellable = cancellable;
-				md->folder = g_object_ref (mi->summary->folder);
+				md->folder = g_object_ref (camel_folder_summary_get_folder (mi->orig_summary));
 				md->uids = g_ptr_array_new ();
 				md->dest = dest;
 				md->delete = delete_originals;
@@ -192,7 +192,7 @@ vtrash_folder_transfer_messages_to_sync (CamelFolder *source,
 				if (cancellable != NULL)
 					g_object_ref (cancellable);
 				camel_folder_freeze (md->folder);
-				g_hash_table_insert (batch, mi->summary->folder, md);
+				g_hash_table_insert (batch, camel_folder_summary_get_folder (mi->orig_summary), md);
 			}
 
 			/* unset the bit temporarily */
diff --git a/camel/providers/imap/camel-imap-folder.c b/camel/providers/imap/camel-imap-folder.c
index d419e27..97b05f1 100644
--- a/camel/providers/imap/camel-imap-folder.c
+++ b/camel/providers/imap/camel-imap-folder.c
@@ -192,6 +192,7 @@ static void
 imap_folder_dispose (GObject *object)
 {
 	CamelImapFolder *imap_folder;
+	CamelStore *parent_store;
 
 	imap_folder = CAMEL_IMAP_FOLDER (object);
 
@@ -216,6 +217,13 @@ imap_folder_dispose (GObject *object)
 		imap_folder->journal = NULL;
 	}
 
+	parent_store = camel_folder_get_parent_store (CAMEL_FOLDER (imap_folder));
+	if (parent_store) {
+		camel_store_summary_disconnect_folder_summary (
+			(CamelStoreSummary *) ((CamelImapStore *) parent_store)->summary,
+			CAMEL_FOLDER (imap_folder)->summary);
+	}
+
 	/* Chain up to parent's dispose() method. */
 	G_OBJECT_CLASS (camel_imap_folder_parent_class)->dispose (object);
 }
@@ -488,6 +496,10 @@ camel_imap_folder_new (CamelStore *parent,
 
 	imap_folder->search = camel_imap_search_new (folder_dir);
 
+	camel_store_summary_connect_folder_summary (
+		(CamelStoreSummary *) ((CamelImapStore *) parent)->summary,
+		folder_name, folder->summary);
+
 	return folder;
 }
 
@@ -557,7 +569,7 @@ camel_imap_folder_selected (CamelFolder *folder,
 	CamelMessageFlags perm_flags = 0;
 	GData *fetch_data;
 	gint i, count;
-	gchar *resp, *old_uid;
+	gchar *resp;
 
 	count = camel_folder_summary_count (folder->summary);
 
@@ -599,7 +611,7 @@ camel_imap_folder_selected (CamelFolder *folder,
 		imap_summary->validity = validity;
 	else if (validity != imap_summary->validity) {
 		imap_summary->validity = validity;
-		camel_folder_summary_clear (folder->summary);
+		camel_folder_summary_clear (folder->summary, NULL);
 		CAMEL_IMAP_FOLDER_REC_LOCK (imap_folder, cache_lock);
 		camel_imap_message_cache_clear (imap_folder->cache);
 		CAMEL_IMAP_FOLDER_REC_UNLOCK (imap_folder, cache_lock);
@@ -614,6 +626,8 @@ camel_imap_folder_selected (CamelFolder *folder,
 	else if (count != 0 && !imap_folder->need_rescan) {
 		CamelStore *parent_store;
 		CamelImapStore *store;
+		GPtrArray *known_uids;
+		const gchar *old_uid;
 
 		parent_store = camel_folder_get_parent_store (folder);
 		store = CAMEL_IMAP_STORE (parent_store);
@@ -649,13 +663,17 @@ camel_imap_folder_selected (CamelFolder *folder,
 		}
 		camel_imap_response_free_without_processing (store, response);
 
-		old_uid = camel_folder_summary_uid_from_index (folder->summary, count - 1);
+		known_uids = camel_folder_summary_get_array (folder->summary);
+		camel_folder_sort_uids (folder, known_uids);
+		old_uid = NULL;
+		if (known_uids && count - 1 >= 0 && count - 1 < known_uids->len)
+			old_uid = g_ptr_array_index (known_uids, count - 1);
 		if (old_uid) {
 			val = strtoul (old_uid, NULL, 10);
-			g_free (old_uid);
 			if (uid == 0 || uid != val)
 				imap_folder->need_rescan = TRUE;
 		}
+		camel_folder_summary_free_array (known_uids);
 	}
 
 	/* Now rescan if we need to */
@@ -882,7 +900,7 @@ imap_refresh_info_sync (CamelFolder *folder,
 		guint32 unread, total;
 
 		total = camel_folder_summary_count (folder->summary);
-		unread = folder->summary->unread_count;
+		unread = camel_folder_summary_get_unread_count (folder->summary);
 
 		if (si->total != total
 		    || si->unread != unread) {
@@ -905,7 +923,7 @@ imap_refresh_info_sync (CamelFolder *folder,
 			if (get_folder_status (folder, &server_total, &server_unread, cancellable, &local_error)) {
 
 				total = camel_folder_summary_count (folder->summary);
-				unread = folder->summary->unread_count;
+				unread = camel_folder_summary_get_unread_count (folder->summary);
 
 				if (total != server_total || unread != server_unread)
 					check_rescan = 1;
@@ -1035,6 +1053,7 @@ imap_rescan (CamelFolder *folder,
 	gboolean ok;
 	CamelFolderChangeInfo *changes = NULL;
 	gboolean success;
+	GPtrArray *known_uids;
 
 	parent_store = camel_folder_get_parent_store (folder);
 	store = CAMEL_IMAP_STORE (parent_store);
@@ -1044,8 +1063,10 @@ imap_rescan (CamelFolder *folder,
 
 	imap_folder->need_rescan = FALSE;
 
-	summary_len = camel_folder_summary_count (folder->summary);
+	known_uids = camel_folder_summary_get_array (folder->summary);
+	summary_len = known_uids ? known_uids->len : 0;
 	if (summary_len == 0) {
+		camel_folder_summary_free_array (known_uids);
 		if (exists)
 			return camel_imap_folder_changed (
 				folder, exists, NULL, cancellable, error);
@@ -1056,19 +1077,22 @@ imap_rescan (CamelFolder *folder,
 	camel_operation_push_message (
 		cancellable, _("Scanning for changed messages in %s"),
 		camel_folder_get_display_name (folder));
-	uid = camel_folder_summary_uid_from_index (folder->summary, summary_len - 1);
 
+	camel_folder_sort_uids (folder, known_uids);
+
+	uid = g_ptr_array_index (known_uids, summary_len - 1);
 	if (!uid) {
 		camel_operation_pop_message (cancellable);
+		camel_folder_summary_free_array (known_uids);
 		return TRUE;
 	}
 
 	ok = camel_imap_command_start (
 		store, folder, cancellable, error,
 		"UID FETCH 1:%s (FLAGS)", uid);
-	g_free (uid);
 	if (!ok) {
 		camel_operation_pop_message (cancellable);
+		camel_folder_summary_free_array (known_uids);
 		return FALSE;
 	}
 
@@ -1110,6 +1134,7 @@ imap_rescan (CamelFolder *folder,
 		g_free (new);
 		g_free (resp);
 
+		camel_folder_summary_free_array (known_uids);
 		return TRUE;
 	}
 
@@ -1126,6 +1151,7 @@ imap_rescan (CamelFolder *folder,
 		if (type != CAMEL_IMAP_RESPONSE_ERROR && type != CAMEL_IMAP_RESPONSE_TAGGED)
 			camel_service_unlock (CAMEL_SERVICE (store), CAMEL_SERVICE_REC_CONNECT_LOCK);
 
+		camel_folder_summary_free_array (known_uids);
 		return TRUE;
 	}
 
@@ -1146,12 +1172,11 @@ imap_rescan (CamelFolder *folder,
 	for (i = 0, j = 0; i < summary_len && new[j].uid; i++) {
 		gboolean changed = FALSE;
 
-		uid = camel_folder_summary_uid_from_index (folder->summary, i);
-
+		uid = g_ptr_array_index (known_uids, i);
 		if (!uid)
 			continue;
 
-		info = camel_folder_summary_uid (folder->summary, uid);
+		info = camel_folder_summary_get (folder->summary, uid);
 		if (!info) {
 			if (g_getenv("CRASH_IMAP")) { /* Debug logs to tackle on hard to get imap crasher */
 				printf ("CRASH: %s: %s",
@@ -1164,40 +1189,6 @@ imap_rescan (CamelFolder *folder,
 		iinfo = (CamelImapMessageInfo *) info;
 
 		if (strcmp (uid, new[j].uid) != 0) {
-			g_free (uid);
-
-			/* these will be deleted from db in a moment. So adjust the counts please */
-			if (info) {
-				CamelMessageInfoBase *dinfo = (CamelMessageInfoBase *) info;
-				gint unread = 0, deleted = 0, junk = 0;
-				guint32 flags;
-
-				flags = dinfo->flags;
-				if (!(flags & CAMEL_MESSAGE_SEEN))
-					unread = 1;
-
-				if (flags & CAMEL_MESSAGE_DELETED)
-					deleted = 1;
-
-				if (flags & CAMEL_MESSAGE_JUNK)
-					junk = 1;
-
-				if (unread)
-					folder->summary->unread_count--;
-
-				if (deleted)
-					folder->summary->deleted_count--;
-				if (junk)
-					folder->summary->junk_count--;
-
-				if (junk && !deleted)
-					folder->summary->junk_not_deleted_count--;
-
-				if (!junk &&  !deleted)
-					folder->summary->visible_count--;
-
-				folder->summary->saved_count--;
-			}
 			seq = i + 1 - del;
 			del++;
 			g_array_append_val (removed, seq);
@@ -1205,49 +1196,18 @@ imap_rescan (CamelFolder *folder,
 			continue;
 		}
 
-		g_free (uid);
-
 		/* Update summary flags */
 
 		if (new[j].flags != iinfo->server_flags) {
 			guint32 server_set, server_cleared;
-			gint read = 0, deleted = 0, junk = 0;
 
 			server_set = new[j].flags & ~iinfo->server_flags;
 			server_cleared = iinfo->server_flags & ~new[j].flags;
 
-			if (server_set & CAMEL_MESSAGE_SEEN)
-				read = 1;
-			else if (server_cleared & CAMEL_MESSAGE_SEEN)
-				read = -1;
-
-			if (server_set & CAMEL_MESSAGE_DELETED)
-				deleted = 1;
-			else if (server_cleared & CAMEL_MESSAGE_DELETED)
-				deleted = -1;
-
-			if (server_set & CAMEL_MESSAGE_JUNK)
-				junk = 1;
-			else if (server_cleared & CAMEL_MESSAGE_JUNK)
-				junk = -1;
-
-			d(printf("%s %s %s %s\n", iinfo->info.uid, read == 1 ? "read" : ( read == -1 ? "unread" : ""),
-				 deleted == 1 ? "deleted" : ( deleted == -1 ? "undeleted" : ""),
-				 junk == 1 ? "junk" : ( junk == -1 ? "unjunked" : "")));
-
-			if (read)
-				folder->summary->unread_count -= read;
-			if (deleted)
-				folder->summary->deleted_count += deleted;
-			if (junk)
-				folder->summary->junk_count += junk;
-			if (junk && !deleted)
-				folder->summary->junk_not_deleted_count += junk;
-			if (junk ||  deleted)
-				folder->summary->visible_count -= junk ? junk : deleted;
-
-			iinfo->info.flags = (iinfo->info.flags | server_set) & ~server_cleared;
+			camel_message_info_set_flags ((CamelMessageInfo *) iinfo, server_set | server_cleared, (iinfo->info.flags | server_set) & ~server_cleared);
 			iinfo->server_flags = new[j].flags;
+			/* unset folder_flagged, because these are flags received froma server */
+			iinfo->info.flags = iinfo->info.flags & (~CAMEL_MESSAGE_FOLDER_FLAGGED);
 			iinfo->info.dirty = TRUE;
 			if (info->summary)
 				camel_folder_summary_touch (info->summary);
@@ -1297,41 +1257,8 @@ imap_rescan (CamelFolder *folder,
 	 */
 
 	for (i = seq; i <= summary_len; i++) {
-		CamelMessageInfoBase *dinfo;
 		gint j;
-		dinfo = (CamelMessageInfoBase *) camel_folder_summary_index (folder->summary, i - 1);
-		if (dinfo) {
-			/* these will be deleted from db in a moment. So adjust the counts please */
-			gint unread = 0, deleted = 0, junk = 0;
-			guint32 flags;
-
-			flags = dinfo->flags;
-			if (!(flags & CAMEL_MESSAGE_SEEN))
-				unread = 1;
 
-			if (flags & CAMEL_MESSAGE_DELETED)
-				deleted = 1;
-
-			if (flags & CAMEL_MESSAGE_JUNK)
-				junk = 1;
-
-			if (unread)
-				folder->summary->unread_count--;
-
-			if (deleted)
-				folder->summary->deleted_count--;
-			if (junk)
-				folder->summary->junk_count--;
-
-			if (junk && !deleted)
-				folder->summary->junk_not_deleted_count--;
-
-			if (!junk &&  !deleted)
-				folder->summary->visible_count--;
-
-			folder->summary->saved_count--;
-			camel_message_info_free (dinfo);
-		}
 		j = seq - del;
 		g_array_append_val (removed, j);
 	}
@@ -1341,6 +1268,7 @@ imap_rescan (CamelFolder *folder,
 		folder, exists, removed, cancellable, error);
 	g_array_free (removed, TRUE);
 
+	camel_folder_summary_free_array (known_uids);
 	return success;
 }
 
@@ -1413,7 +1341,7 @@ get_matching (CamelFolder *folder,
 		uid = summary->pdata[i];
 
 		if (uid) {
-			info = (CamelImapMessageInfo *) camel_folder_summary_uid (folder->summary, uid);
+			info = (CamelImapMessageInfo *) camel_folder_summary_get (folder->summary, uid);
 		} else
 			continue;
 
@@ -1541,9 +1469,9 @@ imap_sync_offline (CamelFolder *folder,
 		full_name = camel_folder_get_full_name (folder);
 		si = camel_store_summary_path ((CamelStoreSummary *)((CamelImapStore *) parent_store)->summary, full_name);
 		if (si) {
-			if (si->total != folder->summary->saved_count || si->unread != folder->summary->unread_count) {
-				si->total = folder->summary->saved_count;
-				si->unread = folder->summary->unread_count;
+			if (si->total != camel_folder_summary_get_saved_count (folder->summary) || si->unread != camel_folder_summary_get_unread_count (folder->summary)) {
+				si->total = camel_folder_summary_get_saved_count (folder->summary);
+				si->unread = camel_folder_summary_get_unread_count (folder->summary);
 				camel_store_summary_touch ((CamelStoreSummary *)((CamelImapStore *) parent_store)->summary);
 			}
 
@@ -1720,7 +1648,7 @@ imap_synchronize_sync (CamelFolder *folder,
 		if (!uid) /* Possibly it was sync by matching flags, which we NULLify */
 			continue;
 
-		if (!(info = (CamelImapMessageInfo *) camel_folder_summary_uid (folder->summary, uid))) {
+		if (!(info = (CamelImapMessageInfo *) camel_folder_summary_get (folder->summary, uid))) {
 			continue;
 		}
 
@@ -1922,7 +1850,7 @@ imap_expunge_uids_offline (CamelFolder *folder,
 	changes = camel_folder_change_info_new ();
 
 	for (i = 0; i < uids->len; i++) {
-		camel_folder_summary_remove_uid_fast (folder->summary, uids->pdata[i]);
+		camel_folder_summary_remove_uid (folder->summary, uids->pdata[i]);
 		camel_folder_change_info_remove_uid (changes, uids->pdata[i]);
 		list = g_list_prepend (list, (gpointer) uids->pdata[i]);
 		/* We intentionally don't remove it from the cache because
@@ -2025,7 +1953,7 @@ imap_expunge_uids_online (CamelFolder *folder,
 
 	changes = camel_folder_change_info_new ();
 	for (i = 0; i < uids->len; i++) {
-		camel_folder_summary_remove_uid_fast (folder->summary, uids->pdata[i]);
+		camel_folder_summary_remove_uid (folder->summary, uids->pdata[i]);
 		camel_folder_change_info_remove_uid (changes, uids->pdata[i]);
 		list = g_list_prepend (list, (gpointer) uids->pdata[i]);
 		/* We intentionally don't remove it from the cache because
@@ -2050,7 +1978,7 @@ imap_expunge_sync (CamelFolder *folder,
 	CamelStore *parent_store;
 	GPtrArray *uids = NULL;
 	const gchar *full_name;
-	gboolean success;
+	gboolean success, real_trash = FALSE;
 
 	full_name = camel_folder_get_full_name (folder);
 	parent_store = camel_folder_get_parent_store (folder);
@@ -2066,7 +1994,8 @@ imap_expunge_sync (CamelFolder *folder,
 
 		if (local_error == NULL && trash && (folder == trash || g_ascii_strcasecmp (full_name, camel_folder_get_full_name (trash)) == 0)) {
 			/* it's a real trash folder, thus get all mails from there */
-			uids = camel_folder_summary_array (folder->summary);
+			real_trash = TRUE;
+			uids = camel_folder_summary_get_array (folder->summary);
 		}
 
 		if (local_error != NULL)
@@ -2086,8 +2015,12 @@ imap_expunge_sync (CamelFolder *folder,
 		success = imap_expunge_uids_offline (
 			folder, uids, cancellable, error);
 
-	g_ptr_array_foreach (uids, (GFunc) camel_pstring_free, NULL);
-	g_ptr_array_free (uids, TRUE);
+	if (real_trash) {
+		camel_folder_summary_free_array (uids);
+	} else {
+		g_ptr_array_foreach (uids, (GFunc) camel_pstring_free, NULL);
+		g_ptr_array_free (uids, TRUE);
+	}
 
 	return success;
 }
@@ -2616,7 +2549,7 @@ imap_transfer_offline (CamelFolder *source,
 
 		destuid = get_temp_uid ();
 
-		mi = camel_folder_summary_uid (source->summary, uid);
+		mi = camel_folder_summary_get (source->summary, uid);
 		g_return_val_if_fail (mi != NULL, FALSE);
 
 		message = camel_folder_get_message_sync (
@@ -2892,7 +2825,7 @@ do_copy (CamelFolder *source,
 				camel_folder_delete_message (
 					source, uids->pdata[i]);
 				if (mark_moved) {
-					CamelMessageInfoBase *info = (CamelMessageInfoBase *) camel_folder_summary_uid (source->summary, uids->pdata[i]);
+					CamelMessageInfoBase *info = (CamelMessageInfoBase *) camel_folder_summary_get (source->summary, uids->pdata[i]);
 
 					if (info)
 						info->flags |= CAMEL_MESSAGE_IMAP_MOVED;
@@ -3515,7 +3448,7 @@ imap_folder_summary_uid_or_error (CamelFolderSummary *summary,
                                   GError **error)
 {
 	CamelImapMessageInfo *mi;
-	mi = (CamelImapMessageInfo *) camel_folder_summary_uid (summary, uid);
+	mi = (CamelImapMessageInfo *) camel_folder_summary_get (summary, uid);
 	if (mi == NULL) {
 		g_set_error (
 			error, CAMEL_FOLDER_ERROR,
@@ -3570,7 +3503,7 @@ imap_get_message_sync (CamelFolder *folder,
 		    || store->braindamaged
 		    || mi->info.size < IMAP_SMALL_BODY_SIZE
 		    || (!content_info_incomplete (mi->info.content) && !mi->info.content->childs)) {
-			CamelMessageInfoBase *info = (CamelMessageInfoBase *) camel_folder_summary_uid (folder->summary, uid);
+			CamelMessageInfoBase *info = (CamelMessageInfoBase *) camel_folder_summary_get (folder->summary, uid);
 			msg = get_message_simple (imap_folder, uid, NULL, cancellable, &local_error);
 			if (info && !info->preview && msg && camel_folder_summary_get_need_preview (folder->summary)) {
 				if (camel_mime_message_build_preview ((CamelMimePart *) msg, (CamelMessageInfo *) info) && info->preview)
@@ -3650,7 +3583,7 @@ imap_get_message_sync (CamelFolder *folder,
 			else
 				msg = get_message (imap_folder, uid, mi->info.content, cancellable, &local_error);
 			if (msg && camel_folder_summary_get_need_preview (folder->summary)) {
-				CamelMessageInfoBase *info = (CamelMessageInfoBase *) camel_folder_summary_uid (folder->summary, uid);
+				CamelMessageInfoBase *info = (CamelMessageInfoBase *) camel_folder_summary_get (folder->summary, uid);
 				if (info && !info->preview) {
 					if (camel_mime_message_build_preview ((CamelMimePart *) msg, (CamelMessageInfo *) info) && info->preview)
 						camel_folder_summary_add_preview (folder->summary, (CamelMessageInfo *) info);
@@ -3950,41 +3883,6 @@ construct_junk_headers (gchar *header,
 	}
 }
 
-static void
-update_summary (CamelFolderSummary *summary,
-                CamelMessageInfoBase *info)
-{
-	gint unread = 0, deleted = 0, junk = 0;
-	guint32 flags = info->flags;
-
-	if (!(flags & CAMEL_MESSAGE_SEEN))
-		unread = 1;
-
-	if (flags & CAMEL_MESSAGE_DELETED)
-		deleted = 1;
-
-	if (flags & CAMEL_MESSAGE_JUNK)
-		junk = 1;
-
-	if (summary) {
-
-		if (unread)
-			summary->unread_count += unread;
-		if (deleted)
-			summary->deleted_count += deleted;
-		if (junk)
-			summary->junk_count += junk;
-		if (junk && !deleted)
-			summary->junk_not_deleted_count += junk;
-		summary->visible_count++;
-		if (junk ||  deleted)
-			summary->visible_count -= junk ? junk : deleted;
-
-		summary->saved_count++;
-		camel_folder_summary_touch (summary);
-	}
-}
-
 #define CAMEL_MESSAGE_INFO_HEADERS "DATE FROM TO CC SUBJECT REFERENCES IN-REPLY-TO MESSAGE-ID MIME-VERSION CONTENT-TYPE CONTENT-CLASS X-CALENDAR-ATTACHMENT "
 
 /* FIXME: this needs to be kept in sync with camel-mime-utils.c's list
@@ -4067,11 +3965,19 @@ imap_update_summary (CamelFolder *folder,
 	seq = camel_folder_summary_count (folder->summary);
 	first = seq + 1;
 	if (seq > 0) {
-		tempuid = camel_folder_summary_uid_from_index (folder->summary, seq -1 );
+		GPtrArray *known_uids;
 
-		if (tempuid) {
-			uidval = strtoul (tempuid, NULL, 10);
-			g_free (tempuid);
+		known_uids = camel_folder_summary_get_array (folder->summary);
+		if (known_uids) {
+			camel_folder_sort_uids (folder, known_uids);
+
+			tempuid = g_ptr_array_index (known_uids, seq - 1);
+			if (tempuid)
+				uidval = strtoul (tempuid, NULL, 10);
+			else
+				uidval = 0;
+
+			camel_folder_summary_free_array (known_uids);
 		} else
 			uidval = 0;
 	} else
@@ -4322,7 +4228,7 @@ imap_update_summary (CamelFolder *folder,
 
 		/* FIXME: If it enters if (info) it will always match the exception. So stupid */
 		/* FIXME[disk-summary] Use a db query to see if the DB exists */
-/*		info = (CamelImapMessageInfo *)camel_folder_summary_uid(folder->summary, uid); */
+/*		info = (CamelImapMessageInfo *)camel_folder_summary_get (folder->summary, uid); */
 /*		if (info) { */
 /*			for (seq = 0; seq < camel_folder_summary_count (folder->summary); seq++) { */
 /*				if (folder->summary->messages->pdata[seq] == info) */
@@ -4333,7 +4239,6 @@ imap_update_summary (CamelFolder *folder,
 		if (((CamelMessageInfoBase *) mi)->summary)
 			camel_folder_summary_touch (((CamelMessageInfoBase *) mi)->summary);
 		camel_folder_summary_add (folder->summary, (CamelMessageInfo *) mi);
-		update_summary (folder->summary, (CamelMessageInfoBase *) mi);
 		camel_folder_change_info_add_uid (changes, camel_message_info_uid (mi));
 
 		/* Report all new messages as recent, even without that flag, thus new
@@ -4389,7 +4294,6 @@ camel_imap_folder_changed (CamelFolder *folder,
 	CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder);
 	CamelFolderChangeInfo *changes;
 	gint len;
-	gchar *uid;
 	gboolean success = TRUE;
 
 	changes = camel_folder_change_info_new ();
@@ -4398,30 +4302,35 @@ camel_imap_folder_changed (CamelFolder *folder,
 		gint i, id;
 		GList *deleted = NULL;
 		const gchar *full_name;
+		const gchar *uid;
+		GPtrArray *known_uids;
 
+		known_uids = camel_folder_summary_get_array (folder->summary);
+		camel_folder_sort_uids (folder, known_uids);
 		for (i = 0; i < expunged->len; i++) {
 			id = g_array_index (expunged, int, i);
-			uid = camel_folder_summary_uid_from_index (folder->summary, id - 1);
+			uid = id - 1 + i >= 0 && id - 1 + i < known_uids->len ? g_ptr_array_index (known_uids, id - 1 + i) : NULL;
 			if (uid == NULL) {
 				/* FIXME: danw: does this mean that the summary is corrupt? */
 				/* I guess a message that we never retrieved got expunged? */
 				continue;
 			}
 
-			deleted = g_list_prepend (deleted, uid);
+			deleted = g_list_prepend (deleted, (gpointer) uid);
 			camel_folder_change_info_remove_uid (changes, uid);
 			CAMEL_IMAP_FOLDER_REC_LOCK (imap_folder, cache_lock);
 			camel_imap_message_cache_remove (imap_folder->cache, uid);
 			CAMEL_IMAP_FOLDER_REC_UNLOCK (imap_folder, cache_lock);
-			camel_folder_summary_remove_index_fast (folder->summary, id - 1);
+			camel_folder_summary_remove_uid (folder->summary, uid);
 		}
 
 		/* Delete all in one transaction */
 		full_name = camel_folder_get_full_name (folder);
 		parent_store = camel_folder_get_parent_store (folder);
 		camel_db_delete_uids (parent_store->cdb_w, full_name, deleted, NULL);
-		g_list_foreach (deleted, (GFunc) g_free, NULL);
 		g_list_free (deleted);
+
+		camel_folder_summary_free_array (known_uids);
 	}
 
 	len = camel_folder_summary_count (folder->summary);
diff --git a/camel/providers/imap/camel-imap-message-cache.c b/camel/providers/imap/camel-imap-message-cache.c
index 8a121a4..be9ec8f 100644
--- a/camel/providers/imap/camel-imap-message-cache.c
+++ b/camel/providers/imap/camel-imap-message-cache.c
@@ -190,7 +190,6 @@ camel_imap_message_cache_new (const gchar *path,
 	const gchar *dname;
 	gchar *uid, *p;
 	GPtrArray *deletes;
-	GHashTable *shash;
 
 	dir = g_dir_open (path, 0, error);
 	if (!dir) {
@@ -204,7 +203,6 @@ camel_imap_message_cache_new (const gchar *path,
 	cache->parts = g_hash_table_new (g_str_hash, g_str_equal);
 	cache->cached = g_hash_table_new (NULL, NULL);
 	deletes = g_ptr_array_new ();
-	shash = camel_folder_summary_get_hashtable (summary);
 
 	while ((dname = g_dir_read_name (dir))) {
 		if (!isdigit (dname[0]))
@@ -215,7 +213,7 @@ camel_imap_message_cache_new (const gchar *path,
 		else
 			uid = g_strdup (dname);
 
-		if (g_hash_table_lookup (shash, uid))
+		if (camel_folder_summary_check_uid (summary, uid))
 			cache_put (cache, uid, dname, NULL);
 		else
 			g_ptr_array_add (deletes, g_strdup_printf ("%s/%s", cache->path, dname));
@@ -231,8 +229,6 @@ camel_imap_message_cache_new (const gchar *path,
 	}
 	g_ptr_array_free (deletes, TRUE);
 
-	camel_folder_summary_free_hashtable (shash);
-
 	return cache;
 }
 
diff --git a/camel/providers/imap/camel-imap-store.c b/camel/providers/imap/camel-imap-store.c
index 4aa299a..7838b1c 100644
--- a/camel/providers/imap/camel-imap-store.c
+++ b/camel/providers/imap/camel-imap-store.c
@@ -1654,19 +1654,24 @@ static gboolean
 imap_summary_is_dirty (CamelFolderSummary *summary)
 {
 	CamelImapMessageInfo *info;
-	gint max, i;
-	gint found = FALSE;
+	gint i;
+	gboolean found = FALSE;
+	GPtrArray *known_uids;
+
+	known_uids = camel_folder_summary_get_array (summary);
+	g_return_val_if_fail (known_uids != NULL, FALSE);
 
-	max = camel_folder_summary_count (summary);
-	for (i = 0; i < max && !found; i++) {
-		info = (CamelImapMessageInfo *) camel_folder_summary_index (summary, i);
+	for (i = 0; i < known_uids->len && !found; i++) {
+		info = (CamelImapMessageInfo *) camel_folder_summary_get (summary, g_ptr_array_index (known_uids, i));
 		if (info) {
 			found = info->info.flags & CAMEL_MESSAGE_FOLDER_FLAGGED;
 			camel_message_info_free (info);
 		}
 	}
 
-	return FALSE;
+	camel_folder_summary_free_array (known_uids);
+
+	return found;
 }
 
 static gboolean
@@ -2878,8 +2883,8 @@ fill_fi (CamelStore *store,
 		else
 			ims = (CamelImapSummary *) camel_imap_summary_new (folder, NULL);
 
-		fi->unread = ((CamelFolderSummary *) ims)->unread_count;
-		fi->total = ((CamelFolderSummary *) ims)->saved_count;
+		fi->unread = camel_folder_summary_get_unread_count ((CamelFolderSummary *) ims);
+		fi->total = camel_folder_summary_get_saved_count ((CamelFolderSummary *) ims);
 
 		if (!folder->summary)
 			g_object_unref (ims);
@@ -3172,27 +3177,6 @@ get_folder_info_offline (CamelStore *store,
 	return fi;
 }
 
-#if 0
-static gboolean
-folder_flags_have_changed (CamelFolder *folder)
-{
-	CamelMessageInfo *info;
-	gint i, max;
-
-	max = camel_folder_summary_count (folder->summary);
-	for (i = 0; i < max; i++) {
-		info = camel_folder_summary_index (folder->summary, i);
-		if (!info)
-			continue;
-		if (info->flags & CAMEL_MESSAGE_FOLDER_FLAGGED) {
-			return TRUE;
-		}
-	}
-
-	return FALSE;
-}
-#endif
-
 /* Use this whenever you need to ensure you're both connected and
  * online. */
 gboolean
diff --git a/camel/providers/imap/camel-imap-summary.c b/camel/providers/imap/camel-imap-summary.c
index c1098dc..fc32104 100644
--- a/camel/providers/imap/camel-imap-summary.c
+++ b/camel/providers/imap/camel-imap-summary.c
@@ -43,11 +43,11 @@ static CamelMessageInfo *message_info_migrate (CamelFolderSummary *s, FILE *in);
 static gboolean info_set_user_flag (CamelMessageInfo *info, const gchar *id, gboolean state);
 static CamelMessageContentInfo *content_info_migrate (CamelFolderSummary *s, FILE *in);
 
-static gint summary_header_from_db (CamelFolderSummary *s, CamelFIRecord *mir);
+static gboolean summary_header_from_db (CamelFolderSummary *s, CamelFIRecord *mir);
 static CamelFIRecord * summary_header_to_db (CamelFolderSummary *s, GError **error);
 static CamelMIRecord * message_info_to_db (CamelFolderSummary *s, CamelMessageInfo *info);
 static CamelMessageInfo * message_info_from_db (CamelFolderSummary *s, CamelMIRecord *mir);
-static gint content_info_to_db (CamelFolderSummary *s, CamelMessageContentInfo *info, CamelMIRecord *mir);
+static gboolean content_info_to_db (CamelFolderSummary *s, CamelMessageContentInfo *info, CamelMIRecord *mir);
 static CamelMessageContentInfo * content_info_from_db (CamelFolderSummary *s, CamelMIRecord *mir);
 
 G_DEFINE_TYPE (CamelImapSummary, camel_imap_summary, CAMEL_TYPE_FOLDER_SUMMARY)
@@ -123,23 +123,6 @@ sort_uid_cmp (gpointer enc,
 	return (a1 < a1) ? -1 : (a1 > a2) ? 1 : 0;
 }
 
-static gint
-uid_compare (gconstpointer va,
-             gconstpointer vb)
-{
-	const gchar **sa = (const gchar **) va, **sb = (const gchar **) vb;
-	gulong a, b;
-
-	a = strtoul (*sa, NULL, 10);
-	b = strtoul (*sb, NULL, 10);
-	if (a < b)
-		return -1;
-	else if (a == b)
-		return 0;
-	else
-		return 1;
-}
-
 /**
  * camel_imap_summary_new:
  * @folder: Parent folder.
@@ -159,8 +142,8 @@ camel_imap_summary_new (CamelFolder *folder,
 
 	parent_store = camel_folder_get_parent_store (folder);
 
-	summary = g_object_new (CAMEL_TYPE_IMAP_SUMMARY, NULL);
-	summary->folder = folder;
+	summary = g_object_new (CAMEL_TYPE_IMAP_SUMMARY, "folder", folder, NULL);
+
 	/* Don't do DB sort. Its pretty slow to load */
 	if (folder && 0) {
 		camel_db_set_collate (
@@ -173,27 +156,25 @@ camel_imap_summary_new (CamelFolder *folder,
 	camel_folder_summary_set_build_content (summary, TRUE);
 	camel_folder_summary_set_filename (summary, filename);
 
-	if (camel_folder_summary_load_from_db (summary, NULL) == -1) {
+	if (!camel_folder_summary_load_from_db (summary, NULL)) {
 		/* FIXME: Isn't this dangerous ? We clear the summary
 		if it cannot be loaded, for some random reason.
 		We need to pass the ex and find out why it is not loaded etc. ? */
-		camel_folder_summary_clear_db (summary);
+		camel_folder_summary_clear (summary, NULL);
 	}
 
-	g_ptr_array_sort (summary->uids, (GCompareFunc) uid_compare);
-
 	return summary;
 }
 
-static gint
+static gboolean
 summary_header_from_db (CamelFolderSummary *s,
                         CamelFIRecord *mir)
 {
 	CamelImapSummary *ims = CAMEL_IMAP_SUMMARY (s);
 	gchar *part;
 
-	if (CAMEL_FOLDER_SUMMARY_CLASS (camel_imap_summary_parent_class)->summary_header_from_db (s, mir) == -1)
-		return -1;
+	if (!CAMEL_FOLDER_SUMMARY_CLASS (camel_imap_summary_parent_class)->summary_header_from_db (s, mir))
+		return FALSE;
 
 	part = mir->bdata;
 
@@ -203,10 +184,10 @@ summary_header_from_db (CamelFolderSummary *s,
 	if (ims->version > CAMEL_IMAP_SUMMARY_VERSION) {
 		g_warning("Unkown summary version\n");
 		errno = EINVAL;
-		return -1;
+		return FALSE;
 	}
 
-	return 0;
+	return TRUE;
 }
 
 static gint
@@ -375,7 +356,7 @@ content_info_migrate (CamelFolderSummary *s,
 		return camel_folder_summary_content_info_new (s);
 }
 
-static gint
+static gboolean
 content_info_to_db (CamelFolderSummary *s,
                     CamelMessageContentInfo *info,
                     CamelMIRecord *mir)
@@ -390,7 +371,7 @@ content_info_to_db (CamelFolderSummary *s,
 		oldr = mir->cinfo;
 		mir->cinfo = oldr ? g_strdup_printf("%s 0", oldr) : g_strdup ("0");
 		g_free (oldr);
-		return 0;
+		return TRUE;
 	}
 }
 
diff --git a/camel/providers/imap/camel-imap-utils.c b/camel/providers/imap/camel-imap-utils.c
index 5c47f3a..de74c6c 100644
--- a/camel/providers/imap/camel-imap-utils.c
+++ b/camel/providers/imap/camel-imap-utils.c
@@ -1187,15 +1187,18 @@ imap_quote_string (const gchar *str)
 }
 
 static inline gulong
-get_summary_uid_numeric (CamelFolderSummary *summary,
+get_summary_uid_numeric (GPtrArray *known_uids,
                          gint index)
 {
 	gulong uid;
-	gchar *suid;
+	const gchar *suid;
 
-	suid = camel_folder_summary_uid_from_index (summary, index);
+	g_return_val_if_fail (known_uids != NULL, 0);
+	g_return_val_if_fail (index >= 0, 0);
+	g_return_val_if_fail (index < known_uids->len, 0);
+
+	suid = g_ptr_array_index (known_uids, index);
 	uid = strtoul (suid, NULL, 10);
-	g_free (suid);
 
 	return uid;
 }
@@ -1235,20 +1238,26 @@ imap_uid_array_to_set (CamelFolderSummary *summary,
 	gint si, scount;
 	GString *gset;
 	gchar *set;
+	GPtrArray *known_uids;
 
 	g_return_val_if_fail (uids->len > uid, NULL);
 
+	known_uids = camel_folder_summary_get_array (summary);
+	g_return_val_if_fail (known_uids != NULL, NULL);
+
+	camel_folder_sort_uids (camel_folder_summary_get_folder (summary), known_uids);
+
 	gset = g_string_new (uids->pdata[uid]);
 	last_uid = strtoul (uids->pdata[uid], NULL, 10);
 	next_summary_uid = 0;
-	scount = camel_folder_summary_count (summary);
+	scount = known_uids->len;
 
 	for (uid++, si = 0; uid < uids->len && !UID_SET_FULL (gset->len, maxlen); uid++) {
 		/* Find the next UID in the summary after the one we
 		 * just wrote out.
 		 */
 		for (; last_uid >= next_summary_uid && si < scount; si++)
-			next_summary_uid = get_summary_uid_numeric (summary, si);
+			next_summary_uid = get_summary_uid_numeric (known_uids, si);
 		if (last_uid >= next_summary_uid)
 			next_summary_uid = (gulong) -1;
 
@@ -1274,6 +1283,7 @@ imap_uid_array_to_set (CamelFolderSummary *summary,
 
 	set = gset->str;
 	g_string_free (gset, FALSE);
+	camel_folder_summary_free_array (known_uids);
 
 	return set;
 }
@@ -1299,10 +1309,15 @@ imap_uid_set_to_array (CamelFolderSummary *summary,
                        const gchar *uids)
 {
 	GPtrArray *arr;
+	GPtrArray *known_uids;
 	gchar *p, *q;
 	gulong uid, suid;
 	gint si, scount;
 
+	known_uids = camel_folder_summary_get_array (summary);
+	g_return_val_if_fail (known_uids != NULL, NULL);
+
+	camel_folder_sort_uids (camel_folder_summary_get_folder (summary), known_uids);
 	arr = g_ptr_array_new ();
 	scount = camel_folder_summary_count (summary);
 
@@ -1319,7 +1334,7 @@ imap_uid_set_to_array (CamelFolderSummary *summary,
 			 * we just saw.
 			 */
 			while (++si < scount) {
-				suid = get_summary_uid_numeric (summary, si);
+				suid = get_summary_uid_numeric (known_uids, si);
 				if (suid > uid)
 					break;
 			}
@@ -1336,7 +1351,7 @@ imap_uid_set_to_array (CamelFolderSummary *summary,
 			while (suid <= uid) {
 				g_ptr_array_add (arr, g_strdup_printf ("%lu", suid));
 				if (++si < scount)
-					suid = get_summary_uid_numeric (summary, si);
+					suid = get_summary_uid_numeric (known_uids, si);
 				else
 					suid++;
 			}
@@ -1344,10 +1359,12 @@ imap_uid_set_to_array (CamelFolderSummary *summary,
 			p = q;
 	} while (*p++ == ',');
 
+	camel_folder_summary_free_array (known_uids);
 	return arr;
 
  lose:
 	g_warning ("Invalid uid set %s", uids);
+	camel_folder_summary_free_array (known_uids);
 	imap_uid_array_free (arr);
 	return NULL;
 }
diff --git a/camel/providers/imapx/camel-imapx-folder.c b/camel/providers/imapx/camel-imapx-folder.c
index 11c3cec..bffcb00 100644
--- a/camel/providers/imapx/camel-imapx-folder.c
+++ b/camel/providers/imapx/camel-imapx-folder.c
@@ -125,6 +125,10 @@ camel_imapx_folder_new (CamelStore *store,
 
 	g_free (summary_file);
 
+	camel_store_summary_connect_folder_summary (
+		(CamelStoreSummary *) ((CamelIMAPXStore *) store)->summary,
+		folder_name, folder->summary);
+
 	return folder;
 }
 
@@ -132,6 +136,7 @@ static void
 imapx_folder_dispose (GObject *object)
 {
 	CamelIMAPXFolder *folder = CAMEL_IMAPX_FOLDER (object);
+	CamelStore *parent_store;
 
 	if (folder->cache != NULL) {
 		g_object_unref (folder->cache);
@@ -143,6 +148,13 @@ imapx_folder_dispose (GObject *object)
 		folder->search = NULL;
 	}
 
+	parent_store = camel_folder_get_parent_store (CAMEL_FOLDER (folder));
+	if (parent_store) {
+		camel_store_summary_disconnect_folder_summary (
+			(CamelStoreSummary *) ((CamelIMAPXStore *) parent_store)->summary,
+			CAMEL_FOLDER (folder)->summary);
+	}
+
 	/* Chain up to parent's dispose() method. */
 	G_OBJECT_CLASS (camel_imapx_folder_parent_class)->dispose (object);
 }
diff --git a/camel/providers/imapx/camel-imapx-server.c b/camel/providers/imapx/camel-imapx-server.c
index a1caa17..430d6f1 100644
--- a/camel/providers/imapx/camel-imapx-server.c
+++ b/camel/providers/imapx/camel-imapx-server.c
@@ -1252,7 +1252,6 @@ imapx_expunge_uid_from_summary (CamelIMAPXServer *imap,
                                 gchar *uid,
                                 gboolean unsolicited)
 {
-	CamelMessageInfo *mi;
 	CamelIMAPXFolder *ifolder = (CamelIMAPXFolder *) imap->select_folder;
 
 	if (unsolicited && ifolder->exists_on_server)
@@ -1261,13 +1260,7 @@ imapx_expunge_uid_from_summary (CamelIMAPXServer *imap,
 	if (imap->changes == NULL)
 		imap->changes = camel_folder_change_info_new ();
 
-	mi = camel_folder_summary_uid (imap->select_folder->summary, uid);
-	if (mi) {
-		imapx_update_summary_for_removed_message (mi, imap->select_folder, unsolicited);
-		camel_message_info_free (mi);
-	}
-
-	camel_folder_summary_remove_uid_fast (imap->select_folder->summary, uid);
+	camel_folder_summary_remove_uid (imap->select_folder->summary, uid);
 	imap->expunged = g_list_prepend (imap->expunged, uid);
 
 	camel_folder_change_info_remove_uid (imap->changes, uid);
@@ -1287,6 +1280,27 @@ imapx_expunge_uid_from_summary (CamelIMAPXServer *imap,
 	}
 }
 
+static gchar *
+imapx_get_uid_from_index (CamelFolderSummary *summary, guint id)
+{
+	GPtrArray *array;
+	gchar *uid;
+
+	g_return_val_if_fail (summary != NULL, NULL);
+
+	array = camel_folder_summary_get_array (summary);
+	g_return_val_if_fail (array != NULL, NULL);
+
+	if (id < array->len) {
+		camel_folder_sort_uids (camel_folder_summary_get_folder (summary), array);
+		uid = g_strdup (g_ptr_array_index (array, id));
+	}
+
+	camel_folder_summary_free_array (array);
+
+	return uid;
+}
+
 static void
 invalidate_local_cache (CamelIMAPXFolder *ifolder,
                         guint64 new_uidvalidity)
@@ -1303,7 +1317,7 @@ invalidate_local_cache (CamelIMAPXFolder *ifolder,
 
 	changes = camel_folder_change_info_new ();
 
-	uids = camel_folder_summary_array (cfolder->summary);
+	uids = camel_folder_summary_get_array (cfolder->summary);
 	for (ii = 0; uids && ii < uids->len; ii++) {
 		const gchar *uid = uids->pdata[ii];
 
@@ -1311,8 +1325,7 @@ invalidate_local_cache (CamelIMAPXFolder *ifolder,
 			camel_folder_change_info_change_uid (changes, uid);
 	}
 
-	g_ptr_array_foreach (uids, (GFunc) camel_pstring_free, NULL);
-	g_ptr_array_free (uids, TRUE);
+	camel_folder_summary_free_array (uids);
 
 	CAMEL_IMAPX_SUMMARY (cfolder->summary)->validity = new_uidvalidity;
 	camel_folder_summary_touch (cfolder->summary);
@@ -1392,11 +1405,12 @@ imapx_untagged (CamelIMAPXServer *imap,
 		if (imap->select_folder) {
 			gchar *uid = NULL;
 
-			uid = camel_folder_summary_uid_from_index (imap->select_folder->summary, expunge - 1);
+			uid = imapx_get_uid_from_index (imap->select_folder->summary, expunge - 1);
 			if (!uid)
 				break;
 
 			imapx_expunge_uid_from_summary (imap, uid, TRUE);
+			g_free (uid);
 		}
 
 		break;
@@ -1534,11 +1548,11 @@ imapx_untagged (CamelIMAPXServer *imap,
 					uid = finfo->uid;
 					finfo->uid = NULL;
 				} else {
-					uid = camel_folder_summary_uid_from_index (folder->summary, id - 1);
+					uid = imapx_get_uid_from_index (folder->summary, id - 1);
 				}
 
 				if (uid) {
-					mi = camel_folder_summary_uid (folder->summary, uid);
+					mi = camel_folder_summary_get (folder->summary, uid);
 					if (mi) {
 						/* It's unsolicited _unless_ imap->select_pending (i.e. during
 						 * a QRESYNC SELECT */
@@ -2744,8 +2758,8 @@ imapx_select (CamelIMAPXServer *is,
 
 		if (total && isum->modseq && ifolder->uidvalidity_on_server) {
 
-			firstuid = camel_folder_summary_uid_from_index (folder->summary, 0);
-			lastuid = camel_folder_summary_uid_from_index (folder->summary, total - 1);
+			firstuid = imapx_get_uid_from_index (folder->summary, 0);
+			lastuid = imapx_get_uid_from_index (folder->summary, total - 1);
 
 			c(is->tagprefix, "SELECT QRESYNC %" G_GUINT64_FORMAT
 			  " %" G_GUINT64_FORMAT "\n",
@@ -2790,7 +2804,7 @@ imapx_select (CamelIMAPXServer *is,
 					 * the summary starts from zero. */
 					sprintf(buf, "%d", total - i + 1);
 					g_string_prepend (seqs, buf);
-					uid = camel_folder_summary_uid_from_index (folder->summary, total - i);
+					uid = imapx_get_uid_from_index (folder->summary, total - i);
 					g_string_prepend (uids, uid);
 					g_free (uid);
 				} while (i < total);
@@ -3757,7 +3771,7 @@ imapx_index_next (GPtrArray *uids,
 		if (index >= uids->len)
 			break;
 
-		info = camel_folder_summary_uid (s, g_ptr_array_index (uids, index));
+		info = camel_folder_summary_get (s, g_ptr_array_index (uids, index));
 		if (!info)
 			continue;
 
@@ -3831,8 +3845,8 @@ imapx_command_step_fetch_done (CamelIMAPXServer *is,
 	}
 
 	if (camel_folder_summary_count (job->folder->summary)) {
-		gchar *uid = camel_folder_summary_uid_from_index (job->folder->summary,
-						  camel_folder_summary_count (job->folder->summary) - 1);
+		gchar *uid = imapx_get_uid_from_index (job->folder->summary,
+						       camel_folder_summary_count (job->folder->summary) - 1);
 		guint64 uidl = strtoull (uid, NULL, 10);
 		g_free (uid);
 
@@ -3930,13 +3944,13 @@ imapx_job_scan_changes_done (CamelIMAPXServer *is,
 		 * for all outstanding messages to be uploaded */
 
 		/* obtain a copy to be thread safe */
-		uids = camel_folder_summary_array (s);
+		uids = camel_folder_summary_get_array (s);
 
 		qsort (infos->data, infos->len, sizeof (struct _refresh_info), imapx_refresh_info_cmp);
 		g_ptr_array_sort (uids, (GCompareFunc) imapx_uids_array_cmp);
 
 		if (uids->len)
-			s_minfo = camel_folder_summary_uid (s, g_ptr_array_index (uids, 0));
+			s_minfo = camel_folder_summary_get (s, g_ptr_array_index (uids, 0));
 
 		for (i = 0; i < infos->len; i++) {
 			struct _refresh_info *r = &g_array_index (infos, struct _refresh_info, i);
@@ -3951,7 +3965,7 @@ imapx_job_scan_changes_done (CamelIMAPXServer *is,
 
 				j = imapx_index_next (uids, s, j);
 				if (j < uids->len)
-					s_minfo = camel_folder_summary_uid (s, g_ptr_array_index (uids, j));
+					s_minfo = camel_folder_summary_get (s, g_ptr_array_index (uids, j));
 			}
 
 			info = NULL;
@@ -3974,14 +3988,14 @@ imapx_job_scan_changes_done (CamelIMAPXServer *is,
 
 			j = imapx_index_next (uids, s, j);
 			if (j < uids->len)
-				s_minfo = camel_folder_summary_uid (s, g_ptr_array_index (uids, j));
+				s_minfo = camel_folder_summary_get (s, g_ptr_array_index (uids, j));
 		}
 
 		if (s_minfo)
 			camel_message_info_free (s_minfo);
 
 		while (j < uids->len) {
-			s_minfo = camel_folder_summary_uid (s, g_ptr_array_index (uids, j));
+			s_minfo = camel_folder_summary_get (s, g_ptr_array_index (uids, j));
 
 			if (!s_minfo) {
 				j++;
@@ -3996,22 +4010,15 @@ imapx_job_scan_changes_done (CamelIMAPXServer *is,
 
 		for (l = removed; l != NULL; l = g_list_next (l)) {
 			gchar *uid = (gchar *) l->data;
-			CamelMessageInfo *mi;
-
-			mi = camel_folder_summary_uid (job->folder->summary, uid);
-			if (mi) {
-				imapx_update_summary_for_removed_message (mi, job->folder, FALSE);
-				camel_message_info_free (mi);
-			}
 
 			camel_folder_change_info_remove_uid (job->u.refresh_info.changes, uid);
-			camel_folder_summary_remove_uid_fast (s, uid);
+			camel_folder_summary_remove_uid (s, uid);
 		}
 
 		if (removed) {
 			const gchar *full_name;
 
-			full_name = camel_folder_get_full_name (s->folder);
+			full_name = camel_folder_get_full_name (camel_folder_summary_get_folder (s));
 			camel_db_delete_uids (is->store->cdb_w, full_name, removed, NULL);
 			g_list_foreach (removed, (GFunc) g_free, NULL);
 			g_list_free (removed);
@@ -4023,7 +4030,7 @@ imapx_job_scan_changes_done (CamelIMAPXServer *is,
 			camel_folder_changed (job->folder, job->u.refresh_info.changes);
 		camel_folder_change_info_clear (job->u.refresh_info.changes);
 
-		camel_folder_free_uids (job->folder, uids);
+		camel_folder_summary_free_array (uids);
 
 		/* If we have any new messages, download their headers, but only a few (100?) at a time */
 		if (fetch_new) {
@@ -4056,7 +4063,7 @@ imapx_job_scan_changes_done (CamelIMAPXServer *is,
 
 	/* There's no sane way to get the server-side unseen count on the
 	 * select mailbox. So just work it out from the flags */
-	((CamelIMAPXFolder *) job->folder)->unread_on_server = job->folder->summary->unread_count;
+	((CamelIMAPXFolder *) job->folder)->unread_on_server = camel_folder_summary_get_unread_count (job->folder->summary);
 
 	g_array_free (job->u.refresh_info.infos, TRUE);
 	imapx_job_done (is, job);
@@ -4108,8 +4115,8 @@ imapx_command_fetch_new_messages_done (CamelIMAPXServer *is,
 	}
 
 	if (camel_folder_summary_count (ic->job->folder->summary)) {
-		gchar *uid = camel_folder_summary_uid_from_index (ic->job->folder->summary,
-					  camel_folder_summary_count (ic->job->folder->summary) - 1);
+		gchar *uid = imapx_get_uid_from_index (ic->job->folder->summary,
+						       camel_folder_summary_count (ic->job->folder->summary) - 1);
 		guint64 uidl = strtoull (uid, NULL, 10);
 		g_free (uid);
 
@@ -4170,7 +4177,7 @@ imapx_job_fetch_new_messages_start (CamelIMAPXServer *is,
 
 	if (total > 0) {
 		guint64 uidl;
-		uid = camel_folder_summary_uid_from_index (folder->summary, total - 1);
+		uid = imapx_get_uid_from_index (folder->summary, total - 1);
 		uidl = strtoull (uid, NULL, 10);
 		g_free (uid);
 		uid = g_strdup_printf ("%" G_GUINT64_FORMAT, uidl+1);
@@ -4250,7 +4257,7 @@ imapx_job_refresh_info_start (CamelIMAPXServer *is,
 	 * message flags, but don't depend on modseq for the selected folder */
 	if (total != ifolder->exists_on_server ||
 	    isum->uidnext != ifolder->uidnext_on_server ||
-	    folder->summary->unread_count != ifolder->unread_on_server ||
+	    camel_folder_summary_get_unread_count (folder->summary) != ifolder->unread_on_server ||
 	    (!is_selected && isum->modseq != ifolder->modseq_on_server))
 		need_rescan = TRUE;
 
@@ -4309,7 +4316,7 @@ imapx_job_refresh_info_start (CamelIMAPXServer *is,
 		/* Recalulate need_rescan */
 		if (total != ifolder->exists_on_server ||
 		    isum->uidnext != ifolder->uidnext_on_server ||
-		    folder->summary->unread_count != ifolder->unread_on_server ||
+		    camel_folder_summary_get_unread_count (folder->summary) != ifolder->unread_on_server ||
 		    (!is_selected && isum->modseq != ifolder->modseq_on_server))
 			need_rescan = TRUE;
 
@@ -4320,7 +4327,7 @@ imapx_job_refresh_info_start (CamelIMAPXServer *is,
 
 	e(is->tagprefix, "folder %s is %sselected, total %u / %u, unread %u / %u, modseq %" G_GUINT64_FORMAT " / %" G_GUINT64_FORMAT ", uidnext %u / %u: will %srescan\n",
 	  full_name, is_selected?"": "not ", total, ifolder->exists_on_server,
-	  folder->summary->unread_count, ifolder->unread_on_server,
+	  camel_folder_summary_get_unread_count (folder->summary), ifolder->unread_on_server,
 	  (guint64) isum->modseq, (guint64) ifolder->modseq_on_server,
 	  isum->uidnext, ifolder->uidnext_on_server,
 	  need_rescan?"":"not ");
@@ -4352,16 +4359,16 @@ imapx_job_refresh_info_start (CamelIMAPXServer *is,
 		isum->modseq = ifolder->modseq_on_server;
 		total = camel_folder_summary_count (job->folder->summary);
 		if (total != ifolder->exists_on_server ||
-		    folder->summary->unread_count != ifolder->unread_on_server ||
+		    camel_folder_summary_get_unread_count (folder->summary) != ifolder->unread_on_server ||
 		    (isum->modseq != ifolder->modseq_on_server)) {
 			c(is->tagprefix, "Eep, after QRESYNC we're out of sync. total %u / %u, unread %u / %u, modseq %" G_GUINT64_FORMAT " / %" G_GUINT64_FORMAT "\n",
 			  total, ifolder->exists_on_server,
-			  folder->summary->unread_count, ifolder->unread_on_server,
+			  camel_folder_summary_get_unread_count (folder->summary), ifolder->unread_on_server,
 			  isum->modseq, ifolder->modseq_on_server);
 		} else {
 			c(is->tagprefix, "OK, after QRESYNC we're still in sync. total %u / %u, unread %u / %u, modseq %" G_GUINT64_FORMAT " / %" G_GUINT64_FORMAT "\n",
 			  total, ifolder->exists_on_server,
-			  folder->summary->unread_count, ifolder->unread_on_server,
+			  camel_folder_summary_get_unread_count (folder->summary), ifolder->unread_on_server,
 			  isum->modseq, ifolder->modseq_on_server);
 			goto done;
 		}
@@ -4402,14 +4409,8 @@ imapx_command_expunge_done (CamelIMAPXServer *is,
 			changes = camel_folder_change_info_new ();
 			for (i = 0; i < uids->len; i++) {
 				gchar *uid = uids->pdata[i];
-				CamelMessageInfo *mi = camel_folder_summary_uid (folder->summary, uid);
-
-				if (mi) {
-					imapx_update_summary_for_removed_message (mi, folder, FALSE);
-					camel_message_info_free (mi);
-				}
 
-				camel_folder_summary_remove_uid_fast (folder->summary, uid);
+				camel_folder_summary_remove_uid (folder->summary, uid);
 				camel_folder_change_info_remove_uid (changes, uids->pdata[i]);
 				removed = g_list_prepend (removed, (gpointer) uids->pdata[i]);
 			}
@@ -4753,7 +4754,7 @@ imapx_command_sync_changes_done (CamelIMAPXServer *is,
 		gint i;
 
 		for (i = 0; i < job->u.sync_changes.changed_uids->len; i++) {
-			CamelIMAPXMessageInfo *xinfo = (CamelIMAPXMessageInfo *) camel_folder_summary_uid (job->folder->summary,
+			CamelIMAPXMessageInfo *xinfo = (CamelIMAPXMessageInfo *) camel_folder_summary_get (job->folder->summary,
 					job->u.sync_changes.changed_uids->pdata[i]);
 
 			if (!xinfo)
@@ -4779,9 +4780,10 @@ imapx_command_sync_changes_done (CamelIMAPXServer *is,
 			/* ... and store's summary when folder's summary is dirty */
 			si = camel_store_summary_path ((CamelStoreSummary *)((CamelIMAPXStore *) parent_store)->summary, full_name);
 			if (si) {
-				if (si->total != job->folder->summary->saved_count || si->unread != job->folder->summary->unread_count) {
-					si->total = job->folder->summary->saved_count;
-					si->unread = job->folder->summary->unread_count;
+				if (si->total != camel_folder_summary_get_saved_count (job->folder->summary) ||
+				    si->unread != camel_folder_summary_get_unread_count (job->folder->summary)) {
+					si->total = camel_folder_summary_get_saved_count (job->folder->summary);
+					si->unread = camel_folder_summary_get_unread_count (job->folder->summary);
 					camel_store_summary_touch ((CamelStoreSummary *)((CamelIMAPXStore *) parent_store)->summary);
 				}
 
@@ -4820,7 +4822,7 @@ imapx_job_sync_changes_start (CamelIMAPXServer *is,
 			c(is->tagprefix, "checking/storing %s flags '%s'\n", on?"on":"off", flags_table[j].name);
 			imapx_uidset_init (&ss, 0, 100);
 			for (i = 0; i < uids->len; i++) {
-				CamelIMAPXMessageInfo *info = (CamelIMAPXMessageInfo *) camel_folder_summary_uid
+				CamelIMAPXMessageInfo *info = (CamelIMAPXMessageInfo *) camel_folder_summary_get
 										(job->folder->summary, uids->pdata[i]);
 				guint32 flags;
 				guint32 sflags;
@@ -5348,7 +5350,7 @@ imapx_server_get_message (CamelIMAPXServer *is,
 		return stream;
 	}
 
-	mi = camel_folder_summary_uid (folder->summary, uid);
+	mi = camel_folder_summary_get (folder->summary, uid);
 	if (!mi) {
 		g_set_error (
 			error, CAMEL_FOLDER_ERROR,
@@ -5678,7 +5680,7 @@ imapx_server_sync_changes (CamelIMAPXServer *is,
 		CamelFlag *uflags, *suflags;
 		guint j = 0;
 
-		info = (CamelIMAPXMessageInfo *) camel_folder_summary_uid (folder->summary, uids->pdata[i]);
+		info = (CamelIMAPXMessageInfo *) camel_folder_summary_get (folder->summary, uids->pdata[i]);
 
 		if (!info)
 			continue;
diff --git a/camel/providers/imapx/camel-imapx-store.c b/camel/providers/imapx/camel-imapx-store.c
index 3f749c3..c9216d6 100644
--- a/camel/providers/imapx/camel-imapx-store.c
+++ b/camel/providers/imapx/camel-imapx-store.c
@@ -367,8 +367,8 @@ fill_fi (CamelStore *store,
 		else
 			ims = (CamelIMAPXSummary *) camel_imapx_summary_new (folder, NULL);
 
-		fi->unread = ((CamelFolderSummary *) ims)->unread_count;
-		fi->total = ((CamelFolderSummary *) ims)->saved_count;
+		fi->unread = camel_folder_summary_get_unread_count ((CamelFolderSummary *) ims);
+		fi->total = camel_folder_summary_get_saved_count ((CamelFolderSummary *) ims);
 
 		if (!folder->summary)
 			g_object_unref (ims);
diff --git a/camel/providers/imapx/camel-imapx-summary.c b/camel/providers/imapx/camel-imapx-summary.c
index a135101..874cd45 100644
--- a/camel/providers/imapx/camel-imapx-summary.c
+++ b/camel/providers/imapx/camel-imapx-summary.c
@@ -42,11 +42,11 @@ static CamelMessageInfo *message_info_migrate (CamelFolderSummary *s, FILE *in);
 static gboolean info_set_user_flag (CamelMessageInfo *info, const gchar *id, gboolean state);
 static CamelMessageContentInfo *content_info_migrate (CamelFolderSummary *s, FILE *in);
 
-static gint summary_header_from_db (CamelFolderSummary *s, CamelFIRecord *mir);
+static gboolean summary_header_from_db (CamelFolderSummary *s, CamelFIRecord *mir);
 static CamelFIRecord * summary_header_to_db (CamelFolderSummary *s, GError **error);
 static CamelMIRecord * message_info_to_db (CamelFolderSummary *s, CamelMessageInfo *info);
 static CamelMessageInfo * message_info_from_db (CamelFolderSummary *s, CamelMIRecord *mir);
-static gint content_info_to_db (CamelFolderSummary *s, CamelMessageContentInfo *info, CamelMIRecord *mir);
+static gboolean content_info_to_db (CamelFolderSummary *s, CamelMessageContentInfo *info, CamelMIRecord *mir);
 static CamelMessageContentInfo * content_info_from_db (CamelFolderSummary *s, CamelMIRecord *mir);
 
 G_DEFINE_TYPE (CamelIMAPXSummary, camel_imapx_summary, CAMEL_TYPE_FOLDER_SUMMARY)
@@ -127,23 +127,6 @@ sort_uid_cmp (gpointer enc,
 	return (a1 < a1) ? -1 : (a1 > a2) ? 1 : 0;
 }
 
-static gint
-uid_compare (gconstpointer va,
-             gconstpointer vb)
-{
-	const gchar **sa = (const gchar **) va, **sb = (const gchar **) vb;
-	gulong a, b;
-
-	a = strtoul (*sa, NULL, 10);
-	b = strtoul (*sb, NULL, 10);
-	if (a < b)
-		return -1;
-	else if (a == b)
-		return 0;
-	else
-		return 1;
-}
-
 /**
  * camel_imapx_summary_new:
  * @folder: Parent folder.
@@ -164,9 +147,8 @@ camel_imapx_summary_new (CamelFolder *folder,
 
 	parent_store = camel_folder_get_parent_store (folder);
 
-	summary = g_object_new (CAMEL_TYPE_IMAPX_SUMMARY, NULL);
+	summary = g_object_new (CAMEL_TYPE_IMAPX_SUMMARY, "folder", folder, NULL);
 
-	summary->folder = folder;
 	/* Don't do DB sort. Its pretty slow to load */
 	if (folder && 0) {
 		camel_db_set_collate (parent_store->cdb_r, "uid", "imapx_uid_sort", (CamelDBCollate)sort_uid_cmp);
@@ -177,21 +159,19 @@ camel_imapx_summary_new (CamelFolder *folder,
 	camel_folder_summary_set_build_content (summary, TRUE);
 	camel_folder_summary_set_filename (summary, filename);
 
-	if (camel_folder_summary_load_from_db (summary, &local_error) == -1) {
+	if (!camel_folder_summary_load_from_db (summary, &local_error)) {
 		/* FIXME: Isn't this dangerous ? We clear the summary
 		if it cannot be loaded, for some random reason.
 		We need to pass the error and find out why it is not loaded etc. ? */
-		camel_folder_summary_clear_db (summary);
+		camel_folder_summary_clear (summary, NULL);
 		g_message ("Unable to load summary: %s\n", local_error->message);
 		g_clear_error (&local_error);
 	}
 
-	g_ptr_array_sort (summary->uids, (GCompareFunc) uid_compare);
-
 	return summary;
 }
 
-static gint
+static gboolean
 summary_header_from_db (CamelFolderSummary *s,
                         CamelFIRecord *mir)
 {
@@ -202,8 +182,8 @@ summary_header_from_db (CamelFolderSummary *s,
 	folder_summary_class = CAMEL_FOLDER_SUMMARY_CLASS (
 		camel_imapx_summary_parent_class);
 
-	if (folder_summary_class->summary_header_from_db (s, mir) == -1)
-		return -1;
+	if (!folder_summary_class->summary_header_from_db (s, mir))
+		return FALSE;
 
 	part = mir->bdata;
 
@@ -218,10 +198,10 @@ summary_header_from_db (CamelFolderSummary *s,
 	if (ims->version > CAMEL_IMAPX_SUMMARY_VERSION) {
 		g_warning("Unknown summary version\n");
 		errno = EINVAL;
-		return -1;
+		return FALSE;
 	}
 
-	return 0;
+	return TRUE;
 }
 
 static gint
@@ -427,7 +407,7 @@ content_info_migrate (CamelFolderSummary *s,
 		return camel_folder_summary_content_info_new (s);
 }
 
-static gint
+static gboolean
 content_info_to_db (CamelFolderSummary *s,
                     CamelMessageContentInfo *info,
                     CamelMIRecord *mir)
@@ -447,7 +427,7 @@ content_info_to_db (CamelFolderSummary *s,
 		oldr = mir->cinfo;
 		mir->cinfo = oldr ? g_strdup_printf("%s 0", oldr) : g_strdup ("0");
 		g_free (oldr);
-		return 0;
+		return TRUE;
 	}
 }
 
diff --git a/camel/providers/imapx/camel-imapx-utils.c b/camel/providers/imapx/camel-imapx-utils.c
index 71b3f02..a9cf44c 100644
--- a/camel/providers/imapx/camel-imapx-utils.c
+++ b/camel/providers/imapx/camel-imapx-utils.c
@@ -264,13 +264,10 @@ imapx_update_message_info_flags (CamelMessageInfo *info,
                                  gboolean unsolicited)
 {
 	gboolean changed = FALSE;
-	CamelIMAPXFolder *ifolder = (CamelIMAPXFolder *) folder;
 	CamelIMAPXMessageInfo *xinfo = (CamelIMAPXMessageInfo *) info;
 
-	if (server_flags != xinfo->server_flags)
-	{
+	if (server_flags != xinfo->server_flags) {
 		guint32 server_set, server_cleared;
-		gint read = 0, deleted = 0, junk = 0;
 
 		server_set = server_flags & ~xinfo->server_flags;
 		server_cleared = xinfo->server_flags & ~server_flags;
@@ -281,44 +278,12 @@ imapx_update_message_info_flags (CamelMessageInfo *info,
 		if (permanent_flags > 0)
 			server_cleared &= permanent_flags;
 
-		if (server_set & CAMEL_MESSAGE_SEEN)
-			read = 1;
-		else if (server_cleared & CAMEL_MESSAGE_SEEN)
-			read = -1;
-
-		if (server_set & CAMEL_MESSAGE_DELETED)
-			deleted = 1;
-		else if (server_cleared & CAMEL_MESSAGE_DELETED)
-			deleted = -1;
-
-		if (server_set & CAMEL_MESSAGE_JUNK)
-			junk = 1;
-		else if (server_cleared & CAMEL_MESSAGE_JUNK)
-			junk = -1;
-
-		d('?', "%s %s %s %s\n", xinfo->info.uid, read == 1 ? "read" : ( read == -1 ? "unread" : ""),
-		  deleted == 1 ? "deleted" : ( deleted == -1 ? "undeleted" : ""),
-		  junk == 1 ? "junk" : ( junk == -1 ? "unjunked" : ""));
-
-		if (read) {
-			folder->summary->unread_count -= read;
-			if (unsolicited)
-				ifolder->unread_on_server -= read;
-		}
-		if (deleted)
-			folder->summary->deleted_count += deleted;
-		if (junk)
-			folder->summary->junk_count += junk;
-		if (junk && !deleted)
-			folder->summary->junk_not_deleted_count += junk;
-		if (junk ||  deleted)
-			folder->summary->visible_count -= junk ? junk : deleted;
-
-		xinfo->info.flags = (xinfo->info.flags | server_set) & ~server_cleared;
+		camel_message_info_set_flags ((CamelMessageInfo *) xinfo, server_set | server_cleared, (xinfo->info.flags | server_set) & ~server_cleared);
+
 		xinfo->server_flags = server_flags;
+		xinfo->info.flags = xinfo->info.flags & ~CAMEL_MESSAGE_FOLDER_FLAGGED;
 		xinfo->info.dirty = TRUE;
-		if (info->summary)
-			camel_folder_summary_touch (info->summary);
+
 		changed = TRUE;
 	}
 
@@ -336,85 +301,17 @@ imapx_set_message_info_flags_for_new_message (CamelMessageInfo *info,
 {
 	CamelMessageInfoBase *binfo = (CamelMessageInfoBase *) info;
 	CamelIMAPXMessageInfo *xinfo = (CamelIMAPXMessageInfo *) info;
-	gint unread = 0, deleted = 0, junk = 0;
-	guint32 flags;
 
 	binfo->flags |= server_flags;
+	camel_message_info_set_flags (info, server_flags, binfo->flags | server_flags);
+
 	xinfo->server_flags = server_flags;
 
 	if (folder->permanent_flags & CAMEL_MESSAGE_USER)
 		imapx_update_user_flags (info, server_user_flags);
 
-	/* update the summary count */
-	flags = binfo->flags;
-
-	if (!(flags & CAMEL_MESSAGE_SEEN))
-		unread = 1;
-
-	if (flags & CAMEL_MESSAGE_DELETED)
-		deleted = 1;
-
-	if (flags & CAMEL_MESSAGE_JUNK)
-		junk = 1;
-
-	if (folder->summary) {
-
-		if (unread)
-			folder->summary->unread_count += unread;
-		if (deleted)
-			folder->summary->deleted_count += deleted;
-		if (junk)
-			folder->summary->junk_count += junk;
-		if (junk && !deleted)
-			folder->summary->junk_not_deleted_count += junk;
-		folder->summary->visible_count++;
-		if (junk ||  deleted)
-			folder->summary->visible_count -= junk ? junk : deleted;
-
-		folder->summary->saved_count++;
-		camel_folder_summary_touch (folder->summary);
-	}
-
 	binfo->flags &= ~CAMEL_MESSAGE_FOLDER_FLAGGED;
-}
-
-void
-imapx_update_summary_for_removed_message (CamelMessageInfo *info,
-                                          CamelFolder *folder,
-                                          gboolean unsolicited)
-{
-	CamelMessageInfoBase *dinfo = (CamelMessageInfoBase *) info;
-	CamelIMAPXFolder *ifolder = (CamelIMAPXFolder *) folder;
-	gint unread = 0, deleted = 0, junk = 0;
-	guint32 flags;
-
-	flags = dinfo->flags;
-	if (!(flags & CAMEL_MESSAGE_SEEN))
-		unread = 1;
-
-	if (flags & CAMEL_MESSAGE_DELETED)
-		deleted = 1;
-
-	if (flags & CAMEL_MESSAGE_JUNK)
-		junk = 1;
-
-	if (unread) {
-		folder->summary->unread_count--;
-		if (unsolicited)
-			ifolder->unread_on_server--;
-	}
-	if (deleted)
-		folder->summary->deleted_count--;
-	if (junk)
-		folder->summary->junk_count--;
-
-	if (junk && !deleted)
-		folder->summary->junk_not_deleted_count--;
-
-	if (!junk &&  !deleted)
-		folder->summary->visible_count--;
-
-	folder->summary->saved_count--;
+	binfo->dirty = TRUE;
 }
 
 void
@@ -432,7 +329,7 @@ imapx_update_store_summary (CamelFolder *folder)
 		guint32 unread, total;
 
 		total = camel_folder_summary_count (folder->summary);
-		unread = folder->summary->unread_count;
+		unread = camel_folder_summary_get_unread_count (folder->summary);
 
 		if (si->unread != unread || si->total != total) {
 			si->unread = unread;
diff --git a/camel/providers/imapx/camel-imapx-utils.h b/camel/providers/imapx/camel-imapx-utils.h
index 17e4d80..848c01a 100644
--- a/camel/providers/imapx/camel-imapx-utils.h
+++ b/camel/providers/imapx/camel-imapx-utils.h
@@ -89,7 +89,6 @@ void imapx_write_flags (CamelStream *stream, guint32 flags, struct _CamelFlag *u
 gboolean imapx_update_message_info_flags (CamelMessageInfo *info, guint32 server_flags, CamelFlag *server_user_flags, guint32 permanent_flags, CamelFolder *folder, gboolean unsolicited);
 void imapx_set_message_info_flags_for_new_message (CamelMessageInfo *info, guint32 server_flags, CamelFlag *server_user_flags,
 							CamelFolder *folder);
-void imapx_update_summary_for_removed_message (CamelMessageInfo *info, CamelFolder *folder, gboolean unsolicited);
 void imapx_update_store_summary (CamelFolder *folder);
 
 /* ********************************************************************** */
diff --git a/camel/providers/local/camel-local-folder.c b/camel/providers/local/camel-local-folder.c
index e1c9765..5b68f1e 100644
--- a/camel/providers/local/camel-local-folder.c
+++ b/camel/providers/local/camel-local-folder.c
@@ -608,7 +608,7 @@ camel_local_folder_construct (CamelLocalFolder *lf,
 	}
 
 	folder->summary = (CamelFolderSummary *) CAMEL_LOCAL_FOLDER_GET_CLASS (lf)->create_summary (lf, lf->summary_path, lf->folder_path, lf->index);
-	if (!(flags & CAMEL_STORE_IS_MIGRATING) && 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)) {
 		/* ? */
 		if (need_summary_check &&
 		    camel_local_summary_check ((CamelLocalSummary *) folder->summary, lf->changes, cancellable, error) == 0) {
diff --git a/camel/providers/local/camel-local-summary.c b/camel/providers/local/camel-local-summary.c
index 92eaf00..2575cbb 100644
--- a/camel/providers/local/camel-local-summary.c
+++ b/camel/providers/local/camel-local-summary.c
@@ -44,7 +44,7 @@
 #define EXTRACT_FIRST_DIGIT(val) val=strtoul (part, &part, 10);
 
 static CamelFIRecord * summary_header_to_db (CamelFolderSummary *, GError **error);
-static gint summary_header_from_db (CamelFolderSummary *, CamelFIRecord *);
+static gboolean summary_header_from_db (CamelFolderSummary *, CamelFIRecord *);
 
 static gint summary_header_load (CamelFolderSummary *, FILE *);
 static gint summary_header_save (CamelFolderSummary *, FILE *);
@@ -144,7 +144,7 @@ camel_local_summary_construct (CamelLocalSummary *new,
 		g_object_ref (index);
 }
 
-static gint
+static gboolean
 local_summary_load (CamelLocalSummary *cls,
                     gint forceindex,
                     GError **error)
@@ -154,7 +154,7 @@ local_summary_load (CamelLocalSummary *cls,
 }
 
 /* load/check the summary */
-gint
+gboolean
 camel_local_summary_load (CamelLocalSummary *cls,
                           gint forceindex,
                           GError **error)
@@ -166,13 +166,13 @@ camel_local_summary_load (CamelLocalSummary *cls,
 	class = CAMEL_LOCAL_SUMMARY_GET_CLASS (cls);
 
 	if ((forceindex && class->need_index ())
-	    || class->load (cls, forceindex, error) == -1) {
+	    || !class->load (cls, forceindex, error)) {
 		w(g_warning("Could not load summary: flags may be reset"));
-		camel_folder_summary_clear ((CamelFolderSummary *) cls);
-		return -1;
+		camel_folder_summary_clear ((CamelFolderSummary *) cls, NULL);
+		return FALSE;
 	}
 
-	return 0;
+	return TRUE;
 }
 
 void camel_local_summary_check_force (CamelLocalSummary *cls)
@@ -295,13 +295,16 @@ camel_local_summary_check (CamelLocalSummary *cls,
 	if (ret != -1) {
 		gint i;
 		CamelFolderSummary *s = (CamelFolderSummary *) cls;
+		GPtrArray *known_uids;
 		struct _stat_info stats = { 0 };
 
+		known_uids = camel_folder_summary_get_array (s);
 		for (i = 0; i < camel_folder_summary_count (s); i++) {
-			CamelMessageInfo *info = camel_folder_summary_index (s, i);
+			CamelMessageInfo *info = camel_folder_summary_get (s, g_ptr_array_index (known_uids, i));
 			do_stat_mi (cls, &stats, info);
 			camel_message_info_free (info);
 		}
+		camel_folder_summary_free_array (known_uids);
 
 		printf("\nMemory used by summary:\n\n");
 		printf("Total of %d messages\n", camel_folder_summary_count(s));
@@ -456,7 +459,7 @@ local_summary_sync (CamelLocalSummary *cls,
 
 	folder_summary = CAMEL_FOLDER_SUMMARY (cls);
 
-	if (camel_folder_summary_save_to_db (folder_summary, error) == -1) {
+	if (!camel_folder_summary_save_to_db (folder_summary, error)) {
 		g_warning ("Could not save summary for local providers");
 		return -1;
 	}
@@ -475,42 +478,6 @@ local_summary_need_index (void)
 	return 1;
 }
 
-static void
-update_summary (CamelFolderSummary *summary,
-                CamelMessageInfoBase *info,
-                CamelMessageInfoBase *old)
-{
-	gint unread = 0, deleted = 0, junk = 0;
-	guint32 flags = info->flags;
-	guint32 oldflags = old->flags;
-
-	if ((flags & CAMEL_MESSAGE_SEEN) != (oldflags & CAMEL_MESSAGE_SEEN))
-		unread = (oldflags & CAMEL_MESSAGE_SEEN) ? 1 : -1;
-
-	if ((flags & CAMEL_MESSAGE_DELETED) != (oldflags & CAMEL_MESSAGE_DELETED))
-		deleted = (oldflags & CAMEL_MESSAGE_DELETED) ? 1 : -1;
-
-	if ((flags & CAMEL_MESSAGE_JUNK) != (oldflags & CAMEL_MESSAGE_JUNK))
-		junk = (oldflags & CAMEL_MESSAGE_JUNK) ? 1 : -1;
-
-	/* Things would already be flagged */
-
-	if (summary) {
-
-		if (unread)
-			summary->unread_count -= unread;
-		if (deleted)
-			summary->deleted_count += deleted;
-		if (junk)
-			summary->junk_count += junk;
-		if (junk && !deleted)
-			summary->junk_not_deleted_count += junk;
-		if (junk ||  deleted)
-			summary->visible_count -= junk ? junk : deleted;
-	}
-
-}
-
 static CamelMessageInfo *
 local_summary_add (CamelLocalSummary *cls,
                    CamelMimeMessage *msg,
@@ -519,7 +486,6 @@ local_summary_add (CamelLocalSummary *cls,
                    GError **error)
 {
 	CamelLocalMessageInfo *mi;
-	CamelFolderSummary *s = (CamelFolderSummary *) cls;
 	gchar *xev;
 
 	d(printf("Adding message to summary\n"));
@@ -541,8 +507,7 @@ local_summary_add (CamelLocalSummary *cls,
 				tag = tag->next;
 			}
 
-			update_summary (s, (CamelMessageInfoBase *) mi, (CamelMessageInfoBase *) info);
-			mi->info.flags |= (camel_message_info_flags (info) & 0xffff);
+			camel_message_info_set_flags ((CamelMessageInfo *) mi, 0xffff, camel_message_info_flags (info));
 			mi->info.size = camel_message_info_size (info);
 		}
 
@@ -693,7 +658,7 @@ local_summary_decode_x_evolution (CamelLocalSummary *cls,
 	return 0;
 }
 
-static gint
+static gboolean
 summary_header_from_db (CamelFolderSummary *s,
                         CamelFIRecord *fir)
 {
@@ -702,8 +667,8 @@ summary_header_from_db (CamelFolderSummary *s,
 
 	/* We dont actually add our own headers, but version that we don't anyway */
 
-	if (CAMEL_FOLDER_SUMMARY_CLASS (camel_local_summary_parent_class)->summary_header_from_db (s, fir) == -1)
-		return -1;
+	if (!CAMEL_FOLDER_SUMMARY_CLASS (camel_local_summary_parent_class)->summary_header_from_db (s, fir))
+		return FALSE;
 
 	part = fir->bdata;
 	if (part) {
@@ -715,7 +680,7 @@ summary_header_from_db (CamelFolderSummary *s,
 	g_free (fir->bdata);
 	fir->bdata = tmp;
 
-	return 0;
+	return TRUE;
 }
 
 static gint
diff --git a/camel/providers/local/camel-local-summary.h b/camel/providers/local/camel-local-summary.h
index ebcb581..9de024d 100644
--- a/camel/providers/local/camel-local-summary.h
+++ b/camel/providers/local/camel-local-summary.h
@@ -75,7 +75,7 @@ struct _CamelLocalSummary {
 struct _CamelLocalSummaryClass {
 	CamelFolderSummaryClass parent_class;
 
-	gint (*load)(CamelLocalSummary *cls, gint forceindex, GError **error);
+	gboolean (*load)(CamelLocalSummary *cls, gint forceindex, GError **error);
 	gint (*check)(CamelLocalSummary *cls, CamelFolderChangeInfo *changeinfo, GCancellable *cancellable, GError **error);
 	gint (*sync)(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, GCancellable *cancellable, GError **error);
 	CamelMessageInfo *(*add)(CamelLocalSummary *cls, CamelMimeMessage *msg, const CamelMessageInfo *info, CamelFolderChangeInfo *, GError **error);
@@ -89,7 +89,7 @@ GType	camel_local_summary_get_type	(void);
 void	camel_local_summary_construct	(CamelLocalSummary *new, const gchar *filename, const gchar *local_name, CamelIndex *index);
 
 /* load/check the summary */
-gint camel_local_summary_load (CamelLocalSummary *cls, gint forceindex, GError **error);
+gboolean camel_local_summary_load (CamelLocalSummary *cls, gint forceindex, GError **error);
 /* check for new/removed messages */
 gint camel_local_summary_check (CamelLocalSummary *cls, CamelFolderChangeInfo *, GCancellable *cancellable, GError **error);
 /* perform a folder sync or expunge, if needed */
diff --git a/camel/providers/local/camel-maildir-folder.c b/camel/providers/local/camel-maildir-folder.c
index bbae5c2..7483546 100644
--- a/camel/providers/local/camel-maildir-folder.c
+++ b/camel/providers/local/camel-maildir-folder.c
@@ -54,8 +54,8 @@ maildir_folder_cmp_uids (CamelFolder *folder,
 	g_return_val_if_fail (folder != NULL, 0);
 	g_return_val_if_fail (folder->summary != NULL, 0);
 
-	a = camel_folder_summary_uid (folder->summary, uid1);
-	b = camel_folder_summary_uid (folder->summary, uid2);
+	a = camel_folder_summary_get (folder->summary, uid1);
+	b = camel_folder_summary_get (folder->summary, uid2);
 
 	g_return_val_if_fail (a != NULL, 0);
 	g_return_val_if_fail (b != NULL, 0);
@@ -94,7 +94,7 @@ maildir_folder_get_filename (CamelFolder *folder,
 	gchar *res;
 
 	/* get the message summary info */
-	if ((info = camel_folder_summary_uid (folder->summary, uid)) == NULL) {
+	if ((info = camel_folder_summary_get (folder->summary, uid)) == NULL) {
 		set_cannot_get_message_ex (
 			error, CAMEL_FOLDER_ERROR_INVALID_UID,
 			uid, lf->folder_path, _("No such message"));
@@ -327,7 +327,7 @@ maildir_folder_transfer_messages_to_sync (CamelFolder *source,
 			CamelMaildirMessageInfo *mdi;
 			CamelMessageInfo *info;
 
-			if ((info = camel_folder_summary_uid (source->summary, uid)) == NULL) {
+			if ((info = camel_folder_summary_get (source->summary, uid)) == NULL) {
 				set_cannot_get_message_ex (
 					error, CAMEL_FOLDER_ERROR_INVALID_UID,
 					uid, lf->folder_path, _("No such message"));
diff --git a/camel/providers/local/camel-maildir-store.c b/camel/providers/local/camel-maildir-store.c
index 95bc8bc..3a5a2b0 100644
--- a/camel/providers/local/camel-maildir-store.c
+++ b/camel/providers/local/camel-maildir-store.c
@@ -384,9 +384,9 @@ fill_fi (CamelStore *store,
 		}
 
 		s = (CamelFolderSummary *) camel_maildir_summary_new (NULL, path, folderpath, NULL);
-		if (camel_folder_summary_header_load_from_db (s, store, fi->full_name, NULL) != -1) {
-			fi->unread = s->unread_count;
-			fi->total = s->saved_count;
+		if (camel_folder_summary_header_load_from_db (s, store, fi->full_name, NULL)) {
+			fi->unread = camel_folder_summary_get_unread_count (s);
+			fi->total = camel_folder_summary_get_saved_count (s);
 		}
 		g_object_unref (s);
 		g_free (folderpath);
diff --git a/camel/providers/local/camel-maildir-summary.c b/camel/providers/local/camel-maildir-summary.c
index 0024c42..e673df6 100644
--- a/camel/providers/local/camel-maildir-summary.c
+++ b/camel/providers/local/camel-maildir-summary.c
@@ -150,8 +150,7 @@ CamelMaildirSummary
 {
 	CamelMaildirSummary *o;
 
-	o = g_object_new (CAMEL_TYPE_MAILDIR_SUMMARY, NULL);
-	((CamelFolderSummary *) o)->folder = folder;
+	o = g_object_new (CAMEL_TYPE_MAILDIR_SUMMARY, "folder", folder, NULL);
 	if (folder) {
 		CamelStore *parent_store;
 
@@ -289,7 +288,7 @@ message_info_new_from_header (CamelFolderSummary *s,
 			mdi->info.info.uid = camel_pstring_add (camel_folder_summary_next_uid_string (s), TRUE);
 
 		/* handle 'duplicates' */
-		info = camel_folder_summary_peek_info (s, uid);
+		info = camel_folder_summary_peek_loaded (s, uid);
 		if (info) {
 			d(printf("already seen uid '%s', just summarising instead\n", uid));
 			camel_message_info_free (mi);
@@ -550,6 +549,7 @@ maildir_summary_check (CamelLocalSummary *cls,
 	gchar *new, *cur;
 	gchar *uid;
 	struct _remove_data rd = { cls, changes };
+	GPtrArray *known_uids;
 
 	g_mutex_lock (((CamelMaildirSummary *) cls)->priv->summary_lock);
 
@@ -580,10 +580,10 @@ maildir_summary_check (CamelLocalSummary *cls,
 	/* keeps track of all uid's that have not been processed */
 	left = g_hash_table_new (g_str_hash, g_str_equal);
 	camel_folder_summary_prepare_fetch_all (s, error);
-	count = camel_folder_summary_count (s);
-	forceindex = count == 0;
-	for (i = 0; i < count; i++) {
-		info = camel_folder_summary_index ((CamelFolderSummary *) cls, i);
+	known_uids = camel_folder_summary_get_array (s);
+	forceindex = !known_uids || known_uids->len == 0;
+	for (i = 0; known_uids && i < known_uids->len; i++) {
+		info = camel_folder_summary_get ((CamelFolderSummary *) cls, g_ptr_array_index (known_uids, i));
 		if (info) {
 			g_hash_table_insert (left, (gchar *) camel_message_info_uid (info), info);
 		}
@@ -620,7 +620,7 @@ maildir_summary_check (CamelLocalSummary *cls,
 			g_hash_table_remove (left, uid);
 		}
 
-		info = camel_folder_summary_uid ((CamelFolderSummary *) cls, uid);
+		info = camel_folder_summary_get ((CamelFolderSummary *) cls, uid);
 		if (info == NULL) {
 			/* must be a message incorporated by another client, this is not a 'recent' uid */
 			if (camel_maildir_summary_add (cls, d->d_name, forceindex, cancellable) == 0)
@@ -676,7 +676,7 @@ maildir_summary_check (CamelLocalSummary *cls,
 				continue;
 
 			/* already in summary?  shouldn't happen, but just incase ... */
-			if ((info = camel_folder_summary_uid ((CamelFolderSummary *) cls, name))) {
+			if ((info = camel_folder_summary_get ((CamelFolderSummary *) cls, name))) {
 				camel_message_info_free (info);
 				newname = destname = camel_folder_summary_next_uid_string (s);
 			} else {
@@ -720,6 +720,7 @@ maildir_summary_check (CamelLocalSummary *cls,
 	g_free (new);
 	g_free (cur);
 
+	camel_folder_summary_free_array (known_uids);
 	g_mutex_unlock (((CamelMaildirSummary *) cls)->priv->summary_lock);
 
 	return 0;
@@ -734,11 +735,12 @@ maildir_summary_sync (CamelLocalSummary *cls,
                       GError **error)
 {
 	CamelLocalSummaryClass *local_summary_class;
-	gint count, i;
+	gint i;
 	CamelMessageInfo *info;
 	CamelMaildirMessageInfo *mdi;
 	gchar *name;
 	struct stat st;
+	GPtrArray *known_uids;
 
 	d(printf("summary_sync(expunge=%s)\n", expunge?"true":"false"));
 
@@ -748,11 +750,11 @@ maildir_summary_sync (CamelLocalSummary *cls,
 	camel_operation_push_message (cancellable, _("Storing folder"));
 
 	camel_folder_summary_prepare_fetch_all ((CamelFolderSummary *) cls, error);
-	count = camel_folder_summary_count ((CamelFolderSummary *) cls);
-	for (i = count - 1; i >= 0; i--) {
-		camel_operation_progress (cancellable, (count - i) * 100 / count);
+	known_uids = camel_folder_summary_get_array ((CamelFolderSummary *) cls);
+	for (i = (known_uids ? known_uids->len : 0) - 1; i >= 0; i--) {
+		camel_operation_progress (cancellable, (known_uids->len - i) * 100 / known_uids->len);
 
-		info = camel_folder_summary_index ((CamelFolderSummary *) cls, i);
+		info = camel_folder_summary_get ((CamelFolderSummary *) cls, g_ptr_array_index (known_uids, i));
 		mdi = (CamelMaildirMessageInfo *) info;
 		if (mdi && (mdi->info.info.flags & CAMEL_MESSAGE_DELETED) && expunge) {
 			name = g_strdup_printf("%s/cur/%s", cls->folder_path, camel_maildir_info_filename(mdi));
@@ -801,6 +803,7 @@ maildir_summary_sync (CamelLocalSummary *cls,
 		camel_message_info_free (info);
 	}
 
+	camel_folder_summary_free_array (known_uids);
 	camel_operation_pop_message (cancellable);
 
 	/* Chain up to parent's sync() method. */
diff --git a/camel/providers/local/camel-mbox-folder.c b/camel/providers/local/camel-mbox-folder.c
index f31fcfc..c5d3725 100644
--- a/camel/providers/local/camel-mbox-folder.c
+++ b/camel/providers/local/camel-mbox-folder.c
@@ -59,8 +59,8 @@ mbox_folder_cmp_uids (CamelFolder *folder,
 	g_return_val_if_fail (folder != NULL, 0);
 	g_return_val_if_fail (folder->summary != NULL, 0);
 
-	a = (CamelMboxMessageInfo *) camel_folder_summary_uid (folder->summary, uid1);
-	b = (CamelMboxMessageInfo *) camel_folder_summary_uid (folder->summary, uid2);
+	a = (CamelMboxMessageInfo *) camel_folder_summary_get (folder->summary, uid1);
+	b = (CamelMboxMessageInfo *) camel_folder_summary_get (folder->summary, uid2);
 
 	g_return_val_if_fail (a != NULL, 0);
 	g_return_val_if_fail (b != NULL, 0);
@@ -109,7 +109,7 @@ mbox_folder_get_filename (CamelFolder *folder,
 	}
 
 	/* get the message summary info */
-	info = (CamelMboxMessageInfo *) camel_folder_summary_uid (folder->summary, uid);
+	info = (CamelMboxMessageInfo *) camel_folder_summary_get (folder->summary, uid);
 
 	if (info == NULL) {
 		set_cannot_get_message_ex (
@@ -317,7 +317,7 @@ mbox_folder_get_message_sync (CamelFolder *folder,
 
 retry:
 	/* get the message summary info */
-	info = (CamelMboxMessageInfo *) camel_folder_summary_uid (folder->summary, uid);
+	info = (CamelMboxMessageInfo *) camel_folder_summary_get (folder->summary, uid);
 
 	if (info == NULL) {
 		set_cannot_get_message_ex (
diff --git a/camel/providers/local/camel-mbox-store.c b/camel/providers/local/camel-mbox-store.c
index f08ce83..9a39c30 100644
--- a/camel/providers/local/camel-mbox-store.c
+++ b/camel/providers/local/camel-mbox-store.c
@@ -130,9 +130,9 @@ fill_fi (CamelStore *store,
 
 		mbs = (CamelMboxSummary *) camel_mbox_summary_new (NULL, path, folderpath, NULL);
 		/* FIXME[disk-summary] track exception */
-		if (camel_folder_summary_header_load_from_db ((CamelFolderSummary *) mbs, store, fi->full_name, NULL) != -1) {
-			fi->unread = ((CamelFolderSummary *) mbs)->unread_count;
-			fi->total = ((CamelFolderSummary *) mbs)->saved_count;
+		if (camel_folder_summary_header_load_from_db ((CamelFolderSummary *) mbs, store, fi->full_name, NULL)) {
+			fi->unread = camel_folder_summary_get_unread_count ((CamelFolderSummary *) mbs);
+			fi->total = camel_folder_summary_get_saved_count ((CamelFolderSummary *) mbs);
 		}
 
 		g_object_unref (mbs);
diff --git a/camel/providers/local/camel-mbox-summary.c b/camel/providers/local/camel-mbox-summary.c
index 4be93e7..dca35d5 100644
--- a/camel/providers/local/camel-mbox-summary.c
+++ b/camel/providers/local/camel-mbox-summary.c
@@ -44,7 +44,7 @@
 #define CAMEL_MBOX_SUMMARY_VERSION (1)
 
 static CamelFIRecord * summary_header_to_db (CamelFolderSummary *, GError **error);
-static gint summary_header_from_db (CamelFolderSummary *, CamelFIRecord *);
+static gboolean summary_header_from_db (CamelFolderSummary *, CamelFIRecord *);
 static CamelMessageInfo * message_info_from_db (CamelFolderSummary *s, CamelMIRecord *record);
 static CamelMIRecord * message_info_to_db (CamelFolderSummary *s, CamelMessageInfo *info);
 
@@ -186,8 +186,7 @@ camel_mbox_summary_new (CamelFolder *folder,
 {
 	CamelMboxSummary *new;
 
-	new = g_object_new (CAMEL_TYPE_MBOX_SUMMARY, NULL);
-	((CamelFolderSummary *) new)->folder = folder;
+	new = g_object_new (CAMEL_TYPE_MBOX_SUMMARY, "folder", folder, NULL);
 	if (folder) {
 		CamelFolderSummary *summary = (CamelFolderSummary *) new;
 		CamelStore *parent_store;
@@ -228,14 +227,15 @@ mbox_summary_encode_x_evolution (CamelLocalSummary *cls,
 	}
 }
 
-static gint
+static gboolean
 summary_header_from_db (CamelFolderSummary *s,
                         struct _CamelFIRecord *fir)
 {
 	CamelMboxSummary *mbs = CAMEL_MBOX_SUMMARY (s);
 	gchar *part;
 
-	CAMEL_FOLDER_SUMMARY_CLASS (camel_mbox_summary_parent_class)->summary_header_from_db (s, fir);
+	if (!CAMEL_FOLDER_SUMMARY_CLASS (camel_mbox_summary_parent_class)->summary_header_from_db (s, fir))
+		return FALSE;
 
 	part = fir->bdata;
 	if (part) {
@@ -243,7 +243,7 @@ summary_header_from_db (CamelFolderSummary *s,
 		mbs->folder_size = bdata_extract_digit (&part);
 	}
 
-	return 0;
+	return TRUE;
 }
 
 static gint
@@ -335,7 +335,7 @@ message_info_new_from_header (CamelFolderSummary *s,
 			uid = camel_message_info_uid (mi);
 			d(printf("found valid x-evolution: %s\n", uid));
 			/* If one is there, it should be there already */
-			info = (CamelMboxMessageInfo *) camel_folder_summary_peek_info (s, uid);
+			info = (CamelMboxMessageInfo *) camel_folder_summary_peek_loaded (s, uid);
 			if (info) {
 				if ((info->info.info.flags & CAMEL_MESSAGE_FOLDER_NOTSEEN)) {
 					info->info.info.flags &= ~CAMEL_MESSAGE_FOLDER_NOTSEEN;
@@ -360,7 +360,7 @@ message_info_new_from_header (CamelFolderSummary *s,
 			camel_pstring_free (mi->info.info.uid);
 			mi->info.info.uid = camel_pstring_add (camel_folder_summary_next_uid_string (s), TRUE);
 		} else {
-			camel_folder_summary_set_uid (s, strtoul (camel_message_info_uid (mi), NULL, 10));
+			camel_folder_summary_set_next_uid (s, strtoul (camel_message_info_uid (mi), NULL, 10));
 		}
 #ifdef STATUS_PINE
 		if (mbs->xstatus && add&2) {
@@ -465,7 +465,7 @@ summary_update (CamelLocalSummary *cls,
                 GCancellable *cancellable,
                 GError **error)
 {
-	gint i, count;
+	gint i;
 	CamelFolderSummary *s = (CamelFolderSummary *) cls;
 	CamelMboxSummary *mbs = (CamelMboxSummary *) cls;
 	CamelMimeParser *mp;
@@ -477,6 +477,7 @@ summary_update (CamelLocalSummary *cls,
 	struct stat st;
 	goffset size = 0;
 	GList *del = NULL;
+	GPtrArray *known_uids;
 
 	d(printf("Calling summary update, from pos %d\n", (gint)offset));
 
@@ -522,15 +523,16 @@ summary_update (CamelLocalSummary *cls,
 	 * If we're not starting from the start, we must be starting
 	 * from the old end, so everything must be treated as new */
 	camel_folder_summary_prepare_fetch_all (s, NULL);
-	count = camel_folder_summary_count (s);
-	for (i = 0; i < count; i++) {
-		mi = (CamelMboxMessageInfo *) camel_folder_summary_index (s, i);
+	known_uids = camel_folder_summary_get_array (s);
+	for (i = 0; known_uids && i < known_uids->len; i++) {
+		mi = (CamelMboxMessageInfo *) camel_folder_summary_get (s, g_ptr_array_index (known_uids, i));
 		if (offset == 0)
 			mi->info.info.flags |= CAMEL_MESSAGE_FOLDER_NOTSEEN;
 		else
 			mi->info.info.flags &= ~CAMEL_MESSAGE_FOLDER_NOTSEEN;
 		camel_message_info_free (mi);
 	}
+	camel_folder_summary_free_array (known_uids);
 	mbs->changes = changeinfo;
 
 	while (camel_mime_parser_step (mp, NULL, NULL) == CAMEL_MIME_PARSER_STATE_FROM) {
@@ -565,39 +567,34 @@ summary_update (CamelLocalSummary *cls,
 
 	g_object_unref (mp);
 
-	count = camel_folder_summary_count (s);
-	for (i = 0; i < count; i++) {
-		mi = (CamelMboxMessageInfo *) camel_folder_summary_index (s, i);
-		/* must've dissapeared from the file? */
-		if (!mi || mi->info.info.flags & CAMEL_MESSAGE_FOLDER_NOTSEEN) {
-			gchar *uid;
-
-			if (mi)
-				uid = g_strdup (camel_message_info_uid (mi));
-			else
-				uid = camel_folder_summary_uid_from_index (s, i);
+	known_uids = camel_folder_summary_get_array (s);
+	for (i = 0; known_uids && i < known_uids->len; i++) {
+		const gchar *uid;
 
-			if (!uid) {
-				g_debug ("%s: didn't get uid at %d of %d (%d)", G_STRFUNC, i, count, camel_folder_summary_count (s));
-				continue;
-			}
+		uid = g_ptr_array_index (known_uids, i);
+		if (!uid)
+			continue;
 
+		mi = (CamelMboxMessageInfo *) camel_folder_summary_get (s, uid);
+		/* must've dissapeared from the file? */
+		if (!mi || mi->info.info.flags & CAMEL_MESSAGE_FOLDER_NOTSEEN) {
 			d(printf("uid '%s' vanished, removing", uid));
 			if (changeinfo)
 				camel_folder_change_info_remove_uid (changeinfo, uid);
 			del = g_list_prepend (del, (gpointer) camel_pstring_strdup (uid));
-			camel_folder_summary_remove_index_fast (s, i);
-			count--;
-			i--;
-			g_free (uid);
+			camel_folder_summary_remove_uid (s, uid);
 		}
+
 		if (mi)
 			camel_message_info_free (mi);
 	}
 
+	if (known_uids)
+		camel_folder_summary_free_array (known_uids);
+
 	/* Delete all in one transaction */
-	full_name = camel_folder_get_full_name (s->folder);
-	parent_store = camel_folder_get_parent_store (s->folder);
+	full_name = camel_folder_get_full_name (camel_folder_summary_get_folder (s));
+	parent_store = camel_folder_get_parent_store (camel_folder_summary_get_folder (s));
 	camel_db_delete_uids (parent_store->cdb_w, full_name, del, NULL);
 	g_list_foreach (del, (GFunc) camel_pstring_free, NULL);
 	g_list_free (del);
@@ -629,7 +626,7 @@ mbox_summary_check (CamelLocalSummary *cls,
 	CamelFolderSummary *s = (CamelFolderSummary *) cls;
 	struct stat st;
 	gint ret = 0;
-	gint i, count;
+	gint i;
 
 	d(printf("Checking summary\n"));
 
@@ -637,7 +634,7 @@ mbox_summary_check (CamelLocalSummary *cls,
 
 	/* check if the summary is up-to-date */
 	if (g_stat (cls->folder_path, &st) == -1) {
-		camel_folder_summary_clear (s);
+		camel_folder_summary_clear (s, NULL);
 		camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
 		g_set_error (
 			error, G_IO_ERROR,
@@ -652,19 +649,22 @@ mbox_summary_check (CamelLocalSummary *cls,
 	cls->check_force = 0;
 
 	if (st.st_size == 0) {
+		GPtrArray *known_uids;
+
 		/* empty?  No need to scan at all */
 		d(printf("Empty mbox, clearing summary\n"));
 		camel_folder_summary_prepare_fetch_all (s, NULL);
-		count= camel_folder_summary_count (s);
-		for (i = 0; i < count; i++) {
-			CamelMessageInfo *info = camel_folder_summary_index (s, i);
+		known_uids = camel_folder_summary_get_array (s);
+		for (i = 0; known_uids && i < known_uids->len; i++) {
+			CamelMessageInfo *info = camel_folder_summary_get (s, g_ptr_array_index (known_uids, i));
 
 			if (info) {
 				camel_folder_change_info_remove_uid (changes, camel_message_info_uid (info));
 				camel_message_info_free (info);
 			}
 		}
-		camel_folder_summary_clear (s);
+		camel_folder_summary_free_array (known_uids);
+		camel_folder_summary_clear (s, NULL);
 		ret = 0;
 	} else {
 		/* is the summary uptodate? */
@@ -822,8 +822,8 @@ cms_sort_frompos (gpointer a,
 	gint ret = 0;
 
 	/* Things are in memory already. Sorting speeds up syncing, if things are sorted by from pos. */
-	info1 = (CamelMboxMessageInfo *) camel_folder_summary_uid (summary, *(gchar **) a);
-	info2 = (CamelMboxMessageInfo *) camel_folder_summary_uid (summary, *(gchar **) b);
+	info1 = (CamelMboxMessageInfo *) camel_folder_summary_get (summary, *(gchar **) a);
+	info2 = (CamelMboxMessageInfo *) camel_folder_summary_get (summary, *(gchar **) b);
 
 	if (info1->frompos > info2->frompos)
 		ret = 1;
@@ -905,7 +905,7 @@ mbox_summary_sync_quick (CamelMboxSummary *mbs,
 
 		camel_operation_progress (cancellable, pc);
 
-		info = (CamelMboxMessageInfo *) camel_folder_summary_uid (s, summary->pdata[i]);
+		info = (CamelMboxMessageInfo *) camel_folder_summary_get (s, summary->pdata[i]);
 
 		d(printf("Checking message %s %08x\n", camel_message_info_uid(info), ((CamelMessageInfoBase *)info)->flags));
 
@@ -1040,14 +1040,14 @@ mbox_summary_sync (CamelLocalSummary *cls,
 		return -1;
 	}
 
-	full_name = camel_folder_get_full_name (s->folder);
-	parent_store = camel_folder_get_parent_store (s->folder);
+	full_name = camel_folder_get_full_name (camel_folder_summary_get_folder (s));
+	parent_store = camel_folder_get_parent_store (camel_folder_summary_get_folder (s));
 
 	/* Sync only the changes */
 
 	summary = camel_folder_summary_get_changed ((CamelFolderSummary *) mbs);
 	for (i = 0; i < summary->len; i++) {
-		CamelMboxMessageInfo *info = (CamelMboxMessageInfo *) camel_folder_summary_uid (s, summary->pdata[i]);
+		CamelMboxMessageInfo *info = (CamelMboxMessageInfo *) camel_folder_summary_get (s, summary->pdata[i]);
 
 		if ((expunge && (info->info.info.flags & CAMEL_MESSAGE_DELETED)) ||
 		    (info->info.info.flags & (CAMEL_MESSAGE_FOLDER_NOXEV | CAMEL_MESSAGE_FOLDER_XEVCHANGE)))
@@ -1127,7 +1127,7 @@ camel_mbox_summary_sync_mbox (CamelMboxSummary *cls,
 	CamelMimeParser *mp = NULL;
 	CamelStore *parent_store;
 	const gchar *full_name;
-	gint i, count;
+	gint i;
 	CamelMboxMessageInfo *info = NULL;
 	gchar *buffer, *xevnew = NULL;
 	gsize len;
@@ -1135,6 +1135,7 @@ camel_mbox_summary_sync_mbox (CamelMboxSummary *cls,
 	gint lastdel = FALSE;
 	gboolean touched = FALSE;
 	GList *del = NULL;
+	GPtrArray *known_uids = NULL;
 #ifdef STATUS_PINE
 	gchar statnew[8], xstatnew[8];
 #endif
@@ -1161,13 +1162,13 @@ camel_mbox_summary_sync_mbox (CamelMboxSummary *cls,
 	camel_mime_parser_init_with_fd (mp, fd);
 
 	camel_folder_summary_prepare_fetch_all (s, NULL);
-	count = camel_folder_summary_count (s);
-	for (i = 0; i < count; i++) {
-		gint pc = (i + 1) * 100 / count;
+	known_uids = camel_folder_summary_get_array (s);
+	for (i = 0; known_uids && i < known_uids->len; i++) {
+		gint pc = (i + 1) * 100 / known_uids->len;
 
 		camel_operation_progress (cancellable, pc);
 
-		info = (CamelMboxMessageInfo *) camel_folder_summary_index (s, i);
+		info = (CamelMboxMessageInfo *) camel_folder_summary_get (s, g_ptr_array_index (known_uids, i));
 
 		if (!info)
 			continue;
@@ -1197,28 +1198,16 @@ camel_mbox_summary_sync_mbox (CamelMboxSummary *cls,
 		lastdel = FALSE;
 		if ((flags&1) && info->info.info.flags & CAMEL_MESSAGE_DELETED) {
 			const gchar *uid = camel_message_info_uid (info);
-			guint32 flags = camel_message_info_flags (info);
-			gint read, junk;
 			d(printf("Deleting %s\n", uid));
 
 			if (((CamelLocalSummary *) cls)->index)
 				camel_index_delete_name (((CamelLocalSummary *) cls)->index, uid);
 
 			/* remove it from the change list */
-			junk = flags & CAMEL_MESSAGE_JUNK;
-			read = flags & CAMEL_MESSAGE_SEEN;
-			s->saved_count--;
-			if (junk)
-				s->junk_count--;
-			if (!read)
-				s->unread_count--;
-			s->deleted_count--;
 			camel_folder_change_info_remove_uid (changeinfo, uid);
-			camel_folder_summary_remove_index_fast (s, i);
+			camel_folder_summary_remove_uid (s, uid);
 			del = g_list_prepend (del, (gpointer) camel_pstring_strdup (uid));
 			camel_message_info_free ((CamelMessageInfo *) info);
-			count--;
-			i--;
 			info = NULL;
 			lastdel = TRUE;
 			touched = TRUE;
@@ -1303,8 +1292,8 @@ camel_mbox_summary_sync_mbox (CamelMboxSummary *cls,
 		}
 	}
 
-	full_name = camel_folder_get_full_name (s->folder);
-	parent_store = camel_folder_get_parent_store (s->folder);
+	full_name = camel_folder_get_full_name (camel_folder_summary_get_folder (s));
+	parent_store = camel_folder_get_parent_store (camel_folder_summary_get_folder (s));
 	camel_db_delete_uids (parent_store->cdb_w, full_name, del, NULL);
 	g_list_foreach (del, (GFunc) camel_pstring_free, NULL);
 	g_list_free (del);
@@ -1318,8 +1307,8 @@ camel_mbox_summary_sync_mbox (CamelMboxSummary *cls,
 	g_object_unref (mp);
 
 	/* clear working flags */
-	for (i = 0; i < count; i++) {
-		info = (CamelMboxMessageInfo *) camel_folder_summary_index (s, i);
+	for (i = 0; known_uids && i < known_uids->len; i++) {
+		info = (CamelMboxMessageInfo *) camel_folder_summary_get (s, g_ptr_array_index (known_uids, i));
 		if (info) {
 			if (info->info.info.flags & (CAMEL_MESSAGE_FOLDER_NOXEV | CAMEL_MESSAGE_FOLDER_FLAGGED | CAMEL_MESSAGE_FOLDER_XEVCHANGE)) {
 				info->info.info.flags &= ~(CAMEL_MESSAGE_FOLDER_NOXEV
@@ -1333,6 +1322,8 @@ camel_mbox_summary_sync_mbox (CamelMboxSummary *cls,
 		}
 	}
 
+	camel_folder_summary_free_array (known_uids);
+
 	if (touched)
 		camel_folder_summary_header_save_to_db (s, NULL);
 
@@ -1347,6 +1338,7 @@ camel_mbox_summary_sync_mbox (CamelMboxSummary *cls,
 	if (info)
 		camel_message_info_free ((CamelMessageInfo *) info);
 
+	camel_folder_summary_free_array (known_uids);
 	camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
 
 	return -1;
diff --git a/camel/providers/local/camel-mh-folder.c b/camel/providers/local/camel-mh-folder.c
index f8b6286..b99f283 100644
--- a/camel/providers/local/camel-mh-folder.c
+++ b/camel/providers/local/camel-mh-folder.c
@@ -150,7 +150,7 @@ mh_folder_get_message_sync (CamelFolder *folder,
 		return NULL;
 
 	/* get the message summary info */
-	if ((info = camel_folder_summary_uid (folder->summary, uid)) == NULL) {
+	if ((info = camel_folder_summary_get (folder->summary, uid)) == NULL) {
 		set_cannot_get_message_ex (
 			error, CAMEL_FOLDER_ERROR_INVALID_UID,
 			uid, lf->folder_path, _("No such message"));
diff --git a/camel/providers/local/camel-mh-store.c b/camel/providers/local/camel-mh-store.c
index 0f3baab..2c7d221 100644
--- a/camel/providers/local/camel-mh-store.c
+++ b/camel/providers/local/camel-mh-store.c
@@ -218,9 +218,9 @@ fill_fi (CamelStore *store,
 		s = (CamelFolderSummary *) camel_mh_summary_new (
 			NULL, path, folderpath, NULL);
 		if (camel_folder_summary_header_load_from_db (
-			s, store, fi->full_name, NULL) != -1) {
-			fi->unread = s->unread_count;
-			fi->total = s->saved_count;
+			s, store, fi->full_name, NULL)) {
+			fi->unread = camel_folder_summary_get_unread_count (s);
+			fi->total = camel_folder_summary_get_saved_count (s);
 		}
 		g_object_unref (s);
 		g_free (folderpath);
diff --git a/camel/providers/local/camel-mh-summary.c b/camel/providers/local/camel-mh-summary.c
index ada6ee5..2d9de03 100644
--- a/camel/providers/local/camel-mh-summary.c
+++ b/camel/providers/local/camel-mh-summary.c
@@ -98,8 +98,7 @@ camel_mh_summary_new (CamelFolder *folder,
 {
 	CamelMhSummary *o;
 
-	o = g_object_new (CAMEL_TYPE_MH_SUMMARY, NULL);
-	((CamelFolderSummary *) o)->folder = folder;
+	o = g_object_new (CAMEL_TYPE_MH_SUMMARY, "folder", folder, NULL);
 	if (folder) {
 		CamelStore *parent_store;
 
@@ -127,7 +126,7 @@ mh_summary_next_uid_string (CamelFolderSummary *s)
 	if (mhs->priv->current_uid) {
 		uidstr = g_strdup (mhs->priv->current_uid);
 		/* tell the summary of this, so we always append numbers to the end */
-		camel_folder_summary_set_uid (s, strtoul (uidstr, NULL, 10) + 1);
+		camel_folder_summary_set_next_uid (s, strtoul (uidstr, NULL, 10) + 1);
 	} else {
 		/* else scan for one - and create it too, to make sure */
 		do {
@@ -210,8 +209,9 @@ mh_summary_check (CamelLocalSummary *cls,
 	CamelMessageInfo *info;
 	CamelFolderSummary *s = (CamelFolderSummary *) cls;
 	GHashTable *left;
-	gint i, count;
-	gint forceindex;
+	gint i;
+	gboolean forceindex;
+	GPtrArray *known_uids;
 
 	/* FIXME: Handle changeinfo */
 
@@ -232,14 +232,15 @@ mh_summary_check (CamelLocalSummary *cls,
 	/* keeps track of all uid's that have not been processed */
 	left = g_hash_table_new (g_str_hash, g_str_equal);
 	camel_folder_summary_prepare_fetch_all ((CamelFolderSummary *) cls, error);
-	count = camel_folder_summary_count ((CamelFolderSummary *) cls);
-	forceindex = count == 0;
-	for (i = 0; i < count; i++) {
-		info = camel_folder_summary_index ((CamelFolderSummary *) cls, i);
+	known_uids = camel_folder_summary_get_array ((CamelFolderSummary *) cls);
+	forceindex = !known_uids || known_uids->len == 0;
+	for (i = 0; known_uids && i < known_uids->len; i++) {
+		info = camel_folder_summary_get ((CamelFolderSummary *) cls, g_ptr_array_index (known_uids, i));
 		if (info) {
 			g_hash_table_insert (left, (gchar *) camel_message_info_uid (info), info);
 		}
 	}
+	camel_folder_summary_free_array (known_uids);
 
 	while ((d = readdir (dir))) {
 		/* FIXME: also run stat to check for regular file */
@@ -249,7 +250,7 @@ mh_summary_check (CamelLocalSummary *cls,
 				break;
 		}
 		if (c == 0) {
-			info = camel_folder_summary_uid ((CamelFolderSummary *) cls, d->d_name);
+			info = camel_folder_summary_get ((CamelFolderSummary *) cls, d->d_name);
 			if (info == NULL || (cls->index && (!camel_index_has_name (cls->index, d->d_name)))) {
 				/* need to add this file to the summary */
 				if (info != NULL) {
@@ -290,7 +291,8 @@ mh_summary_sync (CamelLocalSummary *cls,
                  GError **error)
 {
 	CamelLocalSummaryClass *local_summary_class;
-	gint count, i;
+	gint i;
+	GPtrArray *known_uids;
 	CamelLocalMessageInfo *info;
 	gchar *name;
 	const gchar *uid;
@@ -305,9 +307,9 @@ mh_summary_sync (CamelLocalSummary *cls,
 	/* FIXME: need to update/honour .mh_sequences or whatever it is */
 
 	camel_folder_summary_prepare_fetch_all ((CamelFolderSummary *) cls, error);
-	count = camel_folder_summary_count ((CamelFolderSummary *) cls);
-	for (i = count - 1; i >= 0; i--) {
-		info = (CamelLocalMessageInfo *) camel_folder_summary_index ((CamelFolderSummary *) cls, i);
+	known_uids = camel_folder_summary_get_array ((CamelFolderSummary *) cls);
+	for (i = (known_uids ? known_uids->len : 0) - 1; i >= 0; i--) {
+		info = (CamelLocalMessageInfo *) camel_folder_summary_get ((CamelFolderSummary *) cls, g_ptr_array_index (known_uids, i));
 		g_assert (info);
 		if (expunge && (info->info.flags & CAMEL_MESSAGE_DELETED)) {
 			uid = camel_message_info_uid (info);
diff --git a/camel/providers/local/camel-spool-summary.c b/camel/providers/local/camel-spool-summary.c
index 3d5f6ad..222a48d 100644
--- a/camel/providers/local/camel-spool-summary.c
+++ b/camel/providers/local/camel-spool-summary.c
@@ -86,8 +86,7 @@ camel_spool_summary_new (CamelFolder *folder,
 {
 	CamelSpoolSummary *new;
 
-	new = g_object_new (CAMEL_TYPE_SPOOL_SUMMARY, NULL);
-	((CamelFolderSummary *) new)->folder = folder;
+	new = g_object_new (CAMEL_TYPE_SPOOL_SUMMARY, "folder", folder, NULL);
 	if (folder) {
 		CamelStore *parent_store;
 
@@ -310,9 +309,11 @@ spool_summary_check (CamelLocalSummary *cls,
                      GCancellable *cancellable,
                      GError **error)
 {
-	gint i, work, count;
+	gint i;
+	gboolean work;
 	struct stat st;
 	CamelFolderSummary *s = (CamelFolderSummary *) cls;
+	GPtrArray *known_uids;
 
 	if (CAMEL_LOCAL_SUMMARY_CLASS (camel_spool_summary_parent_class)->check (cls, changeinfo, cancellable, error) == -1)
 		return -1;
@@ -320,13 +321,14 @@ spool_summary_check (CamelLocalSummary *cls,
 	/* check to see if we need to copy/update the file; missing xev headers prompt this */
 	work = FALSE;
 	camel_folder_summary_prepare_fetch_all (s, error);
-	count = camel_folder_summary_count (s);
-	for (i = 0; !work && i < count; i++) {
-		CamelMboxMessageInfo *info = (CamelMboxMessageInfo *) camel_folder_summary_index (s, i);
+	known_uids = camel_folder_summary_get_array (s);
+	for (i = 0; !work && known_uids && i < known_uids->len; i++) {
+		CamelMboxMessageInfo *info = (CamelMboxMessageInfo *) camel_folder_summary_get (s, g_ptr_array_index (known_uids, i));
 		g_assert (info);
 		work = (info->info.info.flags & (CAMEL_MESSAGE_FOLDER_NOXEV)) != 0;
 		camel_message_info_free ((CamelMessageInfo *) info);
 	}
+	camel_folder_summary_free_array (known_uids);
 
 	/* if we do, then write out the headers using sync_full, etc */
 	if (work) {
diff --git a/camel/providers/nntp/camel-nntp-folder.c b/camel/providers/nntp/camel-nntp-folder.c
index 37bebfd..2881df4 100644
--- a/camel/providers/nntp/camel-nntp-folder.c
+++ b/camel/providers/nntp/camel-nntp-folder.c
@@ -42,11 +42,19 @@ G_DEFINE_TYPE (CamelNNTPFolder, camel_nntp_folder, CAMEL_TYPE_DISCO_FOLDER)
 static void
 nntp_folder_dispose (GObject *object)
 {
+	CamelStore *parent_store;
 	CamelNNTPFolder *nntp_folder = CAMEL_NNTP_FOLDER (object);
 
 	camel_folder_summary_save_to_db (
 		CAMEL_FOLDER (nntp_folder)->summary, NULL);
 
+	parent_store = camel_folder_get_parent_store (CAMEL_FOLDER (nntp_folder));
+	if (parent_store) {
+		camel_store_summary_disconnect_folder_summary (
+			(CamelStoreSummary *) ((CamelNNTPStore *) parent_store)->summary,
+			CAMEL_FOLDER (nntp_folder)->summary);
+	}
+
 	/* Chain up to parent's dispose() method. */
 	G_OBJECT_CLASS (camel_nntp_folder_parent_class)->dispose (object);
 }
@@ -140,7 +148,7 @@ unset_flagged_flag (const gchar *uid,
 {
 	CamelMessageInfo *info;
 
-	info = camel_folder_summary_uid (summary, uid);
+	info = camel_folder_summary_get (summary, uid);
 	if (info) {
 		CamelMessageInfoBase *base = (CamelMessageInfoBase *) info;
 
@@ -738,5 +746,9 @@ camel_nntp_folder_new (CamelStore *parent,
 		folder = NULL;
 	}
 
+	camel_store_summary_connect_folder_summary (
+		(CamelStoreSummary *) ((CamelNNTPStore *) parent)->summary,
+		folder_name, folder->summary);
+
 	return folder;
 }
diff --git a/camel/providers/nntp/camel-nntp-summary.c b/camel/providers/nntp/camel-nntp-summary.c
index 105d47e..f8c02e3 100644
--- a/camel/providers/nntp/camel-nntp-summary.c
+++ b/camel/providers/nntp/camel-nntp-summary.c
@@ -56,7 +56,7 @@ struct _CamelNNTPSummaryPrivate {
 static CamelMessageInfo * message_info_new_from_header (CamelFolderSummary *, struct _camel_header_raw *);
 static gint summary_header_load (CamelFolderSummary *, FILE *);
 static gint summary_header_save (CamelFolderSummary *, FILE *);
-static gint summary_header_from_db (CamelFolderSummary *s, CamelFIRecord *mir);
+static gboolean summary_header_from_db (CamelFolderSummary *s, CamelFIRecord *mir);
 static CamelFIRecord * summary_header_to_db (CamelFolderSummary *s, GError **error);
 
 G_DEFINE_TYPE (CamelNNTPSummary, camel_nntp_summary, CAMEL_TYPE_FOLDER_SUMMARY)
@@ -97,8 +97,7 @@ camel_nntp_summary_new (CamelFolder *folder,
 {
 	CamelNNTPSummary *cns;
 
-	cns = g_object_new (CAMEL_TYPE_NNTP_SUMMARY, NULL);
-	((CamelFolderSummary *) cns)->folder = folder;
+	cns = g_object_new (CAMEL_TYPE_NNTP_SUMMARY, "folder", folder, NULL);
 
 	camel_folder_summary_set_filename ((CamelFolderSummary *) cns, path);
 	camel_folder_summary_set_build_content ((CamelFolderSummary *) cns, FALSE);
@@ -128,15 +127,15 @@ message_info_new_from_header (CamelFolderSummary *s,
 	return (CamelMessageInfo *) mi;
 }
 
-static gint
+static gboolean
 summary_header_from_db (CamelFolderSummary *s,
                         CamelFIRecord *mir)
 {
 	CamelNNTPSummary *cns = CAMEL_NNTP_SUMMARY (s);
 	gchar *part;
 
-	if (CAMEL_FOLDER_SUMMARY_CLASS (camel_nntp_summary_parent_class)->summary_header_from_db (s, mir) == -1)
-		return -1;
+	if (!CAMEL_FOLDER_SUMMARY_CLASS (camel_nntp_summary_parent_class)->summary_header_from_db (s, mir))
+		return FALSE;
 
 	part = mir->bdata;
 
@@ -144,7 +143,7 @@ summary_header_from_db (CamelFolderSummary *s,
 	cns->high = bdata_extract_digit (&part);
 	cns->low = bdata_extract_digit (&part);
 
-	return 0;
+	return TRUE;
 }
 
 static gint
@@ -229,10 +228,8 @@ add_range_xover (CamelNNTPSummary *cns,
 	gint ret;
 	guint n, count, total, size;
 	struct _xover_header *xover;
-	GHashTable *summary_table;
 
 	s = (CamelFolderSummary *) cns;
-	summary_table = camel_folder_summary_get_hashtable (s);
 
 	url = camel_service_get_camel_url (CAMEL_SERVICE (store));
 
@@ -301,7 +298,7 @@ add_range_xover (CamelNNTPSummary *cns,
 
 		/* truncated line? ignore? */
 		if (xover == NULL) {
-			if (!GPOINTER_TO_INT (g_hash_table_lookup (summary_table, cns->priv->uid))) {
+			if (!camel_folder_summary_check_uid (s, cns->priv->uid)) {
 				mi = (CamelMessageInfoBase *)
 					camel_folder_summary_add_from_header (s, headers);
 				if (mi) {
@@ -322,8 +319,6 @@ add_range_xover (CamelNNTPSummary *cns,
 
 	camel_operation_pop_message (cancellable);
 
-	camel_folder_summary_free_hashtable (summary_table);
-
 	return ret;
 }
 
@@ -344,12 +339,9 @@ add_range_head (CamelNNTPSummary *cns,
 	guint i, n, count, total;
 	CamelMessageInfo *mi;
 	CamelMimeParser *mp;
-	GHashTable *summary_table;
 
 	s = (CamelFolderSummary *) cns;
 
-	summary_table = camel_folder_summary_get_hashtable (s);
-
 	mp = camel_mime_parser_new ();
 
 	url = camel_service_get_camel_url (CAMEL_SERVICE (store));
@@ -384,7 +376,7 @@ add_range_head (CamelNNTPSummary *cns,
 		if ((msgid = strchr (line, '<')) && (line = strchr (msgid + 1, '>'))) {
 			line[1] = 0;
 			cns->priv->uid = g_strdup_printf ("%u,%s\n", n, msgid);
-			if (!GPOINTER_TO_INT (g_hash_table_lookup (summary_table, cns->priv->uid))) {
+			if (!camel_folder_summary_check_uid (s, cns->priv->uid)) {
 				if (camel_mime_parser_init_with_stream (mp, (CamelStream *) store->stream, error) == -1)
 					goto error;
 				mi = camel_folder_summary_add_from_parser (s, mp);
@@ -429,8 +421,6 @@ ioerror:
 
 	camel_operation_pop_message (cancellable);
 
-	camel_folder_summary_free_hashtable (summary_table);
-
 	return ret;
 }
 
@@ -456,8 +446,8 @@ camel_nntp_summary_check (CamelNNTPSummary *cns,
 
 	s = (CamelFolderSummary *) cns;
 
-	full_name = camel_folder_get_full_name (s->folder);
-	parent_store = camel_folder_get_parent_store (s->folder);
+	full_name = camel_folder_get_full_name (camel_folder_summary_get_folder (s));
+	parent_store = camel_folder_get_parent_store (camel_folder_summary_get_folder (s));
 
 	line +=3;
 	n = strtoul (line, &line, 10);
@@ -484,36 +474,37 @@ camel_nntp_summary_check (CamelNNTPSummary *cns,
 
 	/* Check for messages no longer on the server */
 	if (cns->low != f) {
-		count = camel_folder_summary_count (s);
-		for (i = 0; i < count; i++) {
-			gchar *uid;
-			const gchar *msgid;
-
-			uid  = camel_folder_summary_uid_from_index (s, i);
-			n = strtoul (uid, NULL, 10);
-
-			if (n < f || n > l) {
-				dd (printf ("nntp_summary: %u is lower/higher than lowest/highest article, removed\n", n));
-				/* Since we use a global cache this could prematurely remove
-				 * a cached message that might be in another folder - not that important as
-				 * it is a true cache */
-				msgid = strchr (uid, ',');
-				if (msgid)
-					camel_data_cache_remove (store->cache, "cache", msgid+1, NULL);
-				camel_folder_change_info_remove_uid (changes, uid);
-				del = g_list_prepend (del, uid);
-				camel_folder_summary_remove_uid_fast (s, uid);
-				uid = NULL; /*Lets not free it */
-				count--;
-				i--;
+		GPtrArray *known_uids;
+
+		known_uids = camel_folder_summary_get_array (s);
+		if (known_uids) {
+			for (i = 0; i < known_uids->len; i++) {
+				const gchar *uid;
+				const gchar *msgid;
+
+				uid  = g_ptr_array_index (known_uids, i);
+				n = strtoul (uid, NULL, 10);
+
+				if (n < f || n > l) {
+					dd (printf ("nntp_summary: %u is lower/higher than lowest/highest article, removed\n", n));
+					/* Since we use a global cache this could prematurely remove
+					 * a cached message that might be in another folder - not that important as
+					 * it is a true cache */
+					msgid = strchr (uid, ',');
+					if (msgid)
+						camel_data_cache_remove (store->cache, "cache", msgid + 1, NULL);
+					camel_folder_change_info_remove_uid (changes, uid);
+					del = g_list_prepend (del, (gpointer) camel_pstring_strdup (uid));
+					camel_folder_summary_remove_uid (s, uid);
+				}
 			}
-			g_free (uid);
+			camel_folder_summary_free_array (known_uids);
 		}
 		cns->low = f;
 	}
 
 	camel_db_delete_uids (parent_store->cdb_w, full_name, del, NULL);
-	g_list_foreach (del, (GFunc) g_free, NULL);
+	g_list_foreach (del, (GFunc) camel_pstring_free, NULL);
 	g_list_free (del);
 
 	if (cns->high < l) {



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