evolution-data-server r9125 - in trunk: . camel camel/db-scrap-tools camel/providers/groupwise camel/providers/imap camel/providers/local camel/providers/nntp libedataserver



Author: psankar
Date: Wed Jul 16 11:38:32 2008
New Revision: 9125
URL: http://svn.gnome.org/viewvc/evolution-data-server?rev=9125&view=rev

Log:
Pushing the on-disk summary changes from the madagascar branch



Added:
   trunk/camel/camel-db.c
   trunk/camel/camel-db.h
   trunk/camel/db-scrap-tools/
   trunk/camel/db-scrap-tools/db.c
Modified:
   trunk/ChangeLog
   trunk/camel/ChangeLog
   trunk/camel/Makefile.am
   trunk/camel/camel-folder-search.c
   trunk/camel/camel-folder-search.h
   trunk/camel/camel-folder-summary.c
   trunk/camel/camel-folder-summary.h
   trunk/camel/camel-folder-thread.c
   trunk/camel/camel-folder.c
   trunk/camel/camel-folder.h
   trunk/camel/camel-offline-journal.c
   trunk/camel/camel-store.c
   trunk/camel/camel-store.h
   trunk/camel/camel-string-utils.c
   trunk/camel/camel-vee-folder.c
   trunk/camel/camel-vee-store.c
   trunk/camel/camel-vee-summary.c
   trunk/camel/camel-vee-summary.h
   trunk/camel/camel-vtrash-folder.c
   trunk/camel/providers/groupwise/ChangeLog
   trunk/camel/providers/groupwise/camel-groupwise-folder.c
   trunk/camel/providers/groupwise/camel-groupwise-store.c
   trunk/camel/providers/groupwise/camel-groupwise-summary.c
   trunk/camel/providers/imap/ChangeLog
   trunk/camel/providers/imap/camel-imap-folder.c
   trunk/camel/providers/imap/camel-imap-message-cache.c
   trunk/camel/providers/imap/camel-imap-store.c
   trunk/camel/providers/imap/camel-imap-summary.c
   trunk/camel/providers/imap/camel-imap-utils.c
   trunk/camel/providers/local/ChangeLog
   trunk/camel/providers/local/camel-local-folder.c
   trunk/camel/providers/local/camel-local-store.c
   trunk/camel/providers/local/camel-local-summary.c
   trunk/camel/providers/local/camel-maildir-summary.c
   trunk/camel/providers/local/camel-mbox-store.c
   trunk/camel/providers/local/camel-mbox-summary.c
   trunk/camel/providers/local/camel-mh-summary.c
   trunk/camel/providers/nntp/ChangeLog
   trunk/camel/providers/nntp/camel-nntp-folder.c
   trunk/camel/providers/nntp/camel-nntp-summary.c
   trunk/camel/providers/nntp/camel-nntp-utils.c
   trunk/configure.in
   trunk/libedataserver/e-sexp.c
   trunk/libedataserver/e-sexp.h

Modified: trunk/camel/Makefile.am
==============================================================================
--- trunk/camel/Makefile.am	(original)
+++ trunk/camel/Makefile.am	Wed Jul 16 11:38:32 2008
@@ -156,6 +156,7 @@
 	camel-charset-map.c			\
 	camel-data-cache.c			\
 	camel-data-wrapper.c			\
+	camel-db.c				\
 	camel-debug.c				\
 	camel-exception.c			\
 	camel-file-utils.c			\
@@ -226,6 +227,7 @@
 	camel-charset-map.h			\
 	camel-data-cache.h			\
 	camel-data-wrapper.h			\
+	camel-db.h				\
 	camel-debug.h				\
 	camel-exception-list.def		\
 	camel-exception.h			\

Added: trunk/camel/camel-db.c
==============================================================================
--- (empty file)
+++ trunk/camel/camel-db.c	Wed Jul 16 11:38:32 2008
@@ -0,0 +1,956 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* camel-imap-folder.c: class for an imap folder */
+
+/* 
+ * Authors:
+ *   Sankar P <psankar novell com>
+ *   Srinivasa Ragavan <sragavan novell com> 
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ * This program is free software; you can redistribute it and/or 
+ * modify it under the terms of version 2 of the GNU Lesser General Public 
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ */
+
+
+#include "camel-db.h"
+#include "camel-string-utils.h"
+
+#include <config.h>
+
+#include <string.h>
+#include <stdlib.h>
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+
+#define d(x) 
+
+#define CAMEL_DB_SLEEP_INTERVAL 1*10*10
+#define CAMEL_DB_RELEASE_SQLITE_MEMORY if(!g_getenv("CAMEL_SQLITE_PRESERVE_CACHE")) sqlite3_release_memory(CAMEL_DB_FREE_CACHE_SIZE);
+#define CAMEL_DB_USE_SHARED_CACHE if(!g_getenv("CAMEL_SQLITE_SHARED_CACHE_OFF")) sqlite3_enable_shared_cache(TRUE);
+
+static int 
+cdb_sql_exec (sqlite3 *db, const char* stmt, CamelException *ex) 
+{
+	char *errmsg;
+	int   ret = -1;
+
+	d(g_print("Camel SQL Exec:\n%s\n", stmt));
+
+	ret = sqlite3_exec(db, stmt, 0, 0, &errmsg);
+	while (ret == SQLITE_BUSY || ret == SQLITE_LOCKED || ret == -1) {
+		ret = sqlite3_exec(db, stmt, 0, 0, &errmsg);
+	}
+	
+	if (ret != SQLITE_OK) {
+		d(g_print ("Error in SQL EXEC statement: %s [%s].\n", stmt, errmsg));
+		if (ex)	
+			camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _(errmsg));
+		sqlite3_free (errmsg);
+		return -1;
+	}
+	return 0;
+}
+
+CamelDB *
+camel_db_open (const char *path, CamelException *ex)
+{
+	CamelDB *cdb;
+	sqlite3 *db;
+	char *cache;
+	int ret;
+
+	CAMEL_DB_USE_SHARED_CACHE;
+	
+	sqlite3_enable_shared_cache(TRUE);
+
+	ret = sqlite3_open(path, &db);
+	if (ret) {
+
+		if (!db) {
+			camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Insufficient memory"));
+		} else {
+			const char *error;
+			error = sqlite3_errmsg (db);
+			d(g_print("Can't open database %s: %s\n", path, error));
+			camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _(error));
+			sqlite3_close(db);
+		}
+		return NULL;
+	}
+
+
+
+	cdb = g_new (CamelDB, 1);
+	cdb->db = db;
+	cdb->lock = g_mutex_new ();
+	d(g_print ("\nDatabase succesfully opened  \n"));
+
+	/* Which is big / costlier ? A Stack frame or a pointer */
+	if(!g_getenv("CAMEL_SQLITE_DEFAULT_CACHE_SIZE")) 
+		cache = g_strdup_printf ("PRAGMA cache_size=%s", g_getenv("CAMEL_SQLITE_DEFAULT_CACHE_SIZE"));
+	else 
+		cache = g_strdup ("PRAGMA cache_size=100");
+
+	camel_db_command (cdb, cache, NULL);
+
+	g_free (cache);
+
+	sqlite3_busy_timeout (cdb->db, CAMEL_DB_SLEEP_INTERVAL);
+
+	return cdb;
+}
+
+void
+camel_db_close (CamelDB *cdb)
+{
+	if (cdb) {
+		sqlite3_close (cdb->db);
+		g_mutex_free (cdb->lock);
+		g_free (cdb);
+		d(g_print ("\nDatabase succesfully closed \n"));
+	}
+}
+
+/* Should this be really exposed ? */
+int
+camel_db_command (CamelDB *cdb, const char *stmt, CamelException *ex)
+{
+	int ret;
+	
+	if (!cdb)
+		return TRUE;
+	g_mutex_lock (cdb->lock);
+	d(g_print("Executing: %s\n", stmt));
+	ret = cdb_sql_exec (cdb->db, stmt, ex);
+	g_mutex_unlock (cdb->lock);
+	return ret;
+}
+
+
+int 
+camel_db_begin_transaction (CamelDB *cdb, CamelException *ex)
+{
+	if (!cdb)
+		return -1;
+
+	d(g_print ("\n\aBEGIN TRANSACTION \n\a"));
+	g_mutex_lock (cdb->lock);
+	return (cdb_sql_exec (cdb->db, "BEGIN", ex));
+}
+
+int 
+camel_db_end_transaction (CamelDB *cdb, CamelException *ex)
+{
+	int ret;
+	if (!cdb)
+		return -1;
+
+	d(g_print ("\nCOMMIT TRANSACTION \n"));
+	ret = cdb_sql_exec (cdb->db, "COMMIT", ex);
+	g_mutex_unlock (cdb->lock);
+	CAMEL_DB_RELEASE_SQLITE_MEMORY;
+	
+	return ret;
+}
+
+int
+camel_db_abort_transaction (CamelDB *cdb, CamelException *ex)
+{
+	int ret;
+	
+	d(g_print ("\nABORT TRANSACTION \n"));
+	ret = cdb_sql_exec (cdb->db, "ROLLBACK", ex);
+	g_mutex_unlock (cdb->lock);
+	CAMEL_DB_RELEASE_SQLITE_MEMORY;
+	
+	return ret;
+}
+
+int
+camel_db_add_to_transaction (CamelDB *cdb, const char *stmt, CamelException *ex)
+{
+	if (!cdb)
+		return -1;
+
+	d(g_print("Adding the following query to transaction: %s\n", stmt));
+
+	return (cdb_sql_exec (cdb->db, stmt, ex));
+}
+
+int 
+camel_db_transaction_command (CamelDB *cdb, GSList *qry_list, CamelException *ex)
+{
+	int ret;
+	const char *query;
+
+	if (!cdb)
+		return -1;
+
+	g_mutex_lock (cdb->lock);
+
+	ret = cdb_sql_exec (cdb->db, "BEGIN", ex);
+	if (ret)
+		goto end;
+
+	d(g_print ("\nBEGIN Transaction\n"));
+
+	while (qry_list) {
+		query = qry_list->data;
+		d(g_print ("\nInside Transaction: [%s] \n", query));
+		ret = cdb_sql_exec (cdb->db, query, ex);
+		if (ret)
+			goto end;
+		qry_list = g_slist_next (qry_list);
+	}
+
+	ret = cdb_sql_exec (cdb->db, "COMMIT", ex);
+
+end:
+	g_mutex_unlock (cdb->lock);
+	d(g_print ("\nTransaction Result: [%d] \n", ret));
+	return ret;
+}
+
+static int 
+count_cb (void *data, int argc, char **argv, char **azColName)
+{
+  	int i;
+
+  	for(i=0; i<argc; i++) {
+		if (strstr(azColName[i], "COUNT")) {
+			*(guint32 *)data = argv [i] ? strtoul (argv [i], NULL, 10) : 0;
+		}
+  	}
+
+  	return 0;
+}
+
+static int
+camel_db_count_message_info (CamelDB *cdb, const char *query, guint32 *count, CamelException *ex)
+{
+	int ret = -1;
+	char *errmsg;
+
+	ret = sqlite3_exec(cdb->db, query, count_cb, count, &errmsg);
+	while (ret == SQLITE_BUSY || ret == SQLITE_LOCKED) {
+		ret = sqlite3_exec (cdb->db, query, count_cb, count, &errmsg);
+	}
+
+	CAMEL_DB_RELEASE_SQLITE_MEMORY;
+		
+	if (ret != SQLITE_OK) {
+			g_print ("Error in SQL SELECT statement: %s [%s]\n", query, errmsg);
+			camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _(errmsg));
+			sqlite3_free (errmsg);
+	}
+	return ret;
+}
+
+int
+camel_db_count_junk_message_info (CamelDB *cdb, const char *table_name, guint32 *count, CamelException *ex)
+{
+	int ret;
+
+	if (!cdb)
+		return -1;
+
+	char *query;
+	query = sqlite3_mprintf ("SELECT COUNT (*) FROM %Q WHERE junk = 1", table_name);
+
+	ret = camel_db_count_message_info (cdb, query, count, ex);
+	sqlite3_free (query);
+
+	return ret;
+}
+
+int
+camel_db_count_unread_message_info (CamelDB *cdb, const char *table_name, guint32 *count, CamelException *ex)
+{
+	int ret;
+
+	if (!cdb)
+		return -1;
+
+	char *query;
+	query = sqlite3_mprintf ("SELECT COUNT (*) FROM %Q WHERE read = 0", table_name);
+
+	ret = camel_db_count_message_info (cdb, query, count, ex);
+	sqlite3_free (query);
+
+	return ret;
+}
+
+int
+camel_db_count_visible_unread_message_info (CamelDB *cdb, const char *table_name, guint32 *count, CamelException *ex)
+{
+	int ret;
+
+	if (!cdb)
+		return -1;
+
+	char *query;
+	query = sqlite3_mprintf ("SELECT COUNT (*) FROM %Q WHERE read = 0 AND junk = 0 AND deleted = 0", table_name);
+
+	ret = camel_db_count_message_info (cdb, query, count, ex);
+	sqlite3_free (query);
+
+	return ret;
+}
+
+int
+camel_db_count_visible_message_info (CamelDB *cdb, const char *table_name, guint32 *count, CamelException *ex)
+{
+	int ret;
+
+	if (!cdb)
+		return -1;
+
+	char *query;
+	query = sqlite3_mprintf ("SELECT COUNT (*) FROM %Q WHERE junk = 0 AND deleted = 0", table_name);
+
+	ret = camel_db_count_message_info (cdb, query, count, ex);
+	sqlite3_free (query);
+
+	return ret;
+}
+
+int
+camel_db_count_junk_not_deleted_message_info (CamelDB *cdb, const char *table_name, guint32 *count, CamelException *ex)
+{
+	int ret;
+
+	if (!cdb)
+		return -1;
+
+	char *query ;
+	query = sqlite3_mprintf ("SELECT COUNT (*) FROM %Q WHERE junk = 1 AND deleted = 0", table_name);
+
+	ret = camel_db_count_message_info (cdb, query, count, ex);
+	sqlite3_free (query);
+
+	return ret;
+}
+
+int
+camel_db_count_deleted_message_info (CamelDB *cdb, const char *table_name, guint32 *count, CamelException *ex)
+{
+	int ret;
+
+	if (!cdb)
+		return -1;
+
+	char *query ;
+	query = sqlite3_mprintf ("SELECT COUNT (*) FROM %Q WHERE deleted = 1", table_name);
+
+	ret = camel_db_count_message_info (cdb, query, count, ex);
+	sqlite3_free (query);
+
+	return ret;
+}
+
+
+int
+camel_db_count_total_message_info (CamelDB *cdb, const char *table_name, guint32 *count, CamelException *ex)
+{
+
+	int ret;
+	char *query;
+
+	if (!cdb)
+		return -1;
+	
+	query = sqlite3_mprintf ("SELECT COUNT (*) FROM %Q", table_name);
+
+	ret = camel_db_count_message_info (cdb, query, count, ex);
+	sqlite3_free (query);
+
+	return ret;
+}
+
+int
+camel_db_select (CamelDB *cdb, const char* stmt, CamelDBSelectCB callback, gpointer data, CamelException *ex) 
+{
+  	char *errmsg;
+  	//int nrecs = 0;
+	int ret = -1;
+
+	if (!cdb)
+		return TRUE;
+	
+	d(g_print ("\n%s:\n%s \n", __FUNCTION__, stmt));
+
+	ret = sqlite3_exec(cdb->db, stmt, callback, data, &errmsg);
+	while (ret == SQLITE_BUSY || ret == SQLITE_LOCKED) {
+		ret = sqlite3_exec (cdb->db, stmt, callback, data, &errmsg);
+	}
+
+	CAMEL_DB_RELEASE_SQLITE_MEMORY;
+		
+  	if (ret != SQLITE_OK) {
+    		d(g_warning ("Error in select statement '%s' [%s].\n", stmt, errmsg));
+		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, errmsg);
+		sqlite3_free (errmsg);
+  	}
+
+	return ret;
+}
+
+int
+camel_db_delete_folder (CamelDB *cdb, const char *folder, CamelException *ex)
+{
+	char *tab = sqlite3_mprintf ("DELETE FROM folders WHERE folder_name =%Q", folder);
+	int ret;
+
+	ret = camel_db_command (cdb, tab, ex);
+	sqlite3_free (tab);
+	CAMEL_DB_RELEASE_SQLITE_MEMORY;
+	return ret;
+}
+
+int
+camel_db_create_vfolder (CamelDB *db, const char *folder_name, CamelException *ex)
+{
+	int ret;
+	char *table_creation_query, *safe_index;
+	
+	table_creation_query = sqlite3_mprintf ("CREATE TABLE IF NOT EXISTS %Q (  vuid TEXT PRIMARY KEY)", folder_name);
+
+	ret = camel_db_command (db, table_creation_query, ex);	
+
+	sqlite3_free (table_creation_query);
+
+
+	safe_index = g_strdup_printf("VINDEX-%s", folder_name);
+	table_creation_query = sqlite3_mprintf ("CREATE INDEX IF NOT EXISTS %Q ON %Q (vuid)", safe_index, folder_name);
+	ret = camel_db_command (db, table_creation_query, ex);
+
+	sqlite3_free (table_creation_query);
+	g_free (safe_index);
+	CAMEL_DB_RELEASE_SQLITE_MEMORY;
+	
+	return ret;	 
+}
+
+int
+camel_db_delete_uid_from_vfolder (CamelDB *db, char *folder_name, char *vuid, CamelException *ex)
+{
+	 char *del_query;
+	 int ret;
+	 
+	 del_query = sqlite3_mprintf ("DELETE FROM %Q WHERE vuid = %Q", folder_name, vuid);
+
+	 ret = camel_db_command (db, del_query, ex);
+	 
+	 sqlite3_free (del_query);
+	 CAMEL_DB_RELEASE_SQLITE_MEMORY;
+	 return ret;
+}
+
+static int
+read_uids_callback (void *ref, int ncol, char ** cols, char ** name)
+{
+	GPtrArray *array = (GPtrArray *) ref;
+	 
+	#if 0
+	int i;
+	for (i = 0; i < ncol; ++i) {
+		if (!strcmp (name [i], "uid"))
+			g_ptr_array_add (array, (char *) (camel_pstring_strdup(cols [i])));
+	}
+	#else
+			g_ptr_array_add (array, (char *) (camel_pstring_strdup(cols [0])));
+	#endif
+	 
+	 return 0;
+}
+
+int
+camel_db_get_folder_uids (CamelDB *db, char *folder_name, GPtrArray *array, CamelException *ex)
+{
+	 char *sel_query;
+	 int ret;
+	 
+	 sel_query = sqlite3_mprintf("SELECT uid FROM %Q", folder_name);
+
+	 ret = camel_db_select (db, sel_query, read_uids_callback, array, ex);
+	 sqlite3_free (sel_query);
+
+	 return ret;
+}
+
+GPtrArray *
+camel_db_get_folder_junk_uids (CamelDB *db, char *folder_name, CamelException *ex)
+{
+	 char *sel_query;
+	 int ret;
+	 GPtrArray *array = g_ptr_array_new();
+	 
+	 sel_query = sqlite3_mprintf("SELECT uid FROM %Q where junk=1", folder_name);
+
+	 ret = camel_db_select (db, sel_query, read_uids_callback, array, ex);
+	 sqlite3_free (sel_query);
+
+	 if (!array->len) {
+		 g_ptr_array_free (array, TRUE);
+		 array = NULL;
+	 } 
+	 return array;
+}
+
+GPtrArray *
+camel_db_get_folder_deleted_uids (CamelDB *db, char *folder_name, CamelException *ex)
+{
+	 char *sel_query;
+	 int ret;
+	 GPtrArray *array = g_ptr_array_new();
+	 
+	 sel_query = sqlite3_mprintf("SELECT uid FROM %Q where deleted=1", folder_name);
+
+	 ret = camel_db_select (db, sel_query, read_uids_callback, array, ex);
+	 sqlite3_free (sel_query);
+
+	 if (!array->len) {
+		 g_ptr_array_free (array, TRUE);
+		 array = NULL;
+	 }
+		 
+	 return array;
+}
+
+static int
+read_vuids_callback (void *ref, int ncol, char ** cols, char ** name)
+{
+	 GPtrArray *array = (GPtrArray *)ref;
+	 
+	 #if 0
+	 int i;
+	 
+
+	 for (i = 0; i < ncol; ++i) {
+		  if (!strcmp (name [i], "vuid"))
+			   g_ptr_array_add (array, (char *) (camel_pstring_strdup(cols [i]+8)));
+	 }
+	 #else
+			   g_ptr_array_add (array, (char *) (camel_pstring_strdup(cols [0]+8)));
+	 #endif
+
+	 return 0;
+}
+
+GPtrArray *
+camel_db_get_vuids_from_vfolder (CamelDB *db, char *folder_name, char *filter, CamelException *ex)
+{
+	 char *sel_query;
+	 char *cond = NULL;
+	 GPtrArray *array;
+	 char *tmp = g_strdup_printf("%s%%", filter ? filter:"");
+	 if(filter) 
+		  cond = sqlite3_mprintf("WHERE vuid LIKE %Q", tmp);
+	 g_free(tmp);
+	 sel_query = sqlite3_mprintf("SELECT vuid FROM %Q%s", folder_name, filter ? cond : "");
+
+	 if (cond)
+		  sqlite3_free (cond);
+	 #warning "handle return values"
+	 #warning "No The caller should parse the ex in case of NULL returns" 
+	 array = g_ptr_array_new ();
+	 camel_db_select (db, sel_query, read_vuids_callback, array, ex);
+	 sqlite3_free (sel_query);
+	 /* We make sure to return NULL if we don't get anything. Be good to your caller */ 
+	 if (!array->len) {
+		  g_ptr_array_free (array, TRUE);
+		  array = NULL;
+	 }
+
+	 return array;
+}
+
+int
+camel_db_add_to_vfolder (CamelDB *db, char *folder_name, char *vuid, CamelException *ex)
+{
+	 char *del_query, *ins_query;
+	 int ret;
+	 
+	 ins_query = sqlite3_mprintf ("INSERT INTO %Q VALUES (%Q)", folder_name, vuid);
+	 del_query = sqlite3_mprintf ("DELETE FROM %Q WHERE vuid = %Q", folder_name, vuid);
+
+	 ret = camel_db_command (db, del_query, ex);
+	 ret = camel_db_command (db, ins_query, ex);
+	 
+	 sqlite3_free (ins_query);
+	 sqlite3_free (del_query);
+	 CAMEL_DB_RELEASE_SQLITE_MEMORY;
+	 return ret;
+}
+
+int
+camel_db_add_to_vfolder_transaction (CamelDB *db, char *folder_name, char *vuid, CamelException *ex)
+{
+	 char *del_query, *ins_query;
+	 int ret;
+	 
+	 ins_query = sqlite3_mprintf ("INSERT INTO %Q VALUES (%Q)", folder_name, vuid);
+	 del_query = sqlite3_mprintf ("DELETE FROM %Q WHERE vuid = %Q", folder_name, vuid);
+
+	 ret = camel_db_add_to_transaction (db, del_query, ex);
+	 ret = camel_db_add_to_transaction (db, ins_query, ex);
+	 
+	 sqlite3_free (ins_query);
+	 sqlite3_free (del_query);
+
+	 return ret;
+}
+
+
+int
+camel_db_create_folders_table (CamelDB *cdb, CamelException *ex)
+{
+	char *query = "CREATE TABLE IF NOT EXISTS folders ( folder_name TEXT PRIMARY KEY, version REAL, flags INTEGER, nextuid INTEGER, time NUMERIC, saved_count INTEGER, unread_count INTEGER, deleted_count INTEGER, junk_count INTEGER, visible_count INTEGER, jnd_count INTEGER, bdata TEXT )";
+	CAMEL_DB_RELEASE_SQLITE_MEMORY;
+	return ((camel_db_command (cdb, query, ex)));
+}
+
+int 
+camel_db_prepare_message_info_table (CamelDB *cdb, const char *folder_name, CamelException *ex)
+{
+	int ret;
+	char *table_creation_query, *safe_index;
+
+	/* README: It is possible to compress all system flags into a single column and use just as userflags but that makes querying for other applications difficult an d bloats the parsing code. Instead, it is better to bloat the tables. Sqlite should have some optimizations for sparse columns etc. */
+
+	table_creation_query = sqlite3_mprintf ("CREATE TABLE IF NOT EXISTS %Q (  uid TEXT PRIMARY KEY , flags INTEGER , msg_type INTEGER , read INTEGER , deleted INTEGER , replied INTEGER , important INTEGER , junk INTEGER , attachment INTEGER , msg_security INTEGER , size INTEGER , dsent NUMERIC , dreceived NUMERIC , subject TEXT , mail_from TEXT , mail_to TEXT , mail_cc TEXT , mlist TEXT , followup_flag TEXT , followup_completed_on TEXT , followup_due_by TEXT , part TEXT , labels TEXT , usertags TEXT , cinfo TEXT , bdata TEXT )", folder_name);
+
+	ret = camel_db_add_to_transaction (cdb, table_creation_query, ex);
+
+	sqlite3_free (table_creation_query);
+
+	/* FIXME: sqlize folder_name before you create the index */
+	safe_index = g_strdup_printf("SINDEX-%s", folder_name);
+	table_creation_query = sqlite3_mprintf ("CREATE INDEX IF NOT EXISTS %Q ON %Q (uid, flags, size, dsent, dreceived, subject, mail_from, mail_to, mail_cc, mlist, part, labels, usertags, cinfo)", safe_index, folder_name);
+	ret = camel_db_add_to_transaction (cdb, table_creation_query, ex);
+	g_free (safe_index);
+	sqlite3_free (table_creation_query);
+	
+	return ret;
+}
+
+int
+camel_db_write_message_info_record (CamelDB *cdb, const char *folder_name, CamelMIRecord *record, CamelException *ex)
+{
+	int ret;
+	char *del_query;
+	char *ins_query;
+
+	ins_query = sqlite3_mprintf ("INSERT INTO %Q VALUES (%Q, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %ld, %ld, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %Q )", 
+			folder_name, record->uid, record->flags,
+			record->msg_type, record->read, record->deleted, record->replied,
+			record->important, record->junk, record->attachment, record->msg_security,
+			record->size, record->dsent, record->dreceived,
+			record->subject, record->from, record->to,
+			record->cc, record->mlist, record->followup_flag,
+			record->followup_completed_on, record->followup_due_by, 
+			record->part, record->labels, record->usertags,
+			record->cinfo, record->bdata);
+
+	del_query = sqlite3_mprintf ("DELETE FROM %Q WHERE uid = %Q", folder_name, record->uid);
+
+#if 0
+	char *upd_query;
+
+	upd_query = g_strdup_printf ("IMPLEMENT AND THEN TRY");
+	camel_db_command (cdb, upd_query, ex);
+	g_free (upd_query);
+#else
+
+	ret = camel_db_add_to_transaction (cdb, del_query, ex);
+	ret = camel_db_add_to_transaction (cdb, ins_query, ex);
+
+#endif
+
+	sqlite3_free (del_query);
+	sqlite3_free (ins_query);
+
+	return ret;
+}
+
+int
+camel_db_write_folder_info_record (CamelDB *cdb, CamelFIRecord *record, CamelException *ex)
+{
+	int ret;
+
+	char *del_query;
+	char *ins_query;
+
+	ins_query = sqlite3_mprintf ("INSERT INTO folders VALUES ( %Q, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %Q ) ", 
+			record->folder_name, record->version,
+								 record->flags, record->nextuid, record->time,
+			record->saved_count, record->unread_count,
+								 record->deleted_count, record->junk_count, record->visible_count, record->jnd_count, record->bdata); 
+
+	del_query = sqlite3_mprintf ("DELETE FROM folders WHERE folder_name = %Q", record->folder_name);
+
+
+#if 0
+	char *upd_query;
+	
+	upd_query = g_strdup_printf ("UPDATE folders SET version = %d, flags = %d, nextuid = %d, time = 143, saved_count = %d, unread_count = %d, deleted_count = %d, junk_count = %d, bdata = %s, WHERE folder_name = %Q", record->version, record->flags, record->nextuid, record->saved_count, record->unread_count, record->deleted_count, record->junk_count, "PROVIDER SPECIFIC DATA", record->folder_name );
+	camel_db_command (cdb, upd_query, ex);
+	g_free (upd_query);
+#else
+
+	ret = camel_db_add_to_transaction (cdb, del_query, ex);
+	ret = camel_db_add_to_transaction (cdb, ins_query, ex);
+
+#endif
+
+	sqlite3_free (del_query);
+	sqlite3_free (ins_query);
+
+	return ret;
+}
+
+static int 
+read_fir_callback (void * ref, int ncol, char ** cols, char ** name)
+{
+	CamelFIRecord *record = *(CamelFIRecord **) ref;
+
+	d(g_print ("\nread_fir_callback called \n"));
+#if 0
+	record->folder_name = cols [0];
+	record->version = cols [1];
+	/* Just a sequential mapping of struct members to columns is enough I guess. 
+	Needs some checking */
+#else
+	int i;
+	
+	for (i = 0; i < ncol; ++i) {
+		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]);
+	
+	}
+#endif 
+	return 0;
+}
+
+int
+camel_db_read_folder_info_record (CamelDB *cdb, const char *folder_name, CamelFIRecord **record, CamelException *ex)
+{
+	char *query;
+	int ret;
+
+	query = sqlite3_mprintf ("SELECT * FROM folders WHERE folder_name = %Q", folder_name);
+	ret = camel_db_select (cdb, query, read_fir_callback, record, ex);
+
+	sqlite3_free (query);
+	return (ret);
+}
+
+int
+camel_db_read_message_info_record_with_uid (CamelDB *cdb, const char *folder_name, const char *uid, gpointer p, CamelDBSelectCB read_mir_callback, CamelException *ex)
+{
+	char *query;
+	int ret;
+
+	query = sqlite3_mprintf ("SELECT uid, flags, size, dsent, dreceived, subject, mail_from, mail_to, mail_cc, mlist, part, labels, usertags, cinfo, bdata FROM %Q WHERE uid = %Q", folder_name, uid);
+	ret = camel_db_select (cdb, query, read_mir_callback, p, ex);
+	sqlite3_free (query);
+
+	return (ret);
+}
+
+int
+camel_db_read_message_info_records (CamelDB *cdb, const char *folder_name, gpointer p, CamelDBSelectCB read_mir_callback, CamelException *ex)
+{
+	char *query;
+	int ret;
+
+	query = sqlite3_mprintf ("SELECT uid, flags, size, dsent, dreceived, subject, mail_from, mail_to, mail_cc, mlist, part, labels, usertags, cinfo, bdata FROM %Q ", folder_name);
+	ret = camel_db_select (cdb, query, read_mir_callback, p, ex);
+	sqlite3_free (query);
+
+	return (ret);
+}
+
+int
+camel_db_delete_uid (CamelDB *cdb, const char *folder, const char *uid, CamelException *ex)
+{
+	char *tab = sqlite3_mprintf ("DELETE FROM %Q WHERE uid = %Q", folder, uid);
+	int ret;
+
+	ret = camel_db_command (cdb, tab, ex);
+	sqlite3_free (tab);
+	CAMEL_DB_RELEASE_SQLITE_MEMORY;
+	return ret;
+}
+
+int
+camel_db_delete_uids (CamelDB *cdb, const char * folder_name, GSList *uids, CamelException *ex)
+{
+	char *tmp;
+	int ret;
+	gboolean first = TRUE;
+	GString *str = g_string_new ("DELETE FROM ");
+	GSList *iterator;
+
+	tmp = sqlite3_mprintf ("%Q WHERE uid IN (", folder_name); 
+	g_string_append_printf (str, "%s ", tmp);
+	sqlite3_free (tmp);
+
+	iterator = uids;
+
+	while (iterator) {
+		tmp = sqlite3_mprintf ("%Q", (char *) iterator->data);
+		iterator = iterator->next;
+
+		if (first == TRUE) {
+			g_string_append_printf (str, " %s ", tmp);
+			first = FALSE;
+		} else
+			g_string_append_printf (str, ", %s ", tmp);
+
+		sqlite3_free (tmp);
+	}
+
+	g_string_append (str, ")");
+
+	ret = camel_db_command (cdb, str->str, ex);
+	CAMEL_DB_RELEASE_SQLITE_MEMORY;
+	g_string_free (str, TRUE);
+
+	return ret;
+}
+
+int
+camel_db_clear_folder_summary (CamelDB *cdb, char *folder, CamelException *ex)
+{
+	int ret;
+
+	char *folders_del;
+	char *msginfo_del;
+
+	folders_del = sqlite3_mprintf ("DELETE FROM folders WHERE folder_name = %Q", folder);
+	msginfo_del = sqlite3_mprintf ("DELETE FROM %Q ", folder);
+
+	camel_db_begin_transaction (cdb, ex);
+	camel_db_add_to_transaction (cdb, msginfo_del, ex);
+	camel_db_add_to_transaction (cdb, folders_del, ex);
+	ret = camel_db_end_transaction (cdb, ex);
+
+	sqlite3_free (folders_del);
+	sqlite3_free (msginfo_del);
+
+	return ret;
+}
+
+
+
+void
+camel_db_camel_mir_free (CamelMIRecord *record)
+{
+	if (record) {
+		camel_pstring_free (record->uid);
+		camel_pstring_free (record->subject);
+		camel_pstring_free (record->from);
+		camel_pstring_free (record->to);
+		camel_pstring_free (record->cc);
+		camel_pstring_free (record->mlist);
+		camel_pstring_free (record->followup_flag);
+		camel_pstring_free (record->followup_completed_on);
+		camel_pstring_free (record->followup_due_by);
+		g_free (record->part);
+		g_free (record->labels);
+		g_free (record->usertags);
+		g_free (record->cinfo);
+		g_free (record->bdata);
+
+		g_free (record);
+	}
+}
+
+char * 
+camel_db_sqlize_string (const char *string)
+{
+	return sqlite3_mprintf ("%Q", string);
+}
+
+void 
+camel_db_free_sqlized_string (char *string)
+{
+	sqlite3_free (string);
+	string = NULL;
+}
+
+char * camel_db_get_column_name (const char *raw_name)
+{
+	d(g_print ("\n\aRAW name is : [%s] \n\a", raw_name));
+	if (!g_ascii_strcasecmp (raw_name, "Subject"))
+		return g_strdup ("subject");
+	else if (!g_ascii_strcasecmp (raw_name, "from"))
+		return g_strdup ("mail_from");
+	else if (!g_ascii_strcasecmp (raw_name, "Cc"))
+		return g_strdup ("mail_cc");
+	else if (!g_ascii_strcasecmp (raw_name, "To"))
+		return g_strdup ("mail_to");
+	else if (!g_ascii_strcasecmp (raw_name, "Flagged"))
+		return g_strdup ("important");
+	else if (!g_ascii_strcasecmp (raw_name, "deleted"))
+		return g_strdup ("deleted");
+	else if (!g_ascii_strcasecmp (raw_name, "junk"))
+		return g_strdup ("junk");
+	else if (!g_ascii_strcasecmp (raw_name, "Seen"))
+		return g_strdup ("read");
+	else if (!g_ascii_strcasecmp (raw_name, "Attachments"))
+		return g_strdup ("attachment");
+	else {
+		/* Let it crash for all unknown columns for now. 
+		We need to load the messages into memory and search etc. 
+		We should extend this for camel-folder-search system flags search as well 
+		otherwise, search-for-signed-messages will not work etc.*/
+
+		return g_strdup ("");
+	}
+
+}

Added: trunk/camel/camel-db.h
==============================================================================
--- (empty file)
+++ trunk/camel/camel-db.h	Wed Jul 16 11:38:32 2008
@@ -0,0 +1,155 @@
+/* Srinivasa Ragavan - <sragavan novell com> - GPL v2 or later */
+
+#ifndef __CAMEL_DB_H
+#define __CAMEL_DB_H
+#include <sqlite3.h>
+#include <glib.h>
+#define CAMEL_DB_FILE "folders.db"
+
+#include "camel-exception.h"
+
+struct _CamelDB {
+	sqlite3 *db;
+	GMutex *lock;
+};
+
+#define CAMEL_DB_FREE_CACHE_SIZE 2 * 1024 * 1024
+
+/* The extensive DB format, supporting basic searching and sorting
+  uid, - Message UID
+  flags, - Camel Message info flags
+  unread/read, - boolean read/unread status
+  deleted, - boolean deleted status
+  replied, - boolean replied status
+  imp, - boolean important status
+  junk, - boolean junk status
+  size, - size of the mail
+  attachment, boolean attachment status
+  dsent, - sent date
+  dreceived, - received date
+  subject, - subject of the mail
+  from, - sender
+  to, - recipient
+  cc, - CC members
+  mlist, - message list headers
+  follow-up-flag, - followup flag / also can be queried to see for followup or not
+  completed-on-set, - completed date, can be used to see if completed
+  due-by,  - to see the due by date
+  Location - This can be derived from the database location/name. No need to store.
+  label, - labels of mails also called as userflags
+  usertags, composite string of user tags
+  cinfo, content info string - composite string
+  bdata, provider specific data
+  part, part/references/thread id
+*/
+
+typedef struct _CamelMIRecord {
+	char *uid;
+	guint32 flags;
+	guint32 msg_type;
+	guint32 msg_security;
+	gboolean read;
+	gboolean deleted;
+	gboolean replied;
+	gboolean important;
+	gboolean junk;
+	gboolean attachment;
+	guint32 size;
+	time_t dsent;
+	time_t dreceived;
+	char *subject;
+	char *from;
+	char *to;
+	char *cc;
+	char *mlist;
+	char *followup_flag;
+	char *followup_completed_on;
+	char *followup_due_by;
+	char *part;
+	char *labels;
+	char *usertags;
+	char *cinfo;
+	char *bdata;
+} CamelMIRecord;
+
+typedef struct _CamelFIRecord {
+	char *folder_name;
+	guint32 version;
+	guint32 flags;
+	guint32 nextuid;
+	time_t time;
+	guint32 saved_count;
+	guint32 unread_count;
+	guint32 deleted_count;
+	guint32 junk_count;
+	guint32 visible_count;
+	guint32 jnd_count;  /* Junked not deleted */
+	char *bdata;
+} CamelFIRecord;
+
+
+
+
+typedef struct _CamelDB CamelDB;
+typedef int (*CamelDBSelectCB) (gpointer data, int ncol, char **colvalues, char **colnames);
+
+
+CamelDB * camel_db_open (const char *path, CamelException *ex);
+void camel_db_close (CamelDB *cdb);
+int camel_db_command (CamelDB *cdb, const char *stmt, CamelException *ex);
+
+int camel_db_transaction_command (CamelDB *cdb, GSList *qry_list, CamelException *ex);
+
+int camel_db_begin_transaction (CamelDB *cdb, CamelException *ex);
+int camel_db_add_to_transaction (CamelDB *cdb, const char *query, CamelException *ex);
+int camel_db_end_transaction (CamelDB *cdb, CamelException *ex);
+int camel_db_abort_transaction (CamelDB *cdb, CamelException *ex);
+int camel_db_clear_folder_summary (CamelDB *cdb, char *folder, CamelException *ex);
+
+int camel_db_delete_folder (CamelDB *cdb, const char *folder, CamelException *ex);
+int camel_db_delete_uid (CamelDB *cdb, const char *folder, const char *uid, CamelException *ex);
+/*int camel_db_delete_uids (CamelDB *cdb, CamelException *ex, int nargs, ... );*/
+int camel_db_delete_uids (CamelDB *cdb, const char* folder_name, GSList *uids, CamelException *ex);
+
+int camel_db_create_folders_table (CamelDB *cdb, CamelException *ex);
+int camel_db_select (CamelDB *cdb, const char* stmt, CamelDBSelectCB callback, gpointer data, CamelException *ex);
+
+int camel_db_write_folder_info_record (CamelDB *cdb, CamelFIRecord *record, CamelException *ex);
+int camel_db_read_folder_info_record (CamelDB *cdb, const char *folder_name, CamelFIRecord **record, CamelException *ex);
+
+int camel_db_prepare_message_info_table (CamelDB *cdb, const char *folder_name, CamelException *ex);
+
+int camel_db_write_message_info_record (CamelDB *cdb, const char *folder_name, CamelMIRecord *record, CamelException *ex);
+int camel_db_read_message_info_records (CamelDB *cdb, const char *folder_name, gpointer p, CamelDBSelectCB read_mir_callback, CamelException *ex);
+int camel_db_read_message_info_record_with_uid (CamelDB *cdb, const char *folder_name, const char *uid, gpointer p, CamelDBSelectCB read_mir_callback, CamelException *ex);
+
+int camel_db_count_junk_message_info (CamelDB *cdb, const char *table_name, guint32 *count, CamelException *ex);
+int camel_db_count_unread_message_info (CamelDB *cdb, const char *table_name, guint32 *count, CamelException *ex);
+int camel_db_count_deleted_message_info (CamelDB *cdb, const char *table_name, guint32 *count, CamelException *ex);
+int camel_db_count_total_message_info (CamelDB *cdb, const char *table_name, guint32 *count, CamelException *ex);
+
+int camel_db_count_visible_message_info (CamelDB *cdb, const char *table_name, guint32 *count, CamelException *ex);
+int camel_db_count_visible_unread_message_info (CamelDB *cdb, const char *table_name, guint32 *count, CamelException *ex);
+
+int camel_db_count_junk_not_deleted_message_info (CamelDB *cdb, const char *table_name, guint32 *count, CamelException *ex);
+
+void camel_db_camel_mir_free (CamelMIRecord *record);
+
+int camel_db_create_vfolder (CamelDB *db, const char *folder_name, CamelException *ex);
+int camel_db_delete_uid_from_vfolder (CamelDB *db, char *folder_name, char *vuid, CamelException *ex);
+GPtrArray * camel_db_get_vuids_from_vfolder (CamelDB *db, char *folder_name, char *filter, CamelException *ex);
+int camel_db_add_to_vfolder (CamelDB *db, char *folder_name, char *vuid, CamelException *ex);
+int camel_db_add_to_vfolder_transaction (CamelDB *db, char *folder_name, char *vuid, CamelException *ex);
+
+int camel_db_get_folder_uids (CamelDB *db, char *folder_name, GPtrArray *array, CamelException *ex);
+
+GPtrArray * camel_db_get_folder_junk_uids (CamelDB *db, char *folder_name, CamelException *ex);
+GPtrArray * camel_db_get_folder_deleted_uids (CamelDB *db, char *folder_name, CamelException *ex);
+
+char * camel_db_sqlize_string (const char *string);
+void camel_db_free_sqlized_string (char *string);
+
+char * camel_db_get_column_name (const char *raw_name);
+
+#endif
+

Modified: trunk/camel/camel-folder-search.c
==============================================================================
--- trunk/camel/camel-folder-search.c	(original)
+++ trunk/camel/camel-folder-search.c	Wed Jul 16 11:38:32 2008
@@ -48,6 +48,10 @@
 #include "camel-multipart.h"
 #include "camel-search-private.h"
 #include "camel-stream-mem.h"
+#include "camel-db.h"
+#include "camel-store.h"
+#include "camel-vee-folder.h"
+#include "camel-string-utils.h"
 
 #define d(x) 
 #define r(x) 
@@ -65,6 +69,7 @@
 static ESExpResult *search_not(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search);
 
 static ESExpResult *search_header_contains(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search);
+static ESExpResult *db_search_header_contains(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search);
 static ESExpResult *search_header_matches(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search);
 static ESExpResult *search_header_starts_with(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search);
 static ESExpResult *search_header_ends_with(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search);
@@ -87,6 +92,8 @@
 static void camel_folder_search_init       (CamelFolderSearch *obj);
 static void camel_folder_search_finalize   (CamelObject *obj);
 
+static int read_uid_callback (void * ref, int ncol, char ** cols, char **name);
+
 static CamelObjectClass *camel_folder_search_parent;
 
 static void
@@ -99,7 +106,7 @@
 	klass->match_all = search_match_all;
 	klass->match_threads = search_match_threads;
 	klass->body_contains = search_body_contains;
-	klass->header_contains = search_header_contains;
+	klass->header_contains = db_search_header_contains;
 	klass->header_matches = search_header_matches;
 	klass->header_starts_with = search_header_starts_with;
 	klass->header_ends_with = search_header_ends_with;
@@ -150,13 +157,16 @@
 
 	if (search->sexp)
 		e_sexp_unref(search->sexp);
-	if (search->summary_hash)
-		g_hash_table_destroy(search->summary_hash);
 
 	g_free(search->last_search);
 	g_hash_table_foreach(p->mempool_hash, free_mempool, obj);
 	g_hash_table_destroy(p->mempool_hash);
 	g_free(p);
+
+	if (search->query) {
+		g_print ("\nFinalizing search query and the query is : \n%s\n", search->query->str);
+		g_string_free (search->query, TRUE);
+	}
 }
 
 CamelType
@@ -239,6 +249,8 @@
 			}
 		}
 	}
+
+	search->query = NULL;
 }
 
 /**
@@ -274,7 +286,16 @@
 void
 camel_folder_search_set_folder(CamelFolderSearch *search, CamelFolder *folder)
 {
+	char *tmp = camel_db_sqlize_string(folder->full_name);
 	search->folder = folder;
+
+	if (search->query)
+		g_string_free (search->query, TRUE);
+
+	/* FIXME: Get this string done from camel-db by parsing with sqlite_mprintf etc. */
+	search->query = g_string_new ("SELECT uid FROM ");
+	g_string_append_printf (search->query, "%s ", tmp);
+	camel_db_free_sqlized_string (tmp);
 }
 
 /**
@@ -290,14 +311,7 @@
 void
 camel_folder_search_set_summary(CamelFolderSearch *search, GPtrArray *summary)
 {
-	int i;
-
 	search->summary = summary;
-	if (search->summary_hash)
-		g_hash_table_destroy(search->summary_hash);
-	search->summary_hash = g_hash_table_new(g_str_hash, g_str_equal);
-	for (i=0;i<summary->len;i++)
-		g_hash_table_insert(search->summary_hash, (char *)camel_message_info_uid(summary->pdata[i]), summary->pdata[i]);
 }
 
 /**
@@ -387,17 +401,18 @@
 				g_hash_table_insert(results, g_ptr_array_index(r->value.ptrarray, i), GINT_TO_POINTER (1));
 			}
 			for (i=0;i<search->summary->len;i++) {
-				CamelMessageInfo *info = g_ptr_array_index(search->summary, i);
-				char *uid = (char *)camel_message_info_uid(info);
+				char *uid = g_ptr_array_index(search->summary, i);
 				if (g_hash_table_lookup(results, uid)) {
-					g_ptr_array_add(matches, e_mempool_strdup(pool, uid));
+//					g_ptr_array_add(matches, e_mempool_strdup(pool, uid));
+					g_ptr_array_add(matches, (char *) camel_pstring_strdup(uid));
 				}
 			}
 			g_hash_table_destroy(results);
 		} else {
 			for (i=0;i<r->value.ptrarray->len;i++) {
 				d(printf("adding match: %s\n", (char *)g_ptr_array_index(r->value.ptrarray, i)));
-				g_ptr_array_add(matches, e_mempool_strdup(pool, g_ptr_array_index(r->value.ptrarray, i)));
+//				g_ptr_array_add(matches, e_mempool_strdup(pool, g_ptr_array_index(r->value.ptrarray, i)));
+				g_ptr_array_add(matches, (char *) camel_pstring_strdup(g_ptr_array_index(r->value.ptrarray, i)));
 			}
 		}
 		/* instead of putting the mempool_hash in the structure, we keep the api clean by
@@ -443,8 +458,7 @@
 	ESExpResult *r;
 	GPtrArray *matches = NULL, *summary_set;
 	int i;
-	GHashTable *results;
-	EMemPool *pool;
+	CamelDB *cdb;
 	struct _CamelFolderSearchPrivate *p = _PRIVATE(search);
 
 	g_assert(search->folder);
@@ -453,7 +467,6 @@
 
 	/* setup our search list, summary_hash only contains those we're interested in */
 	search->summary = camel_folder_get_summary(search->folder);
-	search->summary_hash = g_hash_table_new(g_str_hash, g_str_equal);
 
 	if (uids) {
 		GHashTable *uids_hash = g_hash_table_new(g_str_hash, g_str_equal);
@@ -462,16 +475,13 @@
 		for (i=0;i<uids->len;i++)
 			g_hash_table_insert(uids_hash, uids->pdata[i], uids->pdata[i]);
 		for (i=0;i<search->summary->len;i++)
-			if (g_hash_table_lookup(uids_hash, camel_message_info_uid(search->summary->pdata[i])))
+			if (g_hash_table_lookup(uids_hash, search->summary->pdata[i]))
 				g_ptr_array_add(search->summary_set, search->summary->pdata[i]);
 		g_hash_table_destroy(uids_hash);
 	} else {
 		summary_set = search->summary;
 	}
 
-	for (i=0;i<summary_set->len;i++)
-		g_hash_table_insert(search->summary_hash, (char *)camel_message_info_uid(summary_set->pdata[i]), summary_set->pdata[i]);
-
 	/* only re-parse if the search has changed */
 	if (search->last_search == NULL
 	    || strcmp(search->last_search, expr)) {
@@ -491,41 +501,14 @@
 		goto fail;
 	}
 
-	matches = g_ptr_array_new();
-
-	/* now create a folder summary to return?? */
-	if (r->type == ESEXP_RES_ARRAY_PTR) {
-		d(printf("got result ...\n"));
-
-		/* we use a mempool to store the strings, packed in tight as possible, and freed together */
-		/* because the strings are often short (like <8 bytes long), we would be wasting appx 50%
-		   of memory just storing the size tag that malloc assigns us and alignment padding, so this
-		   gets around that (and is faster to allocate and free as a bonus) */
-		pool = e_mempool_new(512, 256, E_MEMPOOL_ALIGN_BYTE);
-		/* reorder result in summary order */
-		results = g_hash_table_new(g_str_hash, g_str_equal);
-		for (i=0;i<r->value.ptrarray->len;i++) {
-			d(printf("adding match: %s\n", (char *)g_ptr_array_index(r->value.ptrarray, i)));
-			g_hash_table_insert(results, g_ptr_array_index(r->value.ptrarray, i), GINT_TO_POINTER (1));
-		}
-
-		for (i=0;i<summary_set->len;i++) {
-			CamelMessageInfo *info = g_ptr_array_index(summary_set, i);
-			char *uid = (char *)camel_message_info_uid(info);
-			if (g_hash_table_lookup(results, uid))
-				g_ptr_array_add(matches, e_mempool_strdup(pool, uid));
-		}
-		g_hash_table_destroy(results);
-
-		/* instead of putting the mempool_hash in the structure, we keep the api clean by
-		   putting a reference to it in a hashtable.  Lets us do some debugging and catch
-		   unfree'd results as well. */
-		g_hash_table_insert(p->mempool_hash, matches, pool);
-	} else {
-		g_warning("Search returned an invalid result type");
-	}
+	printf ("\nsexp is : [%s]\n", expr);
+	printf ("Something is returned in the top-level caller : [%s]\n", search->query->str);
 
+	matches = g_ptr_array_new();
+	cdb = (CamelDB *) (search->folder->cdb);
+	camel_db_select (cdb, search->query->str, (CamelDBSelectCB) read_uid_callback, matches, ex);
 	e_sexp_result_free(search->sexp, r);
+
 fail:
 	/* these might be allocated by match-threads */
 	if (p->threads)
@@ -534,14 +517,12 @@
 		g_hash_table_destroy(p->threads_hash);
 	if (search->summary_set)
 		g_ptr_array_free(search->summary_set, TRUE);
-	g_hash_table_destroy(search->summary_hash);
 	camel_folder_free_summary(search->folder, search->summary);
 
 	p->threads = NULL;
 	p->threads_hash = NULL;
 	search->folder = NULL;
 	search->summary = NULL;
-	search->summary_hash = NULL;
 	search->summary_set = NULL;
 	search->current = NULL;
 	search->body_index = NULL;
@@ -551,10 +532,10 @@
 
 void camel_folder_search_free_result(CamelFolderSearch *search, GPtrArray *result)
 {
+#if 0
 	int i;
 	struct _CamelFolderSearchPrivate *p = _PRIVATE(search);
 	EMemPool *pool;
-
 	pool = g_hash_table_lookup(p->mempool_hash, result);
 	if (pool) {
 		e_mempool_destroy(pool);
@@ -563,6 +544,8 @@
 		for (i=0;i<result->len;i++)
 			g_free(g_ptr_array_index(result, i));
 	}
+#endif
+	g_ptr_array_foreach (result, (GFunc) camel_pstring_free, NULL);
 	g_ptr_array_free(result, TRUE);
 }
 
@@ -616,16 +599,16 @@
 				/* 'not' against the whole summary */
 				GHashTable *have = g_hash_table_new(g_str_hash, g_str_equal);
 				char **s;
-				CamelMessageInfo **m;
+				char **m;
 
 				s = (char **)v->pdata;
 				for (i=0;i<v->len;i++)
 					g_hash_table_insert(have, s[i], s[i]);
 
 				v = search->summary_set?search->summary_set:search->summary;
-				m = (CamelMessageInfo **)v->pdata;
+				m = (char **)v->pdata;
 				for (i=0;i<v->len;i++) {
-					char *uid = (char *)camel_message_info_uid(m[i]);
+					char *uid = m[i];
 
 					if (g_hash_table_lookup(have, uid) == NULL)
 						g_ptr_array_add(r->value.ptrarray, uid);
@@ -652,9 +635,7 @@
 static ESExpResult *
 search_match_all(struct _ESExp *f, int argc, struct _ESExpTerm **argv, CamelFolderSearch *search)
 {
-	int i;
 	ESExpResult *r, *r1;
-	GPtrArray *v;
 	gchar *error_msg;
 
 	if (argc>1) {
@@ -664,7 +645,7 @@
 	/* we are only matching a single message?  or already inside a match-all? */
 	if (search->current) {
 		d(printf("matching against 1 message: %s\n", camel_message_info_subject(search->current)));
-
+		
 		r = e_sexp_result_new(f, ESEXP_RES_BOOL);
 		r->value.bool = FALSE;
 
@@ -694,12 +675,22 @@
 		g_assert(0);
 		return r;
 	}
-
+#if 0
 	v = search->summary_set?search->summary_set:search->summary;
+	
+	if (v->len - g_hash_table_size (search->folder->summary->loaded_infos) > 50 && !CAMEL_IS_VEE_FOLDER (search->folder)) {
+		/* Load the DB contents. FIXME this 100 needs to be a better threshold to reload from DB. */
+		#warning "handle exception"
+		camel_folder_summary_reload_from_db (search->folder->summary, NULL);
+	} 
+
+#endif	
+	e_sexp_term_eval (f, argv [0]);
+#if 0
 	for (i=0;i<v->len;i++) {
 		const char *uid;
 
-		search->current = g_ptr_array_index(v, i);
+		search->current = camel_folder_summary_uid (search->folder->summary, v->pdata[i]);
 		uid = camel_message_info_uid(search->current);
 
 		if (argc>0) {
@@ -717,12 +708,14 @@
 		} else {
 			g_ptr_array_add(r->value.ptrarray, (char *)uid);
 		}
+		camel_message_info_free (search->current);
 	}
+#endif	
 	search->current = NULL;
-
 	return r;
 }
 
+//FIXME Check threads mis
 static void
 fill_thread_table(struct _CamelFolderThreadNode *root, GHashTable *id_hash)
 {
@@ -817,6 +810,7 @@
 	}
 
 	/* cache this, so we only have to re-calculate once per search at most */
+	#warning "make search threads work well. Not sure if that works"
 	if (p->threads == NULL) {
 		p->threads = camel_folder_thread_messages_new(search->folder, NULL, TRUE);
 		p->threads_hash = g_hash_table_new(g_str_hash, g_str_equal);
@@ -867,7 +861,7 @@
 }
 
 static ESExpResult *
-check_header(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search, camel_search_match_t how)
+check_header_deprecated (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search, camel_search_match_t how)
 {
 	ESExpResult *r;
 	int truth = FALSE;
@@ -940,12 +934,71 @@
 }
 
 static ESExpResult *
-search_header_contains(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search)
+check_header (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search, camel_search_match_t how)
+{
+	/* FIXME: What to do for headers that are not stored in db */
+
+	ESExpResult *r;
+
+	if (strlen (argv [1]->value.string) > 1) {
+
+		char *value;
+		char *temp=NULL;
+		char *column;
+
+		column = camel_db_get_column_name (argv [0]->value.string);
+
+		switch (how) {
+			case CAMEL_SEARCH_MATCH_EXACT:
+				temp = g_strdup_printf ("%s", argv [1]->value.string);
+				break;
+			case CAMEL_SEARCH_MATCH_CONTAINS:
+			case CAMEL_SEARCH_MATCH_SOUNDEX:
+				temp = g_strdup_printf ("%%%s%%", argv [1]->value.string);
+				break;
+			case CAMEL_SEARCH_MATCH_STARTS:
+				temp = g_strdup_printf ("%s%%", argv [1]->value.string);
+				break;
+			case CAMEL_SEARCH_MATCH_ENDS:
+				temp = g_strdup_printf ("%%%s", argv [1]->value.string);
+				break;
+		}
+
+		value = camel_db_sqlize_string (temp);
+		g_free (temp);
+
+		if (g_str_has_suffix (search->query->str, " "))
+			g_string_append_printf (search->query, "WHERE %s LIKE %s", column, value);
+		else {
+			if (f->operators)
+				g_string_append_printf (search->query, " %s %s LIKE %s", (char *) (g_slist_nth_data (f->operators, 0)), column, value);
+			else
+				g_string_append_printf (search->query, " OR %s LIKE %s", column, value);
+		}
+
+		g_free (column);
+		camel_db_free_sqlized_string (value);
+	}
+
+	r = e_sexp_result_new(f, ESEXP_RES_BOOL);
+	r->value.bool = FALSE;
+
+	return r;
+}
+
+static ESExpResult *
+search_header_contains (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search)
 {
 	return check_header(f, argc, argv, search, CAMEL_SEARCH_MATCH_CONTAINS);
 }
 
 static ESExpResult *
+db_search_header_contains (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search)
+{
+	return check_header (f, argc, argv, search, CAMEL_SEARCH_MATCH_CONTAINS);
+}
+
+static ESExpResult *
 search_header_matches(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search)
 {
 	return check_header(f, argc, argv, search, CAMEL_SEARCH_MATCH_EXACT);
@@ -1049,7 +1102,6 @@
 	struct _glib_sux_donkeys lambdafoo;
 	CamelIndexCursor *wc, *nc;
 	const char *word, *name;
-	CamelMessageInfo *mi;
 	int i;
 
 	/* we can have a maximum of 32 words, as we use it as the AND mask */
@@ -1063,14 +1115,11 @@
 					nc = camel_index_find(search->body_index, word);
 					if (nc) {
 						while ((name = camel_index_cursor_next(nc))) {
-							mi = g_hash_table_lookup(search->summary_hash, name);
-							if (mi) {
-								int mask;
-								const char *uid = camel_message_info_uid(mi);
-
-								mask = (GPOINTER_TO_INT(g_hash_table_lookup(ht, uid))) | (1<<i);
-								g_hash_table_insert(ht, (char *)uid, GINT_TO_POINTER(mask));
-							}
+							int mask;
+
+							mask = (GPOINTER_TO_INT(g_hash_table_lookup(ht, name))) | (1<<i);
+							g_hash_table_insert(ht, (char *)name, GINT_TO_POINTER(mask));
+							
 						}
 						camel_object_unref((CamelObject *)nc);
 					}
@@ -1181,8 +1230,7 @@
 		GPtrArray *v = search->summary_set?search->summary_set:search->summary;
 
 		for (i=0;i<v->len;i++) {
-			CamelMessageInfo *info = g_ptr_array_index(v, i);
-			const char *uid = camel_message_info_uid(info);
+			char *uid  = g_ptr_array_index(v, i);
 			
 			if (match_words_message(search->folder, uid, words, ex))
 				g_ptr_array_add(matches, (char *)uid);
@@ -1232,9 +1280,9 @@
 			GPtrArray *v = search->summary_set?search->summary_set:search->summary;
 
 			for (i=0;i<v->len;i++) {
-				CamelMessageInfo *info = g_ptr_array_index(v, i);
+				char *uid = g_ptr_array_index(v, i);
 
-				g_ptr_array_add(r->value.ptrarray, (char *)camel_message_info_uid(info));
+				g_ptr_array_add(r->value.ptrarray, uid);
 			}
 		} else {
 			GHashTable *ht = g_hash_table_new(g_str_hash, g_str_equal);
@@ -1266,30 +1314,43 @@
 static ESExpResult *
 search_user_flag(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search)
 {
-	ESExpResult *r;
-	int i;
+		char *value = NULL;
+		ESExpResult *r;
+		char * tmp;
 
-	r(printf("executing user-flag\n"));
+		r(printf("\nexecuting user-flag with init str: [%s]\n", search->query->str));
+
+		if (argc == 1) {
+
+				if (search->current) {
+						/* FIXME: I am not sure if this will ever be executed */
+						abort ();
+				} else {
+						tmp = g_strdup_printf ("%%%s%%", argv[0]->value.string);
+						value = camel_db_sqlize_string (tmp);
+						g_free (tmp);
+
+						if (g_str_has_suffix (search->query->str, " ")) {
+								g_string_append_printf (search->query, "WHERE labels LIKE %s", value);
+						} else {
+								if (f->operators) {
+										g_string_append_printf (search->query, " %s labels LIKE %s", (char *) (g_slist_nth_data (f->operators, 0)), value);
+										f->operators = g_slist_remove_link (f->operators, g_slist_nth (f->operators, 0));
+								} else {
+										g_string_append_printf (search->query, " OR labels LIKE %s", value);
+								}
+						}
+
+						r(printf ("user-flag search value is : [%s] Appended str is : [%s]\n\n", value, search->query->str));
+						camel_db_free_sqlized_string (value);
+				}
+		} else
+				g_warning ("Makes no sense to search for multiple things in user flag. A flag is either set or not that's all: [%d]", argc);
 
-	/* are we inside a match-all? */
-	if (search->current) {
-		int truth = FALSE;
-		/* performs an OR of all words */
-		for (i=0;i<argc && !truth;i++) {
-			if (argv[i]->type == ESEXP_RES_STRING
-			    && camel_message_info_user_flag(search->current, argv[i]->value.string)) {
-				truth = TRUE;
-				break;
-			}
-		}
 		r = e_sexp_result_new(f, ESEXP_RES_BOOL);
-		r->value.bool = truth;
-	} else {
-		r = e_sexp_result_new(f, ESEXP_RES_ARRAY_PTR);
-		r->value.ptrarray = g_ptr_array_new();
-	}
+		r->value.bool = FALSE;
 
-	return r;
+		return r;
 }
 
 static ESExpResult *
@@ -1302,14 +1363,35 @@
 	if (search->current) {
 		gboolean truth = FALSE;
 		
-		if (argc == 1)
+		if (argc == 1) 
 			truth = camel_system_flag_get (camel_message_info_flags(search->current), argv[0]->value.string);
 		
 		r = e_sexp_result_new(f, ESEXP_RES_BOOL);
 		r->value.bool = truth;
 	} else {
-		r = e_sexp_result_new(f, ESEXP_RES_ARRAY_PTR);
-		r->value.ptrarray = g_ptr_array_new ();
+			/* FIXME: You need to complete the camel-db.c:camel_db_get_column_name function and use those return values */
+			char * value = camel_db_get_column_name (argv[0]->value.string);
+			char *connector = "=";
+
+			if (argc > 1) {
+				if (! strcmp(argv[1]->value.string, "set") )
+					connector = "!=";
+			}
+
+			if (g_str_has_suffix (search->query->str, " "))
+					g_string_append_printf (search->query, "WHERE (%s %s 0)", value, connector);
+			else {
+					search->query->len -= 1;
+					if (f->operators)
+							g_string_append_printf (search->query, " %s %s %s 0)", (char *) (g_slist_nth_data (f->operators, 0)), value, connector);
+					else
+							g_string_append_printf (search->query, " OR %s %s 0", value, connector);
+			}
+
+			g_free (value);
+
+			r = e_sexp_result_new(f, ESEXP_RES_BOOL);
+			r->value.bool = FALSE; 
 	}
 	
 	return r;
@@ -1318,18 +1400,42 @@
 static ESExpResult *
 search_user_tag(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search)
 {
-	const char *value = NULL;
-	ESExpResult *r;
-	
-	r(printf("executing user-tag\n"));
-	
-	if (argc == 1)
-		value = camel_message_info_user_tag(search->current, argv[0]->value.string);
-	
-	r = e_sexp_result_new(f, ESEXP_RES_STRING);
-	r->value.string = g_strdup (value ? value : "");
-	
-	return r;
+		char *value = NULL;
+		ESExpResult *r;
+		char * tmp;
+
+		r(printf("executing user-tag\n"));
+
+		if (argc == 2) {
+
+				if (search->current) {
+						/* FIXME: I am not sure if this will ever be executed */
+						abort ();
+				} else {
+
+						tmp = g_strdup_printf ("%s%s", argv[0]->value.string, argv[1]->value.string);
+						value = camel_db_sqlize_string (tmp);
+						g_free (tmp);
+
+						if (g_str_has_suffix (search->query->str, " "))
+								g_string_append_printf (search->query, "WHERE usertags = %s", value);
+						else {
+								if (f->operators)
+										g_string_append_printf (search->query, " %s usertags = %s", (char *) (g_slist_nth_data (f->operators, 0)), value);
+								else
+										g_string_append_printf (search->query, " OR usertags = %s", value);
+						}
+
+						camel_db_free_sqlized_string (value);
+
+				}
+		} else
+				g_warning ("Makes no sense to search for multiple things in user tag as it can hold only one string data : [%d] ", argc);
+
+		r = e_sexp_result_new(f, ESEXP_RES_BOOL);
+		r->value.bool = TRUE;
+
+		return r;
 }
 
 static ESExpResult *
@@ -1437,3 +1543,23 @@
 
 	return r;
 }
+
+static int 
+read_uid_callback (void * ref, int ncol, char ** cols, char **name)
+{
+	GPtrArray *matches;
+
+	matches = (GPtrArray *) ref;
+
+#if 0
+
+	int i;
+	for (i = 0; i < ncol; ++i) {
+		if ( !strcmp (name [i], "uid") ) 
+			g_ptr_array_add (matches, g_strdup (cols [i]));
+	}
+#else
+	g_ptr_array_add (matches, (GFunc) camel_pstring_strdup (cols [0]));
+#endif
+	return 0;
+}

Modified: trunk/camel/camel-folder-search.h
==============================================================================
--- trunk/camel/camel-folder-search.h	(original)
+++ trunk/camel/camel-folder-search.h	Wed Jul 16 11:38:32 2008
@@ -48,7 +48,11 @@
 	CamelFolder *folder;	/* folder for current search */
 	GPtrArray *summary;	/* summary array for current search */
 	GPtrArray *summary_set;	/* subset of summary to actually include in search */
-	GHashTable *summary_hash; /* hashtable of summary items */
+
+	GString *query; /* shall contain the SQL quer that should be executed */
+
+// DEPRECATED	
+//	GHashTable *summary_hash; /* hashtable of summary items */
 	CamelMessageInfo *current; /* current message info, when searching one by one */
 	CamelMimeMessage *current_message; /* cache of current message, if required */
 	CamelIndex *body_index;

Modified: trunk/camel/camel-folder-summary.c
==============================================================================
--- trunk/camel/camel-folder-summary.c	(original)
+++ trunk/camel/camel-folder-summary.c	Wed Jul 16 11:38:32 2008
@@ -34,6 +34,8 @@
 #include <errno.h>
 
 #include <glib.h>
+#include <glib-object.h>
+#include <glib/gi18n-lib.h>
 #include <glib/gstdio.h>
 
 #include <libedataserver/e-memory.h>
@@ -54,7 +56,13 @@
 #include "camel-stream-mem.h"
 #include "camel-stream-null.h"
 #include "camel-string-utils.h"
+#include "camel-store.h"
+#include "camel-vee-folder.h"
 
+/* To switch between e-memchunk and g-alloc */
+#define ALWAYS_ALLOC 1
+#define USE_GSLICE 1
+#define SUMMARY_CACHE_DROP 120
 static pthread_mutex_t info_lock = PTHREAD_MUTEX_INITIALIZER;
 
 /* this lock is ONLY for the standalone messageinfo stuff */
@@ -73,12 +81,17 @@
 extern int strdup_count, malloc_count, free_count;
 #endif
 
-#define CAMEL_FOLDER_SUMMARY_VERSION (13)
+#define CAMEL_FOLDER_SUMMARY_VERSION (14)
 
 #define _PRIVATE(o) (((CamelFolderSummary *)(o))->priv)
 
 #define META_SUMMARY_SUFFIX_LEN 5 /* strlen("-meta") */
 
+#define EXTRACT_FIRST_STRING(val) len=strtoul (part, &part, 10); part++; val=g_strndup (part, len);
+#define EXTRACT_STRING(val) part++; len=strtoul (part, &part, 10); part++; val=g_strndup (part, len);
+#define EXTRACT_FIRST_DIGIT(val) val=strtoul (part, &part, 10);
+#define EXTRACT_DIGIT(val) part++; val=strtoul (part, &part, 10);
+
 /* trivial lists, just because ... */
 struct _node {
 	struct _node *next;
@@ -92,6 +105,8 @@
 static int summary_meta_header_load(CamelFolderSummary *, FILE *);
 static int summary_meta_header_save(CamelFolderSummary *, FILE *);
 
+
+
 static CamelMessageInfo * message_info_new_from_header(CamelFolderSummary *, struct _camel_header_raw *);
 static CamelMessageInfo * message_info_new_from_parser(CamelFolderSummary *, CamelMimeParser *);
 static CamelMessageInfo * message_info_new_from_message(CamelFolderSummary *s, CamelMimeMessage *msg);
@@ -107,6 +122,9 @@
 static int		         content_info_save(CamelFolderSummary *, FILE *, CamelMessageContentInfo *);
 static void		         content_info_free(CamelFolderSummary *, CamelMessageContentInfo *);
 
+static int save_message_infos_to_db (CamelFolderSummary *s, CamelException *ex);
+static int camel_read_mir_callback (void * ref, int ncol, char ** cols, char ** name);
+
 static char *next_uid_string(CamelFolderSummary *s);
 
 static CamelMessageContentInfo * summary_build_content_info(CamelFolderSummary *s, CamelMessageInfo *msginfo, CamelMimeParser *mp);
@@ -117,6 +135,7 @@
 static void camel_folder_summary_finalize   (CamelObject *obj);
 
 static CamelObjectClass *camel_folder_summary_parent;
+static CamelMessageInfo * message_info_from_uid (CamelFolderSummary *s, const char *uid);
 
 static void
 camel_folder_summary_init (CamelFolderSummary *s)
@@ -142,8 +161,8 @@
 	s->time = 0;
 	s->nextuid = 1;
 
-	s->messages = g_ptr_array_new();
-	s->messages_uid = g_hash_table_new(g_str_hash, g_str_equal);
+	s->uids = g_ptr_array_new ();
+	s->loaded_infos = g_hash_table_new (g_str_hash, g_str_equal);
 	
 	p->summary_lock = g_mutex_new();
 	p->io_lock = g_mutex_new();
@@ -157,6 +176,8 @@
 	   exceeding 20, has to override this value 
 	*/
 	s->meta_summary->uid_len = 20;
+	s->cache_load_time = 0;
+	s->timeout_handle = 0;
 }
 
 static void free_o_name(void *key, void *value, void *data)
@@ -173,20 +194,25 @@
 
 	p = _PRIVATE(obj);
 
-	camel_folder_summary_clear(s);
-	g_ptr_array_free(s->messages, TRUE);
-	g_hash_table_destroy(s->messages_uid);
+	if (s->timeout_handle)
+		g_source_remove (s->timeout_handle);
+	//camel_folder_summary_clear(s);
+	g_ptr_array_foreach (s->uids, (GFunc) camel_pstring_free, NULL);
+	g_ptr_array_free (s->uids, TRUE);
+	g_hash_table_destroy (s->loaded_infos);
 
 	g_hash_table_foreach(p->filter_charset, free_o_name, NULL);
 	g_hash_table_destroy(p->filter_charset);
 
 	g_free(s->summary_path);
 
+#ifndef ALWAYS_ALLOC	
 	if (s->message_info_chunks)
 		e_memchunk_destroy(s->message_info_chunks);
 	if (s->content_info_chunks)
 		e_memchunk_destroy(s->content_info_chunks);
-
+#endif
+	
 	if (p->filter_index)
 		camel_object_unref((CamelObject *)p->filter_index);
 	if (p->filter_64)
@@ -329,7 +355,7 @@
 int
 camel_folder_summary_count(CamelFolderSummary *s)
 {
-	return s->messages->len;
+	return s->uids->len;
 }
 
 
@@ -346,18 +372,25 @@
  * Returns the summary item, or %NULL if @index is out of range
  **/
 CamelMessageInfo *
-camel_folder_summary_index(CamelFolderSummary *s, int i)
+camel_folder_summary_index (CamelFolderSummary *s, int i)
 {
 	CamelMessageInfo *info = NULL;
 
 	CAMEL_SUMMARY_LOCK(s, summary_lock);
 	CAMEL_SUMMARY_LOCK(s, ref_lock);
 
-	if (i<s->messages->len)
-		info = g_ptr_array_index(s->messages, i);
+	if (i < s->uids->len) {
+		char *uid;
+		uid = g_ptr_array_index (s->uids, i);
 
-	if (info)
-		info->refcount++;
+		/* FIXME: Get exception from caller
+		and pass it on below */
+		
+		CAMEL_SUMMARY_UNLOCK(s, ref_lock);
+		CAMEL_SUMMARY_UNLOCK(s, summary_lock);
+
+		return camel_folder_summary_uid (s, uid);
+	}
 
 	CAMEL_SUMMARY_UNLOCK(s, ref_lock);
 	CAMEL_SUMMARY_UNLOCK(s, summary_lock);
@@ -365,6 +398,35 @@
 	return info;
 }
 
+#warning "Implement - camel_folder_summary_uid_exist - directly through db than manual strcmp"
+
+/**
+ * camel_folder_summary_uid_from_index:
+ * @summary: a #CamelFolderSummary object
+ * @index: item index
+ * 
+ * Retrieve a summary item's uid  by index number.
+ *
+ * A newly allocated uid is returned, which must be
+ * free'd as appropriate.
+ * 
+ * Returns the summary item's uid , or %NULL if @index is out of range   
+ **/
+char *
+camel_folder_summary_uid_from_index (CamelFolderSummary *s, int i)
+{
+	char *uid=NULL;
+	CAMEL_SUMMARY_LOCK(s, summary_lock);
+
+	if (i<s->uids->len)
+		uid = g_strdup (g_ptr_array_index(s->uids, i));
+
+	CAMEL_SUMMARY_UNLOCK(s, summary_lock);
+	
+	return uid;
+
+}
+
 
 /**
  * camel_folder_summary_array:
@@ -373,50 +435,94 @@
  * Obtain a copy of the summary array.  This is done atomically,
  * so cannot contain empty entries.
  *
- * It must be freed using #camel_folder_summary_array_free.
+ * It must be freed using g_ptr_array_free
  *
- * Returns a #GPtrArray of #CamelMessageInfo items
+ * Returns a #GPtrArray of uids
  **/
 GPtrArray *
 camel_folder_summary_array(CamelFolderSummary *s)
 {
-	CamelMessageInfo *info;
 	GPtrArray *res = g_ptr_array_new();
 	int i;
 	
 	CAMEL_SUMMARY_LOCK(s, summary_lock);
-	CAMEL_SUMMARY_LOCK(s, ref_lock);
 
-	g_ptr_array_set_size(res, s->messages->len);
-	for (i=0;i<s->messages->len;i++) {
-		info = res->pdata[i] = g_ptr_array_index(s->messages, i);
-		info->refcount++;
-	}
+	g_ptr_array_set_size(res, s->uids->len);
+	for (i=0;i<s->uids->len;i++)
+		res->pdata[i] = (gpointer) camel_pstring_strdup ((char *)g_ptr_array_index(s->uids, i));
+	
 
-	CAMEL_SUMMARY_UNLOCK(s, ref_lock);
 	CAMEL_SUMMARY_UNLOCK(s, summary_lock);
 
 	return res;
 }
 
+struct _db_pass_data {
+	CamelFolderSummary *summary;
+	gboolean double_ref;
+	gboolean add; /* or just insert to hashtable */
+};
 
-/**
- * camel_folder_summary_array_free:
- * @summary: a #CamelFolderSummary object
- * @array: array of #CamelMessageInfo items as returned from #camel_folder_summary_array
- * 
- * Free the folder summary array.
- **/
-void
-camel_folder_summary_array_free(CamelFolderSummary *s, GPtrArray *array)
+static CamelMessageInfo *
+message_info_from_uid (CamelFolderSummary *s, const char *uid)
 {
-	int i;
+	CamelMessageInfo *info;
+	int ret;
 
-	/* FIXME: do the locking around the whole lot to make it faster */
-	for (i=0;i<array->len;i++)
-		camel_message_info_free(array->pdata[i]);
+	CAMEL_SUMMARY_LOCK(s, summary_lock);
+	CAMEL_SUMMARY_LOCK(s, ref_lock);
+
+	info = g_hash_table_lookup (s->loaded_infos, uid);
+
+	if (!info) {
+		CamelDB *cdb;
+		CamelException ex;// May be this should come from the caller 
+		char *folder_name;
+		struct _db_pass_data data;
+		
+		d(printf ("\ncamel_folder_summary_uid called \n"));
+		camel_exception_init (&ex);
+		s->flags &= ~CAMEL_SUMMARY_DIRTY;
+
+		folder_name = s->folder->full_name;
+		cdb = s->folder->cdb;
+		
+		CAMEL_SUMMARY_UNLOCK(s, ref_lock);
+		CAMEL_SUMMARY_UNLOCK(s, summary_lock);
 
-	g_ptr_array_free(array, TRUE);
+		data.summary = s;
+		data.double_ref = TRUE;
+		data.add = FALSE;
+
+	
+		ret = camel_db_read_message_info_record_with_uid (cdb, folder_name, uid, &data, camel_read_mir_callback, &ex);
+		if (ret != 0) {
+			// if (strcmp (folder_name, "UNMATCHED"))
+			g_warning ("Unable to read uid %s from folder %s: %s", uid, folder_name, camel_exception_get_description(&ex));
+			
+			return NULL;
+		}
+		CAMEL_SUMMARY_LOCK(s, summary_lock);
+		CAMEL_SUMMARY_LOCK(s, ref_lock);
+
+		/* We would have double reffed at camel_read_mir_callback */
+		info = g_hash_table_lookup (s->loaded_infos, uid);
+		
+		if (!info) {
+			/* Makes no sense now as the exception is local as of now. FIXME: Pass exception from caller */
+			camel_exception_set (&ex, CAMEL_EXCEPTION_SYSTEM, _(g_strdup_printf ("no uid [%s] exists", uid)));
+			// if (strcmp (folder_name, "UNMATCHED"))			
+			g_warning ("No uid[%s] exists in %s\n", uid, folder_name);
+			camel_exception_clear (&ex);
+		}
+	} else
+		info->refcount++;
+
+	
+	CAMEL_SUMMARY_UNLOCK(s, ref_lock);
+	CAMEL_SUMMARY_UNLOCK(s, summary_lock);
+
+	return info;
 }
 
 
@@ -433,25 +539,11 @@
  * Returns the summary item, or %NULL if the uid @uid is not available
  **/
 CamelMessageInfo *
-camel_folder_summary_uid(CamelFolderSummary *s, const char *uid)
+camel_folder_summary_uid (CamelFolderSummary *s, const char *uid)
 {
-	CamelMessageInfo *info;
-
-	CAMEL_SUMMARY_LOCK(s, summary_lock);
-	CAMEL_SUMMARY_LOCK(s, ref_lock);
-
-	info = g_hash_table_lookup(s->messages_uid, uid);
-
-	if (info)
-		info->refcount++;
-
-	CAMEL_SUMMARY_UNLOCK(s, ref_lock);
-	CAMEL_SUMMARY_UNLOCK(s, summary_lock);
-
-	return info;
+	return ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->message_info_from_uid(s, uid);
 }
 
-
 /**
  * camel_folder_summary_next_uid:
  * @summary: a #CamelFolderSummary object
@@ -515,6 +607,38 @@
 	return ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->next_uid_string(s);
 }
 
+static CamelMessageContentInfo *
+perform_content_info_load_from_db (CamelFolderSummary *s, CamelMIRecord *mir)
+{
+	int i;
+	guint32 count;
+	CamelMessageContentInfo *ci, *pci;
+	char *part;
+	ci = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->content_info_from_db (s, mir);
+	if (ci == NULL)
+		return NULL;
+	part = mir->cinfo;
+	if (!part)
+		return ci;
+	if (*part == ' ') part++;
+	EXTRACT_DIGIT (count);
+
+	mir->cinfo = part;
+	for (i=0;i<count;i++) {
+		pci = perform_content_info_load_from_db (s, mir);
+		if (pci ) {
+			my_list_append((struct _node **)&ci->childs, (struct _node *)pci);
+			pci->parent = ci;
+		} else {
+			d(fprintf (stderr, "Summary file format messed up?"));
+			camel_folder_summary_content_info_free (s, ci);
+			return NULL;
+		}
+	}
+	return ci;
+}
+
+
 /* loads the content descriptions, recursively */
 static CamelMessageContentInfo *
 perform_content_info_load(CamelFolderSummary *s, FILE *in)
@@ -546,6 +670,251 @@
 	return ci;
 }
 
+static void
+append_changed_uids (char *key, CamelMessageInfoBase *info, GPtrArray *array)
+{
+	if (info->dirty || info->flags & CAMEL_MESSAGE_FOLDER_FLAGGED)
+		g_ptr_array_add (array, (gpointer)camel_pstring_strdup((camel_message_info_uid(info))));
+}
+
+GPtrArray *
+camel_folder_summary_get_changed (CamelFolderSummary *s)
+{
+	GPtrArray *res = g_ptr_array_new();
+	
+	CAMEL_SUMMARY_LOCK (s, summary_lock);
+	g_hash_table_foreach (s->loaded_infos, (GHFunc) append_changed_uids, res);
+	CAMEL_SUMMARY_UNLOCK (s, summary_lock);
+
+	return res;
+}
+
+#warning "FIXME: I should have a better LRU algorithm "
+static gboolean
+remove_item (char *key, CamelMessageInfoBase *info, CamelFolderSummary *s)
+{
+	d(printf("%d(%d)\t", info->refcount, info->dirty)); //camel_message_info_dump (info);
+	CAMEL_SUMMARY_LOCK(info->summary, ref_lock);
+	if (info->refcount == 1 && !info->dirty && !(info->flags & CAMEL_MESSAGE_FOLDER_FLAGGED)) {
+		CAMEL_SUMMARY_UNLOCK(info->summary, ref_lock);
+		/* Hackit so that hashtable isn;t corrupted. */
+		camel_pstring_free (info->uid);
+		info->uid = NULL;
+		/* Noone seems to need it. Why not free it then. */
+		camel_message_info_free (info);
+		return TRUE;
+	}
+	CAMEL_SUMMARY_UNLOCK(info->summary, ref_lock);	
+	return FALSE;
+}
+
+static gboolean      
+remove_cache (CamelFolderSummary *s)
+{
+	/* Attempt to release 2MB*/
+        sqlite3_release_memory(CAMEL_DB_FREE_CACHE_SIZE); 
+	
+	if (time(NULL) - s->cache_load_time < SUMMARY_CACHE_DROP)
+		return TRUE;
+	
+	printf("removing cache for  %s %d\n", s->folder->full_name, g_hash_table_size (s->loaded_infos));
+	#warning "hack. fix it"
+	CAMEL_SUMMARY_LOCK (s, summary_lock);
+	g_hash_table_foreach_remove  (s->loaded_infos, (GHRFunc) remove_item, s);
+	CAMEL_SUMMARY_UNLOCK (s, summary_lock);
+	printf("done .. now %d\n",g_hash_table_size (s->loaded_infos));
+
+	s->cache_load_time = time(NULL);
+	
+	return TRUE;
+}
+
+int
+camel_folder_summary_cache_size (CamelFolderSummary *s)
+{
+	#warning "this is a timely hack. fix it well"
+	if (!CAMEL_IS_VEE_FOLDER(s->folder))
+		return g_hash_table_size (s->loaded_infos);
+	else
+		return s->uids->len;
+}
+
+int
+camel_folder_summary_reload_from_db (CamelFolderSummary *s, CamelException *ex)
+{
+	CamelDB *cdb;
+	char *folder_name;
+	int ret = 0;
+	struct _db_pass_data data;
+	
+	#warning "baseclass this, and vfolders we may have to load better."
+	d(printf ("\ncamel_folder_summary_reload_from_db called \n"));
+
+	folder_name = s->folder->full_name;
+	cdb = s->folder->cdb;
+
+	/* FIXME FOR SANKAR: No need to pass the address of summary here. */
+	data.summary = s;
+	data.double_ref = FALSE;
+	data.add = FALSE;
+	ret = camel_db_read_message_info_records (cdb, folder_name, (gpointer)&data, camel_read_mir_callback, NULL);
+
+	s->cache_load_time = time (NULL);
+	return ret == 0 ? 0 : -1;
+}
+
+int
+camel_folder_summary_load_from_db (CamelFolderSummary *s, CamelException *ex)
+{
+	CamelDB *cdb;
+	char *folder_name;
+	int ret = 0;
+//	struct _db_pass_data data;
+	
+	d(printf ("\ncamel_folder_summary_load_from_db called \n"));
+	s->flags &= ~CAMEL_SUMMARY_DIRTY;
+
+	ret = camel_folder_summary_header_load_from_db (s, s->folder->parent_store, s->folder->full_name, ex);
+
+	if (ret)
+		return ret;
+
+	folder_name = s->folder->full_name;
+	cdb = s->folder->cdb;
+
+	ret = camel_db_get_folder_uids (cdb, folder_name, s->uids, ex);
+#if 0
+	/* FIXME FOR SANKAR: No need to pass the address of summary here. */
+	data.summary = s;
+	data.add = TRUE;
+	data.double_ref = FALSE;
+	ret = camel_db_read_message_info_records (cdb, folder_name, (gpointer) &data, camel_read_mir_callback, ex);
+#endif	
+	s->cache_load_time = time (NULL);
+	#warning "LRU please and not timeouts"
+	s->timeout_handle = g_timeout_add_seconds (SUMMARY_CACHE_DROP, (GSourceFunc) remove_cache, s);
+
+	return ret == 0 ? 0 : -1;
+}
+
+static void
+mir_from_cols (CamelMIRecord *mir, CamelFolderSummary *s, int ncol, char ** cols, char ** name)
+{
+	int i;
+	
+	for (i = 0; i < ncol; ++i) {
+
+		if ( !strcmp (name [i], "uid") ) 
+			mir->uid = (char *) camel_pstring_strdup (cols [i]);
+		else if ( !strcmp (name [i], "flags") ) 
+			mir->flags = cols [i] ? strtoul (cols [i], NULL, 10) : 0;
+		else if ( !strcmp (name [i], "read") ) 
+			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 = (char *) camel_pstring_strdup (cols [i]);
+		else if ( !strcmp (name [i], "mail_from") ) 
+			mir->from = (char *) camel_pstring_strdup (cols [i]);
+		else if ( !strcmp (name [i], "mail_to") ) 
+			mir->to = (char *) camel_pstring_strdup (cols [i]);
+		else if ( !strcmp (name [i], "mail_cc") ) 
+			mir->cc = (char *) camel_pstring_strdup(cols [i]);
+		else if ( !strcmp (name [i], "mlist") ) 
+			mir->mlist = (char *) camel_pstring_strdup (cols [i]);
+		else if ( !strcmp (name [i], "followup_flag") ) 
+			mir->followup_flag = (char *) camel_pstring_strdup(cols [i]);
+		else if ( !strcmp (name [i], "followup_completed_on") ) 
+			mir->followup_completed_on = (char *) camel_pstring_strdup(cols [i]);
+		else if ( !strcmp (name [i], "followup_due_by") ) 
+			mir->followup_due_by = (char *) 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]);
+
+	}	
+}
+
+static int 
+camel_read_mir_callback (void * ref, int ncol, char ** cols, char ** name)
+{
+	struct _db_pass_data *data = (struct _db_pass_data *) ref;
+	CamelFolderSummary *s = data->summary;
+	CamelMIRecord *mir;
+	CamelMessageInfo *info;
+	int ret = 0;
+
+	mir = g_new0 (CamelMIRecord , 1);
+	mir_from_cols (mir, s, ncol, cols, name);
+	
+	CAMEL_SUMMARY_LOCK (s, summary_lock);
+	if (g_hash_table_lookup (s->loaded_infos, mir->uid)) {
+		/* Unlock and better return*/
+		CAMEL_SUMMARY_UNLOCK (s, summary_lock);
+		camel_db_camel_mir_free (mir);
+		return ret;
+	}
+	CAMEL_SUMMARY_UNLOCK (s, summary_lock);
+
+
+	info = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->message_info_from_db (s, mir);
+
+	if (info) {
+
+		if (s->build_content) {
+			char *tmp;
+			tmp = mir->cinfo;
+			/* FIXME: this should be done differently, how i don't know */
+			((CamelMessageInfoBase *)info)->content = perform_content_info_load_from_db (s, mir);
+			if (((CamelMessageInfoBase *)info)->content == NULL) {
+				camel_message_info_free(info);
+				info = NULL;
+			} 
+			mir->cinfo = tmp;
+		}
+
+		if (data->double_ref)
+			/* double reffing, because, at times frees before, I could read it. so we dont ref and give it again, just use it */		
+			camel_message_info_ref(info);
+		
+		/* Just now we are reading from the DB, it can't be dirty. */
+		((CamelMessageInfoBase *)info)->dirty = FALSE;
+		//((CamelMessageInfoBase *)info)->flags &= ~CAMEL_MESSAGE_DB_DIRTY;		
+		if (data->add)
+			camel_folder_summary_add (s, info);
+		else
+			camel_folder_summary_insert (s, info, TRUE);
+
+	} else {
+		g_warning ("Loading messageinfo from db failed");
+		ret = -1;
+	}
+
+	camel_db_camel_mir_free (mir);
+
+	return ret;
+}
 
 /**
  * camel_folder_summary_load:
@@ -558,10 +927,13 @@
 int
 camel_folder_summary_load(CamelFolderSummary *s)
 {
+#if 0
 	FILE *in;
 	int i;
 	CamelMessageInfo *mi;
 
+	d(g_print ("\ncamel_folder_summary_load from FLAT FILE called \n"));
+
 	if (s->summary_path == NULL ||
 	    s->meta_summary->path == NULL)
 		return 0;
@@ -590,7 +962,7 @@
 			}
 		}
 
-		camel_folder_summary_add(s, mi);
+		camel_folder_summary_add (s, mi);
 	}
 
 	CAMEL_SUMMARY_UNLOCK(s, io_lock);
@@ -609,8 +981,32 @@
 	CAMEL_SUMMARY_UNLOCK(s, io_lock);
 	fclose (in);
 	s->flags |= ~CAMEL_SUMMARY_DIRTY;
-
+#endif	
 	return -1;
+
+}
+
+/* saves the content descriptions, recursively */
+static int
+perform_content_info_save_to_db (CamelFolderSummary *s, CamelMessageContentInfo *ci, CamelMIRecord *record)
+{
+	CamelMessageContentInfo *part;
+	char *oldr;
+	if (((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS (s)))->content_info_to_db (s, ci, record) == -1)
+		return -1;
+	
+	oldr = record->cinfo;
+	record->cinfo = g_strdup_printf ("%s %d", oldr, my_list_size ((struct _node **)&ci->childs));
+	g_free (oldr);
+
+	part = ci->childs;
+	while (part) {
+		if (perform_content_info_save_to_db (s, part, record) == -1)
+			return -1;
+		part = part->next;
+	}
+
+	return 0;
 }
 
 /* saves the content descriptions, recursively */
@@ -635,6 +1031,97 @@
 	return 0;
 }
 
+static void
+save_to_db_cb (gpointer key, gpointer value, gpointer data)
+{
+	CamelException *ex = (CamelException *)data;
+	CamelMessageInfoBase *mi = (CamelMessageInfoBase *)value;	
+	CamelFolderSummary *s = (CamelFolderSummary *)mi->summary;
+	char *folder_name = s->folder->full_name;
+	CamelDB *cdb = s->folder->cdb;
+	CamelMIRecord *mir;
+
+	if (!mi->dirty)
+		return;
+
+	mir = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_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) {
+			g_warning ("unable to save mir+cinfo for uid: %s\n", mir->uid);
+			camel_db_camel_mir_free (mir);
+			/* FIXME: Add exception here */
+			return;
+		}
+	}
+
+	if (camel_db_write_message_info_record (cdb, folder_name, mir, ex) != 0) {
+		camel_db_camel_mir_free (mir);
+		return;
+	}
+
+	/* Reset the flags */
+	mi->dirty = FALSE;
+	
+	camel_db_camel_mir_free (mir);	
+}
+
+static int
+save_message_infos_to_db (CamelFolderSummary *s, CamelException *ex)
+{
+	CamelDB *cdb = s->folder->cdb;
+	char *folder_name;
+
+	folder_name = s->folder->full_name;
+	if (camel_db_prepare_message_info_table (cdb, folder_name, ex) != 0) {
+		return -1;
+	}
+	CAMEL_SUMMARY_LOCK(s, summary_lock);
+	/* Push MessageInfo-es */
+	g_hash_table_foreach (s->loaded_infos, save_to_db_cb, ex);
+	CAMEL_SUMMARY_UNLOCK(s, summary_lock);
+#warning "make sure we free the message infos that are loaded are freed if not used anymore or should we leave that to the timer? "
+	
+	return 0;
+}
+
+int
+camel_folder_summary_save_to_db (CamelFolderSummary *s, CamelException *ex)
+{
+	CamelDB *cdb = s->folder->cdb;
+	CamelFIRecord *record;
+	int ret;
+
+	d(printf ("\ncamel_folder_summary_save_to_db called \n"));
+
+	camel_db_begin_transaction (cdb, ex);
+
+	ret = save_message_infos_to_db (s, ex);
+
+	if (ret != 0) {
+		camel_db_abort_transaction (cdb, ex);
+		return -1;
+	}
+
+
+	record = (((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->summary_header_to_db (s, ex));
+	if (!record) {
+		camel_db_abort_transaction (cdb, ex);
+		return -1;
+	}
+
+	ret = camel_db_write_folder_info_record (cdb, record, ex);
+	g_free (record);
+
+	if (ret != 0) {
+		camel_db_abort_transaction (cdb, ex);
+		return -1;
+	}
+
+	camel_db_end_transaction (cdb, ex);
+
+	return ret;
+}
 
 /**
  * camel_folder_summary_save:
@@ -648,6 +1135,7 @@
 int
 camel_folder_summary_save(CamelFolderSummary *s)
 {
+#if 0
 	FILE *out;
 	FILE *out_meta;
 	int fd, i, fd_meta;
@@ -773,10 +1261,39 @@
 	g_unlink (path);
 	g_unlink (path_meta);
 	errno = i;
-
+#endif
 	return -1;
 }
 
+int
+camel_folder_summary_header_load_from_db (CamelFolderSummary *s, CamelStore *store, const char *folder_name, CamelException *ex)
+{
+	CamelDB *cdb;
+	CamelFIRecord *record;
+	int ret = 0;
+
+	d(printf ("\ncamel_folder_summary_load_from_db called \n"));
+	s->flags &= ~CAMEL_SUMMARY_DIRTY;
+
+	cdb = store->cdb;
+
+	record = g_new0 (CamelFIRecord, 1);
+	camel_db_read_folder_info_record (cdb, folder_name, &record, ex);
+
+	if (record) {
+		if ( ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->summary_header_from_db (s, record) == -1)
+			ret = -1;
+	} else {
+		ret = -1;
+	}
+
+	g_free (record->folder_name);
+	#warning "Crashes, take care"
+	//g_free (record->bdata); 
+	g_free (record);
+
+	return ret;
+}
 
 /**
  * camel_folder_summary_header_load:
@@ -791,9 +1308,11 @@
 int
 camel_folder_summary_header_load(CamelFolderSummary *s)
 {
+	int ret=-1;	
+#if 0	
 	FILE *in;
 	FILE *in_meta;
-	int ret;
+
 
 	if (s->summary_path == NULL ||
 	    s->meta_summary->path == NULL)
@@ -817,6 +1336,7 @@
 	fclose(in);
 	fclose(in_meta);
 	s->flags &= ~CAMEL_SUMMARY_DIRTY;
+#endif	
 	return ret;
 }
 
@@ -829,21 +1349,21 @@
 	uid = camel_message_info_uid (info);
 
 	if (uid == NULL || uid[0] == 0) {
-		g_free (info->uid);
-		uid = info->uid = camel_folder_summary_next_uid_string(s);
+		camel_pstring_free (info->uid);
+		uid = info->uid = (char *)camel_pstring_add (camel_folder_summary_next_uid_string(s), TRUE);
 	}
 
 	CAMEL_SUMMARY_LOCK(s, summary_lock);
 
-	while ((mi = g_hash_table_lookup(s->messages_uid, uid))) {
+	while ((mi = g_hash_table_lookup(s->loaded_infos, uid))) {
 		CAMEL_SUMMARY_UNLOCK(s, summary_lock);
 
 		if (mi == info)
 			return 0;
 
-		d(printf ("Trying to insert message with clashing uid (%s).  new uid re-assigned", camel_message_info_uid(info)));
+		d(printf ("Trying to insert message with clashing uid (%s).  new uid re-assigned", camel_message_info_uid (info)));
 
-		g_free(info->uid);
+		camel_pstring_free (info->uid);
 		uid = info->uid = camel_folder_summary_next_uid_string(s);
 
 		camel_message_info_set_flags(info, CAMEL_MESSAGE_FOLDER_FLAGGED, CAMEL_MESSAGE_FOLDER_FLAGGED);
@@ -871,14 +1391,15 @@
  * class.  And MUST NOT be allocated directly using malloc.
  **/
 void
-camel_folder_summary_add(CamelFolderSummary *s, CamelMessageInfo *info)
+camel_folder_summary_add (CamelFolderSummary *s, CamelMessageInfo *info)
 {
 	if (info == NULL)
 		return;
 
+	
 	if (summary_assign_uid(s, info) == 0)
 		return;
-
+	
 	CAMEL_SUMMARY_LOCK(s, summary_lock);
 
 /* unnecessary for pooled vectors */
@@ -888,14 +1409,49 @@
 	info->strings = e_strv_pack(info->strings);
 #endif
 
-	g_ptr_array_add(s->messages, info);
-	g_hash_table_insert(s->messages_uid, (char *)camel_message_info_uid(info), info);
+	/* Summary always holds a ref for the loaded infos */
+	//camel_message_info_ref(info); //FIXME: Check how things are loaded.
+	#warning "FIXME: 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->loaded_infos, (gpointer) camel_message_info_uid (info), info);
 	s->flags |= CAMEL_SUMMARY_DIRTY;
 
 	CAMEL_SUMMARY_UNLOCK(s, summary_lock);
 }
 
 
+void
+camel_folder_summary_insert (CamelFolderSummary *s, CamelMessageInfo *info, gboolean load)
+{
+	if (info == NULL)
+		return;
+
+	CAMEL_SUMMARY_LOCK(s, summary_lock);
+
+/* unnecessary for pooled vectors */
+#ifdef DOESTRV
+	/* this is vitally important, and also if this is ever modified, then
+	   the hash table needs to be resynced */
+	info->strings = e_strv_pack(info->strings);
+#endif
+
+	/* Summary always holds a ref for the loaded infos */
+	//camel_message_info_ref(info); //FIXME: Check how things are loaded.
+	#warning "FIXME: 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, (char *) camel_pstring_strdup(camel_message_info_uid(info)));
+	
+	g_hash_table_insert (s->loaded_infos, (char *) camel_message_info_uid (info), info);
+	if (!load)
+		s->flags |= CAMEL_SUMMARY_DIRTY;
+
+	CAMEL_SUMMARY_UNLOCK(s, summary_lock);	
+}
+
+
 /**
  * camel_folder_summary_add_from_header:
  * @summary: a #CamelFolderSummary object
@@ -914,7 +1470,7 @@
 {
 	CamelMessageInfo *info = camel_folder_summary_info_new_from_header(s, h);
 
-	camel_folder_summary_add(s, info);
+	camel_folder_summary_add (s, info);
 
 	return info;
 }
@@ -943,7 +1499,7 @@
 
 	info = camel_folder_summary_info_new_from_parser(s, mp);
 
-	camel_folder_summary_add(s, info);
+	camel_folder_summary_add (s, info);
 
 	return info;
 }
@@ -959,11 +1515,11 @@
  * Returns the newly added record
  **/
 CamelMessageInfo *
-camel_folder_summary_add_from_message(CamelFolderSummary *s, CamelMimeMessage *msg)
+camel_folder_summary_add_from_message (CamelFolderSummary *s, CamelMimeMessage *msg)
 {
 	CamelMessageInfo *info = camel_folder_summary_info_new_from_message(s, msg);
 
-	camel_folder_summary_add(s, info);
+	camel_folder_summary_add (s, info);
 
 	return info;
 }
@@ -1149,7 +1705,6 @@
 	CAMEL_SUMMARY_UNLOCK(s, summary_lock);
 }
 
-
 /**
  * camel_folder_summary_clear:
  * @summary: a #CamelFolderSummary object
@@ -1159,6 +1714,7 @@
 void
 camel_folder_summary_clear(CamelFolderSummary *s)
 {
+#if 0
 	int i;
 
 	CAMEL_SUMMARY_LOCK(s, summary_lock);
@@ -1176,8 +1732,74 @@
 	s->flags |= CAMEL_SUMMARY_DIRTY;
 	s->meta_summary->msg_expunged = TRUE;
 	CAMEL_SUMMARY_UNLOCK(s, summary_lock);
+#endif	
+}
+
+/* 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 */
+
+void
+camel_folder_summary_clear_db (CamelFolderSummary *s)
+{
+	CamelDB *cdb;
+	char *folder_name;
+
+	d(printf ("\ncamel_folder_summary_load_from_db called \n"));
+	s->flags &= ~CAMEL_SUMMARY_DIRTY;
+
+	folder_name = s->folder->full_name;
+	cdb = s->folder->cdb;
+
+	CAMEL_SUMMARY_LOCK(s, summary_lock);
+	if (camel_folder_summary_count(s) == 0) {
+		CAMEL_SUMMARY_UNLOCK(s, summary_lock);
+		return;
+	}
+
+
+	camel_db_clear_folder_summary (cdb, folder_name, NULL);
+	g_ptr_array_foreach (s->uids, (GFunc) camel_pstring_free, NULL);
+	g_ptr_array_free (s->uids, TRUE);
+	s->uids = g_ptr_array_new ();
+
+	g_hash_table_destroy(s->loaded_infos);
+	s->loaded_infos = g_hash_table_new(g_str_hash, g_str_equal);
+
+	s->flags |= CAMEL_SUMMARY_DIRTY;
+	CAMEL_SUMMARY_UNLOCK(s, summary_lock);
 }
 
+static void
+summary_remove_uid (CamelFolderSummary *s, const char *uid)
+{
+	int i;
+	CamelDB *cdb;
+	CamelException ex;// May be this should come from the caller 
+	char *folder_name;
+
+	d(printf ("\nsummary_remove_uid called \n"));
+	camel_exception_init (&ex);
+
+	folder_name = s->folder->full_name;
+	cdb = s->folder->cdb;
+
+	if (camel_db_delete_uid (cdb, folder_name, uid, &ex) != 0)
+		return ;
+
+	/* 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);
+			break;
+		}
+
+	}
+
+	return ;
+}
 
 /**
  * camel_folder_summary_remove:
@@ -1187,11 +1809,14 @@
  * Remove a specific @info record from the summary.
  **/
 void
-camel_folder_summary_remove(CamelFolderSummary *s, CamelMessageInfo *info)
+camel_folder_summary_remove (CamelFolderSummary *s, CamelMessageInfo *info)
 {
 	CAMEL_SUMMARY_LOCK(s, summary_lock);
-	g_hash_table_remove(s->messages_uid, camel_message_info_uid(info));
-	g_ptr_array_remove(s->messages, info);
+
+	g_hash_table_remove (s->loaded_infos, camel_message_info_uid(info));	
+	summary_remove_uid (s, camel_message_info_uid(info));
+
+	
 	s->flags |= CAMEL_SUMMARY_DIRTY;
 	s->meta_summary->msg_expunged = TRUE;
 	CAMEL_SUMMARY_UNLOCK(s, summary_lock);
@@ -1215,7 +1840,7 @@
 
 	CAMEL_SUMMARY_LOCK(s, summary_lock);
 	CAMEL_SUMMARY_LOCK(s, ref_lock);
-        if (g_hash_table_lookup_extended(s->messages_uid, uid, (void *)&olduid, (void *)&oldinfo)) {
+        if (g_hash_table_lookup_extended(s->loaded_infos, uid, (void *)&olduid, (void *)&oldinfo)) {
 		/* make sure it doesn't vanish while we're removing it */
 		oldinfo->refcount++;
 		CAMEL_SUMMARY_UNLOCK(s, ref_lock);
@@ -1223,11 +1848,42 @@
 		camel_folder_summary_remove(s, oldinfo);
 		camel_message_info_free(oldinfo);
 	} else {
+		/* Info isn't loaded into the memory. We must just remove the UID*/
+		summary_remove_uid (s, uid);
 		CAMEL_SUMMARY_UNLOCK(s, ref_lock);
 		CAMEL_SUMMARY_UNLOCK(s, summary_lock);
+
+		
 	}
 }
 
+void
+camel_folder_summary_remove_index_fast (CamelFolderSummary *s, int index)
+{
+	const char *uid = s->uids->pdata[index];
+        CamelMessageInfo *oldinfo;
+        char *olduid;
+	
+	CAMEL_SUMMARY_LOCK(s, summary_lock);
+	CAMEL_SUMMARY_LOCK(s, ref_lock);
+
+	if (g_hash_table_lookup_extended(s->loaded_infos, uid, (void *)&olduid, (void *)&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_SUMMARY_UNLOCK(s, ref_lock);
+		CAMEL_SUMMARY_UNLOCK(s, 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_SUMMARY_UNLOCK(s, ref_lock);
+		CAMEL_SUMMARY_UNLOCK(s, summary_lock);
+
+		
+	}	
+}
 
 /**
  * camel_folder_summary_remove_index:
@@ -1239,19 +1895,9 @@
 void
 camel_folder_summary_remove_index(CamelFolderSummary *s, int index)
 {
-	CAMEL_SUMMARY_LOCK(s, summary_lock);
-	if (index < s->messages->len) {
-		CamelMessageInfo *info = s->messages->pdata[index];
+	const char *uid = s->uids->pdata[index];
 
-		g_hash_table_remove(s->messages_uid, camel_message_info_uid(info));
-		g_ptr_array_remove_index(s->messages, index);
-		s->flags |= CAMEL_SUMMARY_DIRTY;
-
-		CAMEL_SUMMARY_UNLOCK(s, summary_lock);
-		camel_message_info_free(info);
-	} else {
-		CAMEL_SUMMARY_UNLOCK(s, summary_lock);
-	}
+	camel_folder_summary_remove_uid (s, uid);
 }
 
 
@@ -1264,35 +1910,49 @@
  * Removes an indexed range of info records.
  **/
 void
-camel_folder_summary_remove_range(CamelFolderSummary *s, int start, int end)
+camel_folder_summary_remove_range (CamelFolderSummary *s, int start, int end)
 {
+	d(g_print ("\ncamel_folder_summary_remove_range called \n"));
 	if (end < start)
 		return;
 
 	CAMEL_SUMMARY_LOCK(s, summary_lock);
-	if (start < s->messages->len) {
-		CamelMessageInfo **infos;
+
+	if (start < s->uids->len) {
+
 		int i;
+		CamelDB *cdb;
+		CamelException ex;// May be this should come from the caller 
+		char *folder_name;
+		GSList *uids = NULL;
+
+		end = MIN(end+1, s->uids->len);
 
-		end = MIN(end+1, s->messages->len);
-		infos = g_malloc((end-start)*sizeof(infos[0]));
+		for (i = start; i < end; i++) {
+			const char *uid = s->uids->pdata[i];
 
-		for (i=start;i<end;i++) {
-			CamelMessageInfo *info = s->messages->pdata[i];
+			uids = g_slist_prepend (uids, (gpointer) uid);
 
-			infos[i-start] = info;
-			g_hash_table_remove(s->messages_uid, camel_message_info_uid(info));
+			g_hash_table_remove(s->loaded_infos, uid);
 		}
+		camel_exception_init (&ex);
+
+		folder_name = s->folder->full_name;
+		cdb = s->folder->cdb;
+
+		#warning "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, &ex);
+
+		g_slist_foreach (uids, (GFunc) camel_pstring_free, NULL);
+		g_slist_free (uids);
+
+		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));
 
-		memmove(s->messages->pdata+start, s->messages->pdata+end, (s->messages->len-end)*sizeof(s->messages->pdata[0]));
-		g_ptr_array_set_size(s->messages, s->messages->len - (end - start));
 		s->flags |= CAMEL_SUMMARY_DIRTY;
 
 		CAMEL_SUMMARY_UNLOCK(s, summary_lock);
 
-		for (i=start;i<end;i++)
-			camel_message_info_free(infos[i-start]);
-		g_free(infos);
 	} else {
 		CAMEL_SUMMARY_UNLOCK(s, summary_lock);
 	}
@@ -1490,14 +2150,49 @@
 	io(printf("Loading meta-header\n"));
 
 	if (camel_file_util_decode_uint32(in, &s->meta_summary->major) == -1
-	    || camel_file_util_decode_uint32(in, &s->meta_summary->minor) == -1
-	    || camel_file_util_decode_uint32(in, &s->meta_summary->uid_len) == -1) {
+	    || camel_file_util_decode_uint32(in, &s->meta_summary->minor) == -1	    || camel_file_util_decode_uint32(in, &s->meta_summary->uid_len) == -1) {
 		return -1;
 	}
 	
 	return 0;
 }
 
+static	int
+summary_header_from_db (CamelFolderSummary *s, CamelFIRecord *record)
+{
+	io(printf("Loading header from db \n"));
+	
+	s->version = record->version;
+
+	/* We may not worry, as we are setting a new standard here */
+#if 0	
+	/* Legacy version check, before version 12 we have no upgrade knowledge */
+	if ((s->version > 0xff) && (s->version & 0xff) < 12) {
+		io(printf ("Summary header version mismatch"));
+		errno = EINVAL;
+		return -1;
+	}
+
+	if (!(s->version < 0x100 && s->version >= 13))
+		io(printf("Loading legacy summary\n"));
+	else
+		io(printf("loading new-format summary\n"));
+#endif
+	
+	s->flags = record->flags;
+	s->nextuid = record->nextuid;
+	s->time = record->time;
+	s->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;
+	
+	return 0;	
+}
+
 static int
 summary_header_load(CamelFolderSummary *s, FILE *in)
 {
@@ -1542,6 +2237,43 @@
 	return 0;
 }
 
+static	CamelFIRecord *
+summary_header_to_db (CamelFolderSummary *s, CamelException *ex)
+{
+	CamelFIRecord * record = g_new0 (CamelFIRecord, 1);
+	CamelDB *db;
+
+	db = s->folder->cdb;
+	//char *table_name = safe_table (camel_file_util_safe_filename (s->folder->full_name));
+	char *table_name = s->folder->full_name;
+
+	io(printf("Savining header to db\n"));
+
+	record->folder_name = table_name;
+
+	/* we always write out the current version */
+	record->version = CAMEL_FOLDER_SUMMARY_VERSION;
+	record->flags  = s->flags;
+	record->nextuid = s->nextuid;
+	record->time = s->time;
+
+	/* FIXME: Ever heard of Constructors and initializing ? */
+	if (camel_db_count_total_message_info (db, table_name, &(record->saved_count), NULL))
+		record->saved_count = 0;
+	if (camel_db_count_junk_message_info (db, table_name, &(record->junk_count), NULL))
+		record->junk_count = 0;
+	if (camel_db_count_deleted_message_info (db, table_name, &(record->deleted_count), NULL))
+		record->deleted_count = 0;
+	if (camel_db_count_unread_message_info (db, table_name, &(record->unread_count), NULL))
+		record->unread_count = 0;
+	if (camel_db_count_visible_message_info (db, table_name, &(record->visible_count), NULL))
+		record->visible_count = 0;
+	if (camel_db_count_junk_not_deleted_message_info (db, table_name, &(record->jnd_count), NULL))
+		record->jnd_count = 0;
+	
+	return record;	
+}
+
 static int
 summary_header_save(CamelFolderSummary *s, FILE *out)
 {
@@ -1724,9 +2456,17 @@
 	CamelMessageContentInfo *ci;
 
 	CAMEL_SUMMARY_LOCK(s, alloc_lock);
+#ifndef ALWAYS_ALLOC	
 	if (s->content_info_chunks == NULL)
 		s->content_info_chunks = e_memchunk_new(32, s->content_info_size);
 	ci = e_memchunk_alloc(s->content_info_chunks);
+#else	
+#ifndef USE_GSLICE
+	ci = g_malloc (s->content_info_size);
+#else	
+	ci = g_slice_alloc (s->content_info_size);
+#endif	
+#endif	
 	CAMEL_SUMMARY_UNLOCK(s, alloc_lock);
 
 	memset(ci, 0, s->content_info_size);
@@ -1842,6 +2582,81 @@
 }
 
 static CamelMessageInfo *
+message_info_from_db (CamelFolderSummary *s, CamelMIRecord *record)
+{
+	CamelMessageInfoBase *mi;
+	int i;
+	int count;
+	char *part, *label;
+	
+	mi = (CamelMessageInfoBase *)camel_message_info_new(s);
+
+	io(printf("Loading message info from db\n"));
+
+	mi->flags = record->flags;
+	mi->size = record->size;
+	mi->date_sent = record->dsent;
+	mi->date_received = record->dreceived;
+
+	mi->uid = (char *) camel_pstring_strdup (record->uid);
+	mi->subject = (char *) camel_pstring_add (record->subject, FALSE);
+	mi->from = (char *) camel_pstring_add (record->from, FALSE);
+	mi->to = (char *) camel_pstring_add (record->to, FALSE);
+	mi->cc = (char *) camel_pstring_add (record->cc, FALSE);
+	mi->mlist = (char *) camel_pstring_add (record->mlist, FALSE);
+
+	/* Extract Message id & References */
+	mi->content = NULL;
+	part = record->part;
+	if (part) {
+		EXTRACT_FIRST_DIGIT (mi->message_id.id.part.hi)
+		EXTRACT_DIGIT (mi->message_id.id.part.lo)
+		EXTRACT_DIGIT (count)
+	
+		if (count > 0) {
+			mi->references = g_malloc(sizeof(*mi->references) + ((count-1) * sizeof(mi->references->references[0])));
+			mi->references->size = count;
+			for (i=0;i<count;i++) {
+				EXTRACT_DIGIT (mi->references->references[i].id.part.hi)
+				EXTRACT_DIGIT (mi->references->references[i].id.part.lo)
+			}
+		} else
+			mi->references = NULL;
+		
+	}
+
+	/* Extract User flags/labels */
+	part = record->labels;
+	if (part) {
+		label = part;
+		for (i=0;part[i];i++) {
+
+			if (part[i] == ' ') {
+				part[i] = 0;
+				camel_flag_set(&mi->user_flags, label, TRUE);
+				label = &(part[i+1]);
+			}
+		}
+		camel_flag_set(&mi->user_flags, label, TRUE);
+	}
+
+	/* Extract User tags */
+	part = record->usertags;
+	EXTRACT_FIRST_DIGIT (count)
+	for (i=0;i<count;i++) {
+		int len;
+		char *name, *value;
+		EXTRACT_STRING (name)
+		EXTRACT_STRING (value)
+		camel_tag_set(&mi->user_tags, name, value);
+		g_free(name);
+		g_free(value);
+	}	
+
+	return (CamelMessageInfo *) mi;
+}
+
+static CamelMessageInfo *
 message_info_load(CamelFolderSummary *s, FILE *in)
 {
 	CamelMessageInfoBase *mi;
@@ -1940,6 +2755,84 @@
 	return ferror(out);
 }
 
+
+static CamelMIRecord *
+message_info_to_db (CamelFolderSummary *s, CamelMessageInfo *info)
+{
+	CamelMIRecord *record = g_new0(CamelMIRecord, 1);
+	CamelMessageInfoBase *mi = (CamelMessageInfoBase *) info;
+	GString *tmp;
+	CamelFlag *flag;
+	CamelTag *tag;
+	int count, i;
+
+	/* Assume that we dont have to take care of DB Safeness. It will be done while doing the DB transaction */
+	record->uid = (char *) camel_pstring_strdup(camel_message_info_uid(mi));
+	record->flags = mi->flags;
+	
+	record->read =  ((mi->flags & (CAMEL_MESSAGE_SEEN|CAMEL_MESSAGE_DELETED|CAMEL_MESSAGE_JUNK)));
+	record->deleted = mi->flags & CAMEL_MESSAGE_DELETED;
+	record->replied = mi->flags & CAMEL_MESSAGE_ANSWERED;	
+	record->important = mi->flags & CAMEL_MESSAGE_FLAGGED;		
+	record->junk = mi->flags & CAMEL_MESSAGE_JUNK;
+	record->attachment = mi->flags & CAMEL_MESSAGE_ATTACHMENTS;
+	
+	record->size = mi->size;
+	record->dsent = mi->date_sent;
+	record->dreceived = mi->date_received;
+
+	record->subject = (char *) camel_pstring_strdup(camel_message_info_subject (mi));
+	record->from = (char *) camel_pstring_strdup(camel_message_info_from (mi));
+	record->to = (char *) camel_pstring_strdup(camel_message_info_to (mi));
+	record->cc = (char *) camel_pstring_strdup(camel_message_info_cc (mi));
+	record->mlist = (char *) camel_pstring_strdup(camel_message_info_mlist (mi));
+	
+	record->followup_flag = (char *) camel_pstring_strdup(camel_message_info_user_tag(info, "follow-up"));
+	record->followup_completed_on = (char *) camel_pstring_strdup(camel_message_info_user_tag(info, "completed-on"));
+ 	record->followup_due_by = (char *) camel_pstring_strdup(camel_message_info_user_tag(info, "due-by"));
+
+	tmp = g_string_new (NULL);
+	if (mi->references) {
+		g_string_append_printf (tmp, "%lu %lu %lu", (long unsigned)mi->message_id.id.part.hi, (long unsigned)mi->message_id.id.part.lo, (long unsigned)mi->references->size);
+		for (i=0;i<mi->references->size;i++) 
+			g_string_append_printf (tmp, " %lu %lu", (long unsigned)mi->references->references[i].id.part.hi, (long unsigned)mi->references->references[i].id.part.lo);
+	} else {
+		g_string_append_printf (tmp, "%lu %lu %lu", (long unsigned)mi->message_id.id.part.hi, (long unsigned)mi->message_id.id.part.lo, (unsigned long) 0);
+	}
+	record->part = tmp->str;
+	g_string_free (tmp, FALSE);
+
+	tmp = g_string_new (NULL);
+	flag = mi->user_flags;
+	while (flag) {
+		g_string_append_printf (tmp, "%s ", flag->name);
+		flag = flag->next;
+	}
+
+	/* Strip off the last space */ 
+	if (tmp->len)
+		tmp->len--;
+	
+	record->labels = tmp->str;
+	g_string_free (tmp, FALSE);
+
+	tmp = g_string_new (NULL);	
+	count = camel_tag_list_size(&mi->user_tags);
+	g_string_append_printf (tmp, "%lu", (long unsigned)count);	
+	tag = mi->user_tags;
+	while (tag) {
+		/* FIXME: Should we handle empty tags? Can it be empty? If it potential crasher ahead*/
+		g_string_append_printf (tmp, " %lu-%s %lu-%s", (long unsigned)strlen(tag->name), tag->name, (long unsigned)strlen(tag->value), tag->value);		
+		tag = tag->next;
+	}
+	record->usertags = tmp->str;
+	g_string_free (tmp, FALSE);
+		
+
+	return record;
+}
+
+
 static int
 message_info_save(CamelFolderSummary *s, FILE *out, CamelMessageInfo *info)
 {
@@ -1999,8 +2892,11 @@
 message_info_free(CamelFolderSummary *s, CamelMessageInfo *info)
 {
 	CamelMessageInfoBase *mi = (CamelMessageInfoBase *)info;
-
-	g_free(mi->uid);
+	
+	if (mi->uid) {
+		g_hash_table_remove (s->loaded_infos, mi->uid);
+		camel_pstring_free(mi->uid);
+	} 
 	camel_pstring_free(mi->subject);
 	camel_pstring_free(mi->from);
 	camel_pstring_free(mi->to);
@@ -2014,9 +2910,21 @@
 	
 
 	if (s)
-		e_memchunk_free(s->message_info_chunks, mi);
+#ifndef ALWAYS_ALLOC
+		e_memchunk_free(s->message_info_chunks, mi);		
+#else
+#ifndef USE_GSLICE	
+		g_free(mi);
+#else		
+	        g_slice_free1 (s->message_info_size, mi);
+#endif		
+#endif
 	else
+#ifndef USE_GSLICE
 		g_free(mi);
+#else		
+		g_slice_free (CamelMessageInfoBase, mi);
+#endif		
 }
 
 static CamelMessageContentInfo *
@@ -2037,6 +2945,56 @@
 }
 
 static CamelMessageContentInfo *
+content_info_from_db(CamelFolderSummary *s, CamelMIRecord *record)
+{
+	CamelMessageContentInfo *ci;
+	char *type, *subtype;
+	guint32 count, i;
+	CamelContentType *ct;
+	char *part = record->cinfo;
+	int len;
+
+	io(printf("Loading content info from db\n"));
+	
+	if (!part)
+		return NULL;
+	
+	ci = camel_folder_summary_content_info_new(s);
+	if (*part == ' ') part++; /* Move off the space in the record*/
+
+	EXTRACT_FIRST_STRING (type)
+	EXTRACT_STRING (subtype)
+	ct = camel_content_type_new(type, subtype);
+	g_free(type);		/* can this be removed? */
+	g_free(subtype);
+	EXTRACT_DIGIT (count)
+
+	for (i = 0; i < count; i++) {
+		char *name, *value;
+		EXTRACT_STRING (name)
+		EXTRACT_STRING (value)
+
+		camel_content_type_set_param(ct, name, value);
+		/* TODO: do this so we dont have to double alloc/free */
+		g_free(name);
+		g_free(value);
+	}
+	ci->type = ct;
+
+	#warning "move all these to camel pstring"
+	EXTRACT_STRING (ci->id);
+	EXTRACT_STRING (ci->description)
+	EXTRACT_STRING (ci->encoding)
+	EXTRACT_DIGIT (ci->size)
+
+	record->cinfo = part; /* Keep moving the cursor in the record */
+
+	ci->childs = NULL;
+
+	return ci;
+}
+
+static CamelMessageContentInfo *
 content_info_load(CamelFolderSummary *s, FILE *in)
 {
 	CamelMessageContentInfo *ci;
@@ -2088,6 +3046,71 @@
 }
 
 static int
+content_info_to_db(CamelFolderSummary *s, CamelMessageContentInfo *ci, CamelMIRecord *record)
+{
+	CamelContentType *ct;
+	struct _camel_header_param *hp;
+	GString *str = g_string_new (NULL);
+	char *oldr;
+	
+	io(printf("Saving content info to db\n"));
+
+	ct = ci->type;
+	if (ct) {
+		if (ct->type)
+			g_string_append_printf (str, " %d-%s", strlen (ct->type), ct->type);
+		else 
+			g_string_append_printf (str, " 0-");
+		if (ct->subtype)
+			g_string_append_printf (str, " %d-%s", strlen (ct->subtype), ct->subtype);
+		else 
+			g_string_append_printf (str, " 0-");
+		g_string_append_printf (str, " %d", my_list_size((struct _node **)&ct->params));
+		hp = ct->params;
+		while (hp) {
+			if (hp->name)
+				g_string_append_printf (str, " %d-%s", strlen(hp->name), hp->name);
+			else 
+				g_string_append_printf (str, " 0-");
+			if (hp->value)
+				g_string_append_printf (str, " %d-%s", strlen (hp->value), hp->value);
+			else
+				g_string_append_printf (str, " 0-");
+			hp = hp->next;
+		}
+	} else {
+		g_string_append_printf (str, " %d-", 0);
+		g_string_append_printf (str, " %d-", 0);
+		g_string_append_printf (str, " %d", 0);
+	}
+
+	if (ci->id)
+		g_string_append_printf (str, " %d-%s", strlen (ci->id), ci->id);
+	else 
+		g_string_append_printf (str, " 0-");
+	if (ci->description)
+		g_string_append_printf (str, " %d-%s", strlen (ci->description), ci->description);
+	else
+		g_string_append_printf (str, " 0-");
+	if (ci->encoding)
+		g_string_append_printf (str, " %d-%s", strlen (ci->encoding), ci->encoding);
+	else
+		g_string_append_printf (str, " 0-");
+	g_string_append_printf (str, " %u", ci->size);
+
+	if (record->cinfo) {
+		oldr = record->cinfo;
+		record->cinfo = g_strconcat(oldr, str->str, NULL);
+		g_free (oldr); g_string_free (str, TRUE);
+	} else {
+		record->cinfo = str->str;
+		g_string_free (str, FALSE);
+	}
+
+	return 0;	
+}
+
+static int
 content_info_save(CamelFolderSummary *s, FILE *out, CamelMessageContentInfo *ci)
 {
 	CamelContentType *ct;
@@ -2125,7 +3148,15 @@
 	g_free(ci->id);
 	g_free(ci->description);
 	g_free(ci->encoding);
+#ifndef ALWAYS_ALLOC	
 	e_memchunk_free(s->content_info_chunks, ci);
+#else
+#ifndef USE_GSLICE	
+	g_free(ci);
+#else	
+	g_slice_free1 (s->content_info_size, ci);
+#endif	
+#endif	
 }
 
 static char *
@@ -2416,6 +3447,9 @@
 {
 	CamelFlag *flag, *tmp;
 
+	if (!name)
+		return TRUE;
+
 	/* this 'trick' works because flag->next is the first element */
 	flag = (CamelFlag *)list;
 	while (flag->next) {
@@ -2759,17 +3793,34 @@
 
 	if (s) {
 		CAMEL_SUMMARY_LOCK(s, alloc_lock);
+#ifndef ALWAYS_ALLOC		
 		if (s->message_info_chunks == NULL)
 			s->message_info_chunks = e_memchunk_new(32, s->message_info_size);
 		info = e_memchunk_alloc0(s->message_info_chunks);
+#else
+#ifndef USE_GSLICE		
+		info = g_malloc0(s->message_info_size);
+#else		
+		info = g_slice_alloc0 (s->message_info_size);
+#endif		
+#endif		
 		CAMEL_SUMMARY_UNLOCK(s, alloc_lock);
 	} else {
+#ifndef USE_GSLICE		
 		info = g_malloc0(sizeof(CamelMessageInfoBase));
+#else		
+		info = g_slice_alloc0 (sizeof(CamelMessageInfoBase));
+#endif
+
+		
 	}
 
 	info->refcount = 1;
 	info->summary = s;
 
+	/* We assume that mi is always dirty unless freshly read or just saved*/
+	((CamelMessageInfoBase *)info)->dirty = TRUE;
+	
 	return info;
 }
 
@@ -3101,13 +4152,23 @@
 {
 	guint32 old;
 	CamelMessageInfoBase *mi = (CamelMessageInfoBase *)info;
-
+	int 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; 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; ;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; ;printf("Setting junk as %d\n", set & CAMEL_MESSAGE_JUNK ? 1 : 0);}
+	
 	old = mi->flags;
 	mi->flags = (old & ~flags) | (set & flags);
 	if (old != mi->flags) {
 		mi->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED;
+		mi->dirty = TRUE;
 		if (mi->summary)
 			camel_folder_summary_touch(mi->summary);
 	}
@@ -3123,6 +4184,20 @@
 		camel_folder_change_info_free(changes);
 	}
 
+	if (mi->summary) {
+		if (read)
+			mi->summary->unread_count -= read;
+		if (deleted)
+			mi->summary->deleted_count += deleted;
+		if (junk)
+			mi->summary->junk_count += junk;
+		if (junk && !deleted)
+			mi->summary->junk_not_deleted_count += junk;
+		if (junk ||  deleted) 
+			mi->summary->visible_count -= junk ? junk : deleted;
+	}
+
+	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;
 }
 
@@ -3159,6 +4234,7 @@
 		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_object_trigger_event(mi->summary->folder, "folder_changed", changes);
@@ -3200,6 +4276,7 @@
 		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_object_trigger_event(mi->summary->folder, "folder_changed", changes);
@@ -3285,6 +4362,13 @@
 	klass->summary_header_load = summary_header_load;
 	klass->summary_header_save = summary_header_save;
 
+	klass->summary_header_from_db = summary_header_from_db;
+	klass->summary_header_to_db = summary_header_to_db;
+	klass->message_info_from_db = message_info_from_db;
+	klass->message_info_to_db = message_info_to_db;
+	klass->content_info_from_db = content_info_from_db;
+	klass->content_info_to_db = content_info_to_db;
+
 	klass->message_info_new_from_header  = message_info_new_from_header;
 	klass->message_info_new_from_parser = message_info_new_from_parser;
 	klass->message_info_new_from_message = message_info_new_from_message;
@@ -3293,7 +4377,8 @@
 	klass->meta_message_info_save = meta_message_info_save;
 	klass->message_info_free = message_info_free;
 	klass->message_info_clone = message_info_clone;
-
+	klass->message_info_from_uid = message_info_from_uid;
+	
 	klass->content_info_new_from_header  = content_info_new_from_header;
 	klass->content_info_new_from_parser = content_info_new_from_parser;
 	klass->content_info_new_from_message = content_info_new_from_message;

Modified: trunk/camel/camel-folder-summary.h
==============================================================================
--- trunk/camel/camel-folder-summary.h	(original)
+++ trunk/camel/camel-folder-summary.h	Wed Jul 16 11:38:32 2008
@@ -27,6 +27,7 @@
 #include <camel/camel-mime-parser.h>
 #include <camel/camel-object.h>
 #include <camel/camel-index.h>
+#include <camel/camel-db.h>
 
 #define CAMEL_FOLDER_SUMMARY_TYPE         camel_folder_summary_get_type ()
 #define CAMEL_FOLDER_SUMMARY(obj)         CAMEL_CHECK_CAST (obj, camel_folder_summary_get_type (), CamelFolderSummary)
@@ -80,7 +81,7 @@
 
 	/* following flags are for the folder, and are not really permanent flags */
 	CAMEL_MESSAGE_FOLDER_FLAGGED = 1<<16, /* for use by the folder implementation */
-
+	CAMEL_MESSAGE_DB_DIRTY = 1<<17, /* To say whether the changes are syned to db.*/
 	/* flags after 1<<16 are used by camel providers,
            if adding non permanent flags, add them to the end  */
 
@@ -152,6 +153,8 @@
 
 	guint32 refcount;	/* ??? */
 	char *uid;
+	/*FIXME: Make it work with the CAMEL_MESSADE_DB_DIRTY flag instead of another 4 bytes*/
+	int dirty:1;
 };
 
 /* For classes wishing to do the provided i/o, or for anonymous users,
@@ -162,7 +165,9 @@
 
 	guint32 refcount;	/* ??? */
 	char *uid;
-
+	/*FIXME: Make it work with the CAMEL_MESSADE_DB_DIRTY flag instead of another 4 bytes*/
+	int dirty:1;
+	
 	const char *subject;
 	const char *from;
 	const char *to;
@@ -184,6 +189,8 @@
 	/* tree of content description - NULL if it is not available */
 	CamelMessageContentInfo *content;
 	struct _camel_header_param *headers;
+
+
 };
 
 /* probably do this as well, removing CamelFolderChangeInfo and interfaces 
@@ -214,7 +221,9 @@
 	guint32 unread_count;	/* handy totals */
 	guint32 deleted_count;
 	guint32 junk_count;
-
+	guint32 junk_not_deleted_count;
+	guint32 visible_count;
+	
 	/* sizes of memory objects */
 	guint32 message_info_size;
 	guint32 content_info_size;
@@ -226,11 +235,18 @@
 	char *summary_path;
 	gboolean build_content;	/* do we try and parse/index the content, or not? */
 
-	GPtrArray *messages;	/* CamelMessageInfo's */
-	GHashTable *messages_uid; /* CamelMessageInfo's by uid */
+	/* Deprecated */
+//	GPtrArray *messages;	/* CamelMessageInfo's */
+//	GHashTable *messages_uid; /* CamelMessageInfo's by uid */
+
+	/* 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;
 };
 
 struct _CamelFolderSummaryClass {
@@ -240,6 +256,14 @@
 	int (*summary_header_load)(CamelFolderSummary *, FILE *);
 	int (*summary_header_save)(CamelFolderSummary *, FILE *);
 
+	/* Load/Save folder summary from DB*/
+	int (*summary_header_from_db)(CamelFolderSummary *, CamelFIRecord *);
+	CamelFIRecord * (*summary_header_to_db)(CamelFolderSummary *, CamelException *ex);
+	CamelMessageInfo * (*message_info_from_db) (CamelFolderSummary *, struct _CamelMIRecord*);
+	CamelMIRecord * (*message_info_to_db) (CamelFolderSummary *, CamelMessageInfo *);
+	CamelMessageContentInfo * (*content_info_from_db) (CamelFolderSummary *, CamelMIRecord *);
+	int (*content_info_to_db) (CamelFolderSummary *, CamelMessageContentInfo *, CamelMIRecord *);
+	
 	/* create/save/load an individual message info */
 	CamelMessageInfo * (*message_info_new_from_header)(CamelFolderSummary *, struct _camel_header_raw *);
 	CamelMessageInfo * (*message_info_new_from_parser)(CamelFolderSummary *, CamelMimeParser *);
@@ -258,7 +282,7 @@
 	CamelMessageContentInfo * (*content_info_load)(CamelFolderSummary *, FILE *);
 	int		          (*content_info_save)(CamelFolderSummary *, FILE *, CamelMessageContentInfo *);
 	void		          (*content_info_free)(CamelFolderSummary *, CamelMessageContentInfo *);
-
+	CamelMessageInfo * (*message_info_from_uid) (CamelFolderSummary *, const char *);
 	/* get the next uid */
 	char *(*next_uid_string)(CamelFolderSummary *);
 
@@ -294,7 +318,10 @@
 CamelType			 camel_folder_summary_get_type	(void);
 CamelFolderSummary      *camel_folder_summary_new	(struct _CamelFolder *folder);
 
+/* Deprecated */
 void camel_folder_summary_set_filename(CamelFolderSummary *summary, const char *filename);
+
+
 void camel_folder_summary_set_index(CamelFolderSummary *summary, CamelIndex *index);
 void camel_folder_summary_set_build_content(CamelFolderSummary *summary, gboolean state);
 
@@ -306,14 +333,30 @@
 int camel_folder_summary_load(CamelFolderSummary *summary);
 int camel_folder_summary_save(CamelFolderSummary *summary);
 
+/* load/save the full summary from/to the db */
+int camel_folder_summary_save_to_db (CamelFolderSummary *s, CamelException *ex);
+int camel_folder_summary_load_from_db (CamelFolderSummary *s, CamelException *ex);
+
 /* only load the header */
 int camel_folder_summary_header_load(CamelFolderSummary *summary);
+int camel_folder_summary_header_load_from_db (CamelFolderSummary *s, CamelStore *store, const char *folder_name, CamelException *ex);
 
 /* set the dirty bit on the summary */
 void camel_folder_summary_touch(CamelFolderSummary *summary);
 
 /* add a new raw summary item */
-void camel_folder_summary_add(CamelFolderSummary *summary, CamelMessageInfo *info);
+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);
+/* Gets the size of loaded mi's */
+int camel_folder_summary_cache_size (CamelFolderSummary *s);
+/* reload the summary at any required point if required */
+int camel_folder_summary_reload_from_db (CamelFolderSummary *s, CamelException *ex);
+/* insert mi to summary */
+void camel_folder_summary_insert (CamelFolderSummary *s, CamelMessageInfo *info, gboolean load);
+
+void camel_folder_summary_remove_index_fast (CamelFolderSummary *s, int index);
 
 /* build/add raw summary items */
 CamelMessageInfo *camel_folder_summary_add_from_header(CamelFolderSummary *summary, struct _camel_header_raw *headers);
@@ -336,13 +379,18 @@
 
 /* remove all items */
 void camel_folder_summary_clear(CamelFolderSummary *summary);
+void camel_folder_summary_clear_db (CamelFolderSummary *s);
+
+int camel_folder_summary_reload_from_db (CamelFolderSummary *s, CamelException *ex);
+int camel_folder_summary_cache_size (CamelFolderSummary *s);
 
 /* lookup functions */
 int camel_folder_summary_count(CamelFolderSummary *summary);
 CamelMessageInfo *camel_folder_summary_index(CamelFolderSummary *summary, int index);
 CamelMessageInfo *camel_folder_summary_uid(CamelFolderSummary *summary, const char *uid);
+char * camel_folder_summary_uid_from_index (CamelFolderSummary *s, int i);
+
 GPtrArray *camel_folder_summary_array(CamelFolderSummary *summary);
-void camel_folder_summary_array_free(CamelFolderSummary *summary, GPtrArray *array);
 
 /* basically like strings, but certain keywords can be compressed and de-cased */
 int camel_folder_summary_encode_token(FILE *out, const char *str);

Modified: trunk/camel/camel-folder-thread.c
==============================================================================
--- trunk/camel/camel-folder-thread.c	(original)
+++ trunk/camel/camel-folder-thread.c	Wed Jul 16 11:38:32 2008
@@ -618,15 +618,20 @@
 			g_hash_table_insert(wanted, uids->pdata[i], uids->pdata[i]);
 	}
 
-	fsummary = camel_folder_get_summary(folder);
+	fsummary = camel_folder_summary_array (folder->summary);
 	thread->summary = summary = g_ptr_array_new();
+	if (fsummary->len - camel_folder_summary_cache_size (folder->summary) > 50)
+		camel_folder_summary_reload_from_db (folder->summary, NULL);
 
-	for (i=0;i<fsummary->len;i++) {
-		CamelMessageInfo *info = fsummary->pdata[i];
-
-		if (wanted == NULL || g_hash_table_lookup(wanted, camel_message_info_uid(info)) != NULL) {
-			camel_folder_ref_message_info(folder, info);
-			g_ptr_array_add(summary, info);
+	for (i = 0 ; i < fsummary->len ; i++) {
+		CamelMessageInfo *info ;
+		char *uid = fsummary->pdata[i];
+
+		if (wanted == NULL || g_hash_table_lookup(wanted, uid) != NULL) {
+			info = camel_folder_get_message_info (folder, uid);
+			if (info)
+				g_ptr_array_add(summary, info);
+			/* FIXME: Check if the info is leaking */
 		}
 	}
 

Modified: trunk/camel/camel-folder.c
==============================================================================
--- trunk/camel/camel-folder.c	(original)
+++ trunk/camel/camel-folder.c	Wed Jul 16 11:38:32 2008
@@ -43,6 +43,7 @@
 #include "camel-session.h"
 #include "camel-store.h"
 #include "camel-vtrash-folder.h"
+#include "camel-string-utils.h"
 
 #define d(x)
 #define w(x)
@@ -201,7 +202,12 @@
 		camel_object_unref (camel_folder->summary);
 
 	camel_folder_change_info_free(p->changed_frozen);
-	
+
+	if (camel_folder->cdb) {
+		camel_db_close (camel_folder->cdb);
+		camel_folder->cdb = NULL;
+	}
+
 	g_static_rec_mutex_free(&p->lock);
 	g_static_mutex_free(&p->change_lock);
 	
@@ -240,6 +246,10 @@
 camel_folder_construct (CamelFolder *folder, CamelStore *parent_store,
 			const char *full_name, const char *name)
 {
+	char *store_db_path;
+	CamelService *service = (CamelService *) parent_store;
+	CamelException ex;
+	
 	g_return_if_fail (CAMEL_IS_FOLDER (folder));
 	g_return_if_fail (CAMEL_IS_STORE (parent_store));
 	g_return_if_fail (folder->parent_store == NULL);
@@ -251,6 +261,23 @@
 
 	folder->name = g_strdup (name);
 	folder->full_name = g_strdup (full_name);
+
+	store_db_path = g_build_filename (service->url->path, CAMEL_DB_FILE, NULL);
+	camel_exception_init(&ex);
+	if (strlen (store_db_path) < 2) {
+		g_free (store_db_path);
+		store_db_path = g_build_filename ( camel_session_get_storage_path ((CamelSession *)camel_service_get_session (service), service, &ex), CAMEL_DB_FILE, NULL);		
+	}
+
+
+	folder->cdb = camel_db_open (store_db_path, &ex);
+	g_free (store_db_path);
+	
+	if (camel_exception_is_set (&ex)) {
+		g_print ("Exiting without success for stire_db_path : [%s]: %s\n", store_db_path, camel_exception_get_description(&ex));
+		camel_exception_clear(&ex);
+		return;
+	}	
 }
 
 
@@ -305,7 +332,9 @@
 	g_return_if_fail (CAMEL_IS_FOLDER (folder));
 
 	CAMEL_FOLDER_REC_LOCK(folder, lock);
+
 	CF_CLASS (folder)->refresh_info (folder, ex);
+	
 	CAMEL_FOLDER_REC_UNLOCK(folder, lock);
 }
 
@@ -352,31 +381,58 @@
 		case CAMEL_FOLDER_ARG_JUNKED_NOT_DELETED:
 		case CAMEL_FOLDER_ARG_VISIBLE:
 			/* This is so we can get the values atomically, and also so we can calculate them only once */
+
+			#warning "Add a better base class function to get counts specific to normal/vee folder."
 			if (unread == -1) {
 				int j;
 				CamelMessageInfo *info;
 
-				/* TODO: Locking? */
-				unread = 0;
-				count = camel_folder_summary_count (folder->summary);
-				for (j = 0; j < count; j++) {
-					if ((info = camel_folder_summary_index (folder->summary, j))) {
-						guint32 flags = camel_message_info_flags(info);
-
-						if ((flags & (CAMEL_MESSAGE_SEEN|CAMEL_MESSAGE_DELETED|CAMEL_MESSAGE_JUNK)) == 0)
-							unread++;
-						if (flags & CAMEL_MESSAGE_DELETED)
-							deleted++;
-						if (flags & CAMEL_MESSAGE_JUNK) {
-							junked++;
-							if (! (flags & CAMEL_MESSAGE_DELETED))
-								junked_not_deleted++;
+				if (!CAMEL_IS_VEE_FOLDER (folder)) {
+					/* TODO: Locking? */
+					unread = folder->summary->unread_count;
+					deleted = folder->summary->deleted_count;
+					junked = folder->summary->junk_count;
+					junked_not_deleted = folder->summary->junk_not_deleted_count;
+					visible = folder->summary->visible_count;
+                                        #warning "unread should be unread and not del/junk and take care of dirty infos also"
+					// camel_folder_summary_save_to_db (folder->summary, NULL);
+					//camel_db_count_visible_unread_message_info (folder->cdb, folder->full_name, &unread, ex);
+					//camel_db_count_junk_message_info (folder->cdb, folder->full_name, &junked, ex);
+					//camel_db_count_deleted_message_info (folder->cdb, folder->full_name, &deleted, ex);
+					//camel_db_count_junk_not_deleted_message_info (folder->cdb, folder->full_name, &junked_not_deleted, ex);
+					//camel_db_count_visible_message_info (folder->cdb, folder->full_name, &visible, ex);
+				} else {
+					count = camel_folder_summary_count (folder->summary);
+					for (j = 0; j < count; j++) {
+						if ((info = camel_folder_summary_index (folder->summary, j))) {
+							guint32 flags = camel_message_info_flags(info);
+
+							if ((flags & (CAMEL_MESSAGE_SEEN|CAMEL_MESSAGE_DELETED|CAMEL_MESSAGE_JUNK)) == 0)
+								unread++;
+							if (flags & CAMEL_MESSAGE_DELETED)
+								deleted++;
+							if (flags & CAMEL_MESSAGE_JUNK) {
+								junked++;
+								if (! (flags & CAMEL_MESSAGE_DELETED))
+									junked_not_deleted++;
+							}
+							if ((flags & (CAMEL_MESSAGE_DELETED|CAMEL_MESSAGE_JUNK)) == 0)
+								visible++;
+							camel_message_info_free(info);
 						}
-						if ((flags & (CAMEL_MESSAGE_DELETED|CAMEL_MESSAGE_JUNK)) == 0)
-							visible++;
-						camel_message_info_free(info);
+
+					}
+                                        #warning "I added it for vfolders summary storage, does it harm ?"
+					if (unread == -1) {
+						unread = folder->summary->unread_count;
+						/*
+						folder->summary->junk_count = junked;
+						folder->summary->deleted_count = deleted;
+						printf("*************************** %s %d %d %d\n", folder->full_name, folder->summary->unread_count, unread, count);
+						folder->summary->unread_count = unread; */
 					}
 				}
+
 			}
 
 			switch (tag & CAMEL_ARG_TAG) {
@@ -400,7 +456,7 @@
 			*arg->ca_int = count;
 			break;
 		case CAMEL_FOLDER_ARG_UID_ARRAY: {
-			int j;
+/*			int j;
 			CamelMessageInfo *info;
 			GPtrArray *array;
 
@@ -413,7 +469,9 @@
 					camel_message_info_free(info);
 				}
 			}
-			*arg->ca_ptr = array;
+			*arg->ca_ptr = array;*/
+			// WTH this is reqd ?, let it crash to find out who uses this
+			g_assert (0);
 			break; }
 		case CAMEL_FOLDER_ARG_INFO_ARRAY:
 			*arg->ca_ptr = camel_folder_summary_array(folder->summary);
@@ -446,7 +504,7 @@
 		g_ptr_array_free(array, TRUE);
 		break; }
 	case CAMEL_FOLDER_ARG_INFO_ARRAY:
-		camel_folder_summary_array_free(folder->summary, val);
+		camel_folder_free_summary (folder, val);
 		break;
 	case CAMEL_FOLDER_ARG_PROPERTIES:
 		g_slist_free(val);
@@ -1114,7 +1172,7 @@
 		CamelMessageInfo *info = camel_folder_summary_index(folder->summary, i);
 		
 		if (info) {
-			array->pdata[j++] = g_strdup (camel_message_info_uid (info));
+			array->pdata[j++] = (char *)camel_pstring_strdup (camel_message_info_uid (info));
 			camel_message_info_free(info);
 		}
 	}
@@ -1155,7 +1213,7 @@
 	int i;
 
 	for (i=0; i<array->len; i++)
-		g_free(array->pdata[i]);
+		camel_pstring_free(array->pdata[i]);
 	g_ptr_array_free(array, TRUE);
 }
 
@@ -1249,9 +1307,8 @@
 static void
 free_summary(CamelFolder *folder, GPtrArray *summary)
 {
-	g_assert(folder->summary != NULL);
-
-	camel_folder_summary_array_free(folder->summary, summary);
+	g_ptr_array_foreach (summary, (GFunc) camel_pstring_free, NULL);
+	g_ptr_array_free (summary, TRUE);
 }
 
 
@@ -1265,8 +1322,6 @@
 void
 camel_folder_free_summary(CamelFolder *folder, GPtrArray *array)
 {
-	g_return_if_fail(CAMEL_IS_FOLDER(folder));
-
 	CF_CLASS(folder)->free_summary(folder, array);
 }
 
@@ -1376,7 +1431,7 @@
 	int i;
 
 	for (i = 0; i < result->len; i++)
-		g_free (g_ptr_array_index (result, i));
+		camel_pstring_free (g_ptr_array_index (result, i));
 	g_ptr_array_free (result, TRUE);
 }
 
@@ -1415,7 +1470,7 @@
 
 	/* if its deleted we poke the flags, so we need to copy the messageinfo */
 	if ((source->folder_flags & CAMEL_FOLDER_HAS_SUMMARY_CAPABILITY)
-	    && (minfo = camel_folder_get_message_info(source, uid))) {
+			&& (minfo = camel_folder_get_message_info(source, uid))) {
 		info = camel_message_info_clone(minfo);
 		camel_folder_free_message_info(source, minfo);
 	} else

Modified: trunk/camel/camel-folder.h
==============================================================================
--- trunk/camel/camel-folder.h	(original)
+++ trunk/camel/camel-folder.h	Wed Jul 16 11:38:32 2008
@@ -109,6 +109,7 @@
 
 	guint32 folder_flags;
 	guint32 permanent_flags;
+	CamelDB *cdb;
 };
 
 #define CAMEL_FOLDER_HAS_SUMMARY_CAPABILITY (1<<0)

Modified: trunk/camel/camel-offline-journal.c
==============================================================================
--- trunk/camel/camel-offline-journal.c	(original)
+++ trunk/camel/camel-offline-journal.c	Wed Jul 16 11:38:32 2008
@@ -45,7 +45,7 @@
 #include "camel-offline-journal.h"
 #include "camel-private.h"
 
-#define d(x) x
+#define d(x) 
 
 static void camel_offline_journal_class_init (CamelOfflineJournalClass *klass);
 static void camel_offline_journal_init (CamelOfflineJournal *journal, CamelOfflineJournalClass *klass);

Modified: trunk/camel/camel-store.c
==============================================================================
--- trunk/camel/camel-store.c	(original)
+++ trunk/camel/camel-store.c	Wed Jul 16 11:38:32 2008
@@ -42,7 +42,7 @@
 #include "camel-store.h"
 #include "camel-vtrash-folder.h"
 
-#define d(x)
+#define d(x) 
 #define w(x)
 
 static CamelServiceClass *parent_class = NULL;
@@ -153,11 +153,17 @@
 {
 	CamelStore *store = CAMEL_STORE (object);
 
+	d(printf ("\ncamel_store_finalize called \n"));
 	if (store->folders)
 		camel_object_bag_destroy(store->folders);
 	
 	g_static_rec_mutex_free (&store->priv->folder_lock);
-	
+
+	if (store->cdb) {
+		camel_db_close (store->cdb);
+		store->cdb = NULL;
+	}
+
 	g_free (store->priv);
 }
 
@@ -200,11 +206,35 @@
 	   CamelException *ex)
 {
 	CamelStore *store = CAMEL_STORE(service);
+	char *store_db_path;
 
 	parent_class->construct(service, session, provider, url, ex);
 	if (camel_exception_is_set (ex))
 		return;
 
+	store_db_path = g_build_filename (service->url->path, CAMEL_DB_FILE, NULL);
+
+	if (strlen (store_db_path) < 2) {
+		g_free (store_db_path);
+		store_db_path = g_build_filename ( camel_session_get_storage_path (session, service, ex), CAMEL_DB_FILE, NULL);		
+	}
+
+	store->cdb = camel_db_open (store_db_path, ex);
+	printf("store_db_path %s\n", store_db_path);
+	g_free (store_db_path);
+	if (camel_exception_is_set (ex)) {
+		g_print ("Exiting without success for stire_db_path : [%s]\n", store_db_path);
+		return;
+	}
+
+	if (camel_db_create_folders_table (store->cdb, ex))
+		printf ("something went wrong terribly\n");
+	else
+		printf ("folders table succesfully created \n");
+
+	if (camel_exception_is_set (ex))
+		return;
+
 	if (camel_url_get_param(url, "filter"))
 		store->flags |= CAMEL_STORE_FILTER_INBOX;
 }

Modified: trunk/camel/camel-store.h
==============================================================================
--- trunk/camel/camel-store.h	(original)
+++ trunk/camel/camel-store.h	Wed Jul 16 11:38:32 2008
@@ -32,6 +32,7 @@
 
 #include <camel/camel-object.h>
 #include <camel/camel-service.h>
+#include <camel/camel-db.h>
 
 G_BEGIN_DECLS
 
@@ -121,6 +122,7 @@
 	struct _CamelStorePrivate *priv;
 	
 	CamelObjectBag *folders;
+	CamelDB *cdb;
 
 	guint32 flags;
 	guint32 mode;

Modified: trunk/camel/camel-string-utils.c
==============================================================================
--- trunk/camel/camel-string-utils.c	(original)
+++ trunk/camel/camel-string-utils.c	Wed Jul 16 11:38:32 2008
@@ -240,11 +240,15 @@
 		if (count == 0) {
 			g_hash_table_remove(pstring_table, p);
 			g_free(p);
+			if (p != s) /* Only for debugging purposes */
+				g_assert(0);
 		} else {
 			g_hash_table_insert(pstring_table, p, GINT_TO_POINTER(count));
 		}
 	} else {
 		g_warning("Trying to free string not allocated from the pool '%s'", s);
+		/*Only for debugging purposes */
+		g_assert (0);
 	}
 	pthread_mutex_unlock(&pstring_lock);
 }

Modified: trunk/camel/camel-vee-folder.c
==============================================================================
--- trunk/camel/camel-vee-folder.c	(original)
+++ trunk/camel/camel-vee-folder.c	Wed Jul 16 11:38:32 2008
@@ -43,6 +43,7 @@
 #include "camel-vee-folder.h"
 #include "camel-vee-store.h"	/* for open flags */
 #include "camel-vee-summary.h"
+#include "camel-string-utils.h"
 
 #define d(x) 
 #define dd(x) (camel_debug("vfolder")?(x):0)
@@ -421,7 +422,7 @@
 {
 	CamelFolder *folder;
 
-	folder = vinfo->real->summary->folder;
+	folder = vinfo->summary->folder;
 
 	/* locking?  yes?  no?  although the vfolderinfo is valid when obtained
 	   the folder in it might not necessarily be so ...? */
@@ -465,13 +466,40 @@
 	g_list_free(list);
 }
 
+static	CamelFIRecord *
+summary_header_to_db (CamelFolderSummary *s, CamelException *ex)
+{
+	CamelFIRecord * record = g_new0 (CamelFIRecord, 1);
+	CamelDB *db;
+
+	db = s->folder->parent_store->cdb;
+	char *table_name = s->folder->full_name;
+
+
+	record->folder_name = table_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->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;
+
+	return record;	
+}
+
 static void
 vee_sync(CamelFolder *folder, gboolean expunge, CamelException *ex)
 {
 	CamelVeeFolder *vf = (CamelVeeFolder *)folder;
 	struct _CamelVeeFolderPrivate *p = _PRIVATE(vf);
 	GList *node;
-
+	CamelFIRecord * record;
+	
 	CAMEL_VEE_FOLDER_LOCK(vf, subfolder_lock);
 
 	node = p->folders;
@@ -486,15 +514,20 @@
 			camel_exception_setv(ex, ex->id, _("Error storing '%s': %s"), desc, ex->desc);
 			break;
 		}
-
+#warning "see if it is really required"
 		/* auto update vfolders shouldn't need a rebuild */
-		if ((vf->flags & CAMEL_STORE_VEE_FOLDER_AUTO) == 0
-		    && camel_vee_folder_rebuild_folder(vf, f, ex) == -1)
-			break;
+/* 		if ((vf->flags & CAMEL_STORE_VEE_FOLDER_AUTO) == 0 */
+/* 		    && camel_vee_folder_rebuild_folder(vf, f, ex) == -1) */
+/* 			break; */
 
 		node = node->next;
 	}
-
+	
+	record = summary_header_to_db (folder->summary, ex);
+	#warning handle exception and ret
+	camel_db_write_folder_info_record (folder->parent_store->cdb, record, ex);
+	g_free (record);
+	
 	if (node == NULL) {
 		CAMEL_VEE_FOLDER_LOCK(vf, changed_lock);
 		g_list_free(p->folders_changed);
@@ -521,7 +554,7 @@
 
 	mi = (CamelVeeMessageInfo *)camel_folder_summary_uid(folder->summary, uid);
 	if (mi) {
-		msg =  camel_folder_get_message(mi->real->summary->folder, camel_message_info_uid(mi)+8, ex);
+		msg =  camel_folder_get_message(mi->summary->folder, camel_message_info_uid(mi)+8, ex);
 		camel_message_info_free((CamelMessageInfo *)mi);
 	} else {
 		camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID,
@@ -543,8 +576,6 @@
 	GHashTable *searched = g_hash_table_new(NULL, NULL);
 	CamelVeeFolder *folder_unmatched = vf->parent_vee_store ? vf->parent_vee_store->folder_unmatched : NULL;
 	
-	CAMEL_VEE_FOLDER_LOCK(vf, subfolder_lock);
-	
 	if (vf != folder_unmatched)
 		expr = g_strdup_printf ("(and %s %s)", vf->expression ? vf->expression : "", expression);
 	else
@@ -560,7 +591,7 @@
 		if (g_hash_table_lookup(searched, f) == NULL) {
 			camel_vee_folder_hash_folder(f, hash);
 			/* FIXME: shouldn't ignore search exception */
-			matches = camel_folder_search_by_expression(f, expression, NULL);
+			matches = camel_folder_search_by_expression(f, expr, NULL);
 			if (matches) {
 				for (i = 0; i < matches->len; i++) {
 					char *uid = matches->pdata[i], *vuid;
@@ -568,7 +599,8 @@
 					vuid = g_malloc(strlen(uid)+9);
 					memcpy(vuid, hash, 8);
 					strcpy(vuid+8, uid);
-					g_ptr_array_add(result, vuid);
+					g_ptr_array_add(result, (gpointer) camel_pstring_strdup(vuid));
+					g_free (vuid);
 				}
 				camel_folder_search_free(f, matches);
 			}
@@ -577,11 +609,69 @@
 		node = g_list_next(node);
 	}
 
+	
 	g_free(expr);
-	CAMEL_VEE_FOLDER_UNLOCK(vf, subfolder_lock);
 
-	g_hash_table_destroy(searched);
+	if (0)
+	{
+		GHashTable *hashes = g_hash_table_new (g_str_hash, g_str_equal);
+		GPtrArray *subids = g_ptr_array_new ();
+		GPtrArray *summary = camel_folder_summary_array (folder->summary);
+		char *last_id = NULL;
+		printf("Doing for folder %s\n", folder->full_name);
+		CAMEL_VEE_FOLDER_LOCK(vf, subfolder_lock);		
+		node = p->folders;
+		while (node) {
+			CamelFolder *f = node->data;
+			char hash[9];
+
+			camel_vee_folder_hash_folder(f, hash);
+			hash[8] = 0;
+			g_hash_table_insert(hashes, hash, f);
+			node = g_list_next(node);
+		}
+		CAMEL_VEE_FOLDER_UNLOCK(vf, subfolder_lock);
+		if (summary->len) {
+			int i, j;
+			
+			last_id = summary->pdata[0];
+			g_ptr_array_add (subids, last_id+8);
+			for (i=1; i<=summary->len; i++) {
+				if (i==summary->len || strncmp(last_id, summary->pdata[i], 8)) {
+					/* We got a new id */
+					char shash[9];
+					strncpy (shash, last_id, 8);
+					shash[8] = 0;
+					CamelFolder *cf = g_hash_table_lookup (hashes, shash);
+					d(printf("Searching %s for %d uids (%d<%d )...\t", cf->full_name, subids->len, i, summary->len));
+					matches = camel_folder_search_by_uids (cf, expression, subids, NULL);
+					d(printf("Got %d\n", matches->len));
+					if (matches) {
+						for (j = 0; j < matches->len; j++) {
+							char *uid = matches->pdata[j], *vuid;
+
+							vuid = g_malloc(strlen(uid)+9);
+							memcpy(vuid, shash, 8);
+							strcpy(vuid+8, uid);
+							g_ptr_array_add(result, vuid);
+						}
+						camel_folder_search_free(cf, matches);
+					}					
+					g_ptr_array_set_size(subids, 0);
+				}
+				if (i <summary->len) {
+					last_id = summary->pdata[i];
+					g_ptr_array_add (subids, last_id+8);
+				}
+			}
+			
+		}
+		camel_folder_free_summary (folder, summary);		
+	}
 
+
+	g_hash_table_destroy(searched);
+	printf("returning %d\n", result->len);
 	return result;
 }
 
@@ -695,14 +785,9 @@
 static CamelVeeMessageInfo *
 vee_folder_add_uid(CamelVeeFolder *vf, CamelFolder *f, const char *inuid, const char hash[8])
 {
-	CamelMessageInfo *info;
 	CamelVeeMessageInfo *mi = NULL;
 
-	info = camel_folder_get_message_info(f, inuid);
-	if (info) {
-		mi = camel_vee_summary_add((CamelVeeSummary *)((CamelFolder *)vf)->summary, info, hash);
-		camel_folder_free_message_info(f, info);
-	}
+	mi = camel_vee_summary_add((CamelVeeSummary *)((CamelFolder *)vf)->summary, f->summary, (char *)inuid, hash);
 	return mi;
 }
 
@@ -749,7 +834,7 @@
 				CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *)camel_folder_summary_index(((CamelFolder *)folder_unmatched)->summary, i);
 				
 				if (mi) {
-					if (mi->real->summary == ssummary) {
+					if (mi->summary == ssummary) {
 						camel_folder_change_info_remove_uid(folder_unmatched->changes, camel_message_info_uid(mi));
 						if (last == -1) {
 							last = start = i;
@@ -775,7 +860,7 @@
 	for (i=0;i<count;i++) {
 		CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *)camel_folder_summary_index(folder->summary, i);
 		if (mi) {
-			if (mi->real->summary == ssummary) {
+			if (mi->summary == ssummary) {
 				const char *uid = camel_message_info_uid(mi);
 
 				camel_folder_change_info_remove_uid(vf->changes, uid);
@@ -794,9 +879,12 @@
 						if (g_hash_table_lookup_extended(unmatched_uids, uid, (void **)&oldkey, &oldval)) {
 							n = GPOINTER_TO_INT (oldval);
 							if (n == 1) {
+								CamelMessageInfo *tinfo;
 								g_hash_table_remove(unmatched_uids, oldkey);
-								if (vee_folder_add_uid(folder_unmatched, source, oldkey+8, hash))
+								if (tinfo = (CamelMessageInfo *) vee_folder_add_uid(folder_unmatched, source, oldkey+8, hash)) {
+									camel_message_info_free (tinfo);
 									camel_folder_change_info_add_uid(folder_unmatched->changes, oldkey);
+								}
 								g_free(oldkey);
 							} else {
 								g_hash_table_insert(unmatched_uids, oldkey, GINT_TO_POINTER(n-1));
@@ -850,6 +938,7 @@
 	char hash[8];
 	CamelVeeFolder *folder_unmatched;
 	GHashTable *unmatched_uids;
+	gboolean rebuilt;
 };
 
 static void
@@ -885,7 +974,10 @@
 
 	if ( (mi = vee_folder_add_uid(u->vf, u->source, uidin, u->hash)) ) {
 		camel_folder_change_info_add_uid(u->vf->changes, camel_message_info_uid(mi));
-
+		#warning "Handle exceptions"
+		#warning "Make all these as transactions, just testing atm"
+		if (u->rebuilt)
+			camel_db_add_to_vfolder_transaction (((CamelFolder *) u->vf)->parent_store->cdb, ((CamelFolder *) u->vf)->full_name, (char *) camel_message_info_uid(mi), NULL);
 		if (!CAMEL_IS_VEE_FOLDER(u->source) && u->unmatched_uids != NULL) {
 			if (g_hash_table_lookup_extended(u->unmatched_uids, camel_message_info_uid(mi), (void **)&oldkey, &oldval)) {
 				n = GPOINTER_TO_INT (oldval);
@@ -911,24 +1003,35 @@
 	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 = source->summary;
-
+	gboolean rebuilded = FALSE;
+	
 	if (vf == folder_unmatched)
 		return 0;
 
+	#warning "Reframe these lines later on"
+	camel_vee_folder_hash_folder(source, u.hash);
+	
 	/* if we have no expression, or its been cleared, then act as if no matches */
 	if (vf->expression == NULL) {
 		match = g_ptr_array_new();
 	} else {
-		match = camel_folder_search_by_expression(f, vf->expression, ex);
-		if (match == NULL)
-			return -1;
+		/* Load the folder results from the DB. */
+		match = camel_vee_summary_get_ids ((CamelVeeSummary *)folder->summary, u.hash);
+		
+		if (!match) {
+			match = camel_folder_search_by_expression(f, vf->expression, ex);
+			if (match == NULL)
+				return -1;
+			rebuilded = TRUE;
+		}
+		printf("len = %d %d\n", match->len, rebuilded);
 	}
 
 	u.source = source;
 	u.vf = vf;
 	u.folder_unmatched = folder_unmatched;
 	u.unmatched_uids = unmatched_uids;
-	camel_vee_folder_hash_folder(source, u.hash);
+	u.rebuilt = rebuilded;
 
 	CAMEL_VEE_FOLDER_LOCK(vf, summary_lock);
 
@@ -955,7 +1058,7 @@
 		CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *)camel_folder_summary_index(folder->summary, i);
 
 		if (mi) {
-			if (mi->real->summary == ssummary) {
+			if (mi->summary == ssummary) {
 				char *uid = (char *)camel_message_info_uid(mi), *oldkey;
 				void *oldval;
 				
@@ -992,28 +1095,33 @@
 		camel_folder_summary_remove_range(folder->summary, start, last);
 
 	/* now matchhash contains any new uid's, add them, etc */
+	if (rebuilded) {
+		camel_db_begin_transaction (folder->parent_store->cdb, NULL);
+
+	}
 	g_hash_table_foreach(matchhash, (GHFunc)folder_added_uid, &u);
 
+	if (rebuilded)
+		camel_db_end_transaction (folder->parent_store->cdb, NULL);
+	
 	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++) {
-			CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *)camel_folder_summary_index(((CamelFolder *)folder_unmatched)->summary, i);
-
-			if (mi) {
-				if (mi->real->summary == ssummary) {
-					char *uid = (char *)camel_message_info_uid(mi);
+			char *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) {
 						/* no longer exists at all, just remove it entirely */
-						camel_folder_summary_remove_index(((CamelFolder *)folder_unmatched)->summary, i);
-						camel_folder_change_info_remove_uid(folder_unmatched->changes, camel_message_info_uid(mi));
+						camel_folder_summary_remove_index_fast(((CamelFolder *)folder_unmatched)->summary, i);
+						camel_folder_change_info_remove_uid(folder_unmatched->changes, uid);
 						i--;
 					} else {
 						g_hash_table_remove(allhash, uid+8);
 					}
 				}
-				camel_message_info_free((CamelMessageInfo *)mi);
+				g_free (uid);
 			}
 		}
 
@@ -1040,9 +1148,10 @@
 	g_hash_table_destroy(matchhash);
 	g_hash_table_destroy(allhash);
 	/* if expression not set, we only had a null list */
-	if (vf->expression == NULL)
+	if (vf->expression == NULL || !rebuilded) {
+		g_ptr_array_foreach (match, (GFunc) camel_pstring_free, NULL);
 		g_ptr_array_free(match, TRUE);
-	else
+	} else
 		camel_folder_search_free(f, match);
 	camel_folder_free_uids(f, all);
 
@@ -1119,6 +1228,8 @@
 	vinfo = (CamelVeeMessageInfo *)camel_folder_summary_uid(folder->summary, vuid);
 	if (vinfo) {
 		camel_folder_change_info_remove_uid(vf->changes, vuid);
+                #warning "Handle exception"
+		camel_db_delete_uid_from_vfolder (folder->parent_store->cdb, folder->full_name, vuid, NULL);
 		camel_folder_summary_remove(folder->summary, (CamelMessageInfo *)vinfo);
 		camel_message_info_free((CamelMessageInfo *)vinfo);
 	}
@@ -1499,7 +1610,7 @@
 		if (mi == NULL)
 			continue;
 
-		if (mi->real->summary == ssummary) {
+		if (mi->summary == ssummary) {
 			char *uid = (char *)camel_message_info_uid(mi);
 			char *oldkey;
 			void *oldval;
@@ -1641,7 +1752,7 @@
 	g_free(vf->expression);
 	if (query)
 		vf->expression = g_strdup(query);
-
+	#warning "reset the DB, err drop the table, . as the expression changed"
 	node = p->folders;
 	while (node) {
 		CamelFolder *f = node->data;
@@ -1735,10 +1846,13 @@
 		for (node = p->folders;node;node = g_list_next(node))
 			camel_object_unref(node->data);
 	} else {
+		#warning "See if it is really reqd"
+		camel_folder_freeze ((CamelFolder *)vf);
 		while (p->folders) {
 			CamelFolder *f = p->folders->data;
 			camel_vee_folder_remove_folder(vf, f);
 		}
+		camel_folder_thaw ((CamelFolder *)vf);
 	}
 
 	g_free(vf->expression);

Modified: trunk/camel/camel-vee-store.c
==============================================================================
--- trunk/camel/camel-vee-store.c	(original)
+++ trunk/camel/camel-vee-store.c	Wed Jul 16 11:38:32 2008
@@ -48,6 +48,7 @@
 static void camel_vee_store_class_init (CamelVeeStoreClass *klass);
 static void camel_vee_store_init       (CamelVeeStore *obj);
 static void camel_vee_store_finalise   (CamelObject *obj);
+static void construct (CamelService *service, CamelSession *session, CamelProvider *provider, CamelURL *url, CamelException *ex);
 
 static CamelStoreClass *camel_vee_store_parent;
 
@@ -82,7 +83,8 @@
 	store_class->delete_folder = vee_delete_folder;
 	store_class->get_folder_info = vee_get_folder_info;
 	store_class->free_folder_info = camel_store_free_folder_info_full;
-
+	((CamelServiceClass *)store_class)->construct = construct;
+	
 	store_class->sync = vee_sync;
 	store_class->get_trash = vee_get_trash;
 	store_class->get_junk = vee_get_junk;
@@ -95,13 +97,25 @@
 
 	/* we dont want a vtrash/vjunk on this one */
 	store->flags &= ~(CAMEL_STORE_VTRASH | CAMEL_STORE_VJUNK);	
+}
 
+static void
+construct (CamelService *service, CamelSession *session, CamelProvider *provider, CamelURL *url, CamelException *ex)
+{
+	/*  CamelStore *store = (CamelStore *)service;
+	 CamelVeeStore *obj = (CamelVeeStore *)service; */
+	 
+	 ((CamelServiceClass *) camel_vee_store_parent)->construct(service, session, provider, url, ex);
+	 
 	/* Set up unmatched folder */
+#ifdef VEE_UNMATCHED_ENABLE
 	obj->unmatched_uids = g_hash_table_new (g_str_hash, g_str_equal);
 	obj->folder_unmatched = (CamelVeeFolder *)camel_object_new (camel_vee_folder_get_type ());
 	camel_vee_folder_construct (obj->folder_unmatched, store, CAMEL_UNMATCHED_NAME, _("Unmatched"), CAMEL_STORE_FOLDER_PRIVATE);
+	camel_db_create_vfolder (store->cdb, _("Unmatched"), NULL);
+#endif
+	 
 }
-
 static void
 cvs_free_unmatched(void *key, void *value, void *data)
 {
@@ -333,7 +347,8 @@
 	g_hash_table_destroy(infos_hash);
 
 	/* and always add UNMATCHED, if scanning from top/etc */
-	if (top == NULL || top[0] == 0 || strncmp(top, CAMEL_UNMATCHED_NAME, strlen(CAMEL_UNMATCHED_NAME)) == 0) {
+	#warning "comment it out well"
+	if (0 && (top == NULL || top[0] == 0 || strncmp(top, CAMEL_UNMATCHED_NAME, strlen(CAMEL_UNMATCHED_NAME)) == 0)) {
 		info = camel_folder_info_new ();
 		url = camel_url_new("vfolder:", NULL);
 		camel_url_set_path(url, ((CamelService *)store)->url->path);

Modified: trunk/camel/camel-vee-summary.c
==============================================================================
--- trunk/camel/camel-vee-summary.c	(original)
+++ trunk/camel/camel-vee-summary.c	Wed Jul 16 11:38:32 2008
@@ -30,7 +30,10 @@
 #include <sys/stat.h>
 
 #include "camel-folder.h"
+#include "camel-store.h"
 #include "camel-vee-summary.h"
+#include "camel-private.h"
+#include "camel-string-utils.h"
 
 #define d(x)
 
@@ -40,15 +43,9 @@
 vee_message_info_free(CamelFolderSummary *s, CamelMessageInfo *info)
 {
 	CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *)info;
-	CamelFolderSummary *real_summary = mi->real->summary;
 
 	g_free(info->uid);
-	camel_message_info_free(mi->real);
-
-	/* and unref the real summary too */
-	/* FIXME: You may not need this during CamelDBSummary */
-	if (real_summary)
-		camel_object_unref (real_summary);
+	camel_object_unref (mi->summary);
 }
 
 static CamelMessageInfo *
@@ -59,42 +56,68 @@
 
 	to = (CamelVeeMessageInfo *)camel_message_info_new(s);
 
-	to->real = camel_message_info_clone(from->real);
+	to->summary = from->summary;
 	/* FIXME: We may not need this during CamelDBSummary */
-	camel_object_ref (to->real->summary);
+	camel_object_ref (to->summary);
 	to->info.summary = s;
 	
 	return (CamelMessageInfo *)to;
 }
 
 static const void *
-vee_info_ptr(const CamelMessageInfo *mi, int id)
+vee_info_ptr (const CamelMessageInfo *mi, int id)
 {
-	return camel_message_info_ptr(((CamelVeeMessageInfo *)mi)->real, id);
+	CamelVeeMessageInfo *vmi = (CamelVeeMessageInfo *) mi;
+	CamelMessageInfo *info;
+	gpointer p;
+	
+	info = camel_folder_summary_uid (vmi->summary, mi->uid+8);
+	p = (gpointer) camel_message_info_ptr(info, id);
+	camel_message_info_free (info);
+
+	return p;
 }
 
 static guint32
 vee_info_uint32(const CamelMessageInfo *mi, int id)
 {
-	return camel_message_info_uint32(((CamelVeeMessageInfo *)mi)->real, id);
+	CamelMessageInfo *rmi = camel_folder_summary_uid (((CamelVeeMessageInfo *)mi)->summary, mi->uid+8);
+	guint32 ret = camel_message_info_uint32 (rmi, id);
+
+	camel_message_info_free (rmi);
+
+	return ret;
+
 }
 
 static time_t
 vee_info_time(const CamelMessageInfo *mi, int id)
 {
-	return camel_message_info_time(((CamelVeeMessageInfo *)mi)->real, id);
+	CamelMessageInfo *rmi = camel_folder_summary_uid (((CamelVeeMessageInfo *)mi)->summary, mi->uid+8);
+	time_t ret = camel_message_info_time (rmi, id);
+	camel_message_info_free (rmi);
+
+	return ret;
 }
 
 static gboolean
 vee_info_user_flag(const CamelMessageInfo *mi, const char *id)
 {
-	return camel_message_info_user_flag(((CamelVeeMessageInfo *)mi)->real, id);
+	CamelMessageInfo *rmi = camel_folder_summary_uid (((CamelVeeMessageInfo *)mi)->summary, mi->uid+8);
+	gboolean ret = 	camel_message_info_user_flag (rmi, id);
+	camel_message_info_free (rmi);
+
+	return ret;
 }
 
 static const char *
 vee_info_user_tag(const CamelMessageInfo *mi, const char *id)
 {
-	return camel_message_info_user_tag(((CamelVeeMessageInfo *)mi)->real, id);
+	CamelMessageInfo *rmi = camel_folder_summary_uid (((CamelVeeMessageInfo *)mi)->summary, mi->uid+8);
+	const char *ret = camel_message_info_user_tag (rmi, id);
+	camel_message_info_free (rmi);
+
+	return ret;
 }
 
 static gboolean
@@ -102,9 +125,12 @@
 {
 	int res = FALSE;
 
-	if (mi->uid)
-		res = camel_message_info_set_user_flag(((CamelVeeMessageInfo *)mi)->real, name, value);
-
+	if (mi->uid) {
+		CamelMessageInfo *rmi = camel_folder_summary_uid (((CamelVeeMessageInfo *)mi)->summary, mi->uid+8);
+		res = camel_message_info_set_user_flag(rmi, name, value);
+		camel_message_info_free (rmi);		
+	}
+ 
 	return res;
 }
 
@@ -113,9 +139,12 @@
 {
 	int res = FALSE;
 
-	if (mi->uid)
-		res = camel_message_info_set_user_tag(((CamelVeeMessageInfo *)mi)->real, name, value);
-
+	if (mi->uid) {
+		CamelMessageInfo *rmi = camel_folder_summary_uid (((CamelVeeMessageInfo *)mi)->summary, mi->uid+8);
+		res = camel_message_info_set_user_tag(rmi, name, value);
+		camel_message_info_free (rmi);			
+	}
+ 
 	return res;
 }
 
@@ -124,12 +153,35 @@
 {
 	int res = FALSE;
 
-	if (mi->uid)
-		res = camel_message_info_set_flags(((CamelVeeMessageInfo *)mi)->real, flags, set);
-
+	if (mi->uid) {
+		CamelMessageInfo *rmi = camel_folder_summary_uid (((CamelVeeMessageInfo *)mi)->summary, mi->uid+8);		
+		res = camel_message_info_set_flags(rmi, flags, set);
+		camel_message_info_free (rmi);
+	}
+ 
 	return res;
 }
 
+static CamelMessageInfo *
+message_info_from_uid (CamelFolderSummary *s, const char *uid)
+{
+	CamelMessageInfoBase *info;
+
+	#warning "too bad design. Need to peek it from cfs instead of hacking ugly like this"
+	CAMEL_SUMMARY_LOCK(s, summary_lock);
+	CAMEL_SUMMARY_LOCK(s, ref_lock);
+
+	info = g_hash_table_lookup (s->loaded_infos, uid);
+
+	if (info)
+		info->refcount++;
+
+	CAMEL_SUMMARY_UNLOCK(s, ref_lock);
+	CAMEL_SUMMARY_UNLOCK(s, summary_lock);
+
+	return (CamelMessageInfo *) info;	
+}
+
 static void
 camel_vee_summary_class_init (CamelVeeSummaryClass *klass)
 {
@@ -152,6 +204,7 @@
 	((CamelFolderSummaryClass *)klass)->info_set_user_tag = vee_info_set_user_tag;
 
 	((CamelFolderSummaryClass *)klass)->info_set_flags = vee_info_set_flags;
+	((CamelFolderSummaryClass *)klass)->message_info_from_uid = message_info_from_uid;
 }
 
 static void
@@ -201,41 +254,63 @@
 	s = (CamelVeeSummary *)camel_object_new(camel_vee_summary_get_type());
 	s->summary.folder = parent;
 
+        #warning "fix exceptions and note return values"
+	#warning "if Evo's junk/trash vfolders make it VJunk VTrash instead of .#evolution/Junk-or-whatever"		
+	camel_db_create_vfolder (parent->cdb, parent->full_name, NULL);
+
+	#warning "handle excep and ret"
+	camel_folder_summary_header_load_from_db ((CamelFolderSummary *)s, parent->parent_store, parent->full_name, NULL);	
 	return &s->summary;
 }
 
+GPtrArray *
+camel_vee_summary_get_ids (CamelVeeSummary *summary, char hash[8])
+{
+	char *shash = g_strdup_printf("%c%c%c%c%c%c%c%c", hash[0], hash[1], hash[2], hash[3], hash[4], hash[5], hash[6], hash[7]);
+	CamelFolderSummary *cfs = (CamelFolderSummary *)summary;
+	GPtrArray *array;
+
+	#warning "fix exception passing"
+	array = camel_db_get_vuids_from_vfolder(cfs->folder->cdb, cfs->folder->full_name, shash, NULL);
+	
+	g_free(shash);
+
+	return array;
+}
+
 CamelVeeMessageInfo *
-camel_vee_summary_add(CamelVeeSummary *s, CamelMessageInfo *info, const char hash[8])
+camel_vee_summary_add(CamelVeeSummary *s, CamelFolderSummary *summary, const char *uid, const char hash[8])
 {
 	CamelVeeMessageInfo *mi;
 	char *vuid;
-	const char *uid;
 
-	uid = camel_message_info_uid(info);
 	vuid = g_malloc(strlen(uid)+9);
 	memcpy(vuid, hash, 8);
 	strcpy(vuid+8, uid);
-	mi = (CamelVeeMessageInfo *)camel_folder_summary_uid(&s->summary, vuid);
+	
+	#warning do we need it really ?
+/* 	mi = (CamelVeeMessageInfo *)camel_folder_summary_uid(&s->summary, vuid); */
+/* 	if (mi) { */
+/* 		d(printf("w:clash, we already have '%s' in summary\n", vuid)); */
+/* 		camel_message_info_free((CamelMessageInfo *)mi); */
+/* 		g_free(vuid); */
+/* 		return NULL; */
+/* 	} */
+
+	mi = (CamelVeeMessageInfo *) message_info_from_uid(&s->summary, vuid); 
 	if (mi) {
-		d(printf("w:clash, we already have '%s' in summary\n", vuid));
-		camel_message_info_free((CamelMessageInfo *)mi);
-		g_free(vuid);
-		return NULL;
+		g_warning ("%s - already there\n", vuid);
+		g_free (vuid);
+		return mi;
 	}
 
 	mi = (CamelVeeMessageInfo *)camel_message_info_new(&s->summary);
-	mi->real = info;
-	camel_message_info_ref(info);
-
-	/* Ensures the owner of the message info will not die before we free the mi->real;
-	   It's obvious that the real->summary should not be changed after this call. */
-	/* FIXME: We may not need this during CamelDBSummary */
-	if (info->summary)
-		camel_object_ref (info->summary);
-
-	mi->info.uid = vuid;
-
-	camel_folder_summary_add(&s->summary, (CamelMessageInfo *)mi);
-
+	mi->summary = summary;
+	camel_object_ref (summary);
+	mi->info.uid = (char *) camel_pstring_strdup (vuid);
+	g_free (vuid);
+	camel_message_info_ref (mi);
+	camel_folder_summary_insert(&s->summary, (CamelMessageInfo *)mi, FALSE);
+	
 	return mi;
 }

Modified: trunk/camel/camel-vee-summary.h
==============================================================================
--- trunk/camel/camel-vee-summary.h	(original)
+++ trunk/camel/camel-vee-summary.h	Wed Jul 16 11:38:32 2008
@@ -42,8 +42,7 @@
 
 struct _CamelVeeMessageInfo {
 	CamelMessageInfo info;
-
-	CamelMessageInfo *real;
+	CamelFolderSummary *summary;
 };
 
 struct _CamelVeeSummary {
@@ -58,7 +57,8 @@
 CamelType               camel_vee_summary_get_type     (void);
 CamelFolderSummary *camel_vee_summary_new(struct _CamelFolder *parent);
 
-CamelVeeMessageInfo * camel_vee_summary_add(CamelVeeSummary *s, CamelMessageInfo *info, const char hash[8]);
+CamelVeeMessageInfo * camel_vee_summary_add(CamelVeeSummary *s, CamelFolderSummary *summary, const char *uid, const char hash[8]);
+GPtrArray * camel_vee_summary_get_ids (CamelVeeSummary *summary, char hash[8]);
 
 G_END_DECLS
 

Modified: trunk/camel/camel-vtrash-folder.c
==============================================================================
--- trunk/camel/camel-vtrash-folder.c	(original)
+++ trunk/camel/camel-vtrash-folder.c	Wed Jul 16 11:38:32 2008
@@ -36,7 +36,7 @@
 #include "camel-store.h"
 #include "camel-vee-store.h"
 #include "camel-vtrash-folder.h"
-
+#include "camel-string-utils.h"
 
 /* Returns the class for a CamelFolder */
 #define CF_CLASS(so) ((CamelFolderClass *)((CamelObject *)(so))->klass)
@@ -48,11 +48,12 @@
 	guint32 bit;
 	guint32 flags;
 	const char *error_copy;
+	const char *db_col;
 } vdata[] = {
 	{ CAMEL_VTRASH_NAME, N_("Trash"), "(match-all (system-flag \"Deleted\"))", CAMEL_MESSAGE_DELETED, CAMEL_FOLDER_IS_TRASH,
-	  N_("Cannot copy messages to the Trash folder") },
+	  N_("Cannot copy messages to the Trash folder"), "deleted" },
 	{ CAMEL_VJUNK_NAME, N_("Junk"), "(match-all (system-flag \"Junk\"))", CAMEL_MESSAGE_JUNK, CAMEL_FOLDER_IS_JUNK,
-	  N_("Cannot copy messages to the Junk folder") },
+	  N_("Cannot copy messages to the Junk folder"), "junk" },
 };
 
 static CamelVeeFolderClass *camel_vtrash_folder_parent;
@@ -262,20 +263,20 @@
 			continue;
 		}
 		
-		if (dest == mi->real->summary->folder) {
+		if (dest == mi->summary->folder) {
 			/* 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->real->summary->folder);
+			md = g_hash_table_lookup(batch, mi->summary->folder);
 			if (md == NULL) {
 				md = g_malloc0(sizeof(*md));
-				md->folder = mi->real->summary->folder;
+				md->folder = mi->summary->folder;
 				camel_object_ref((CamelObject *)md->folder);
 				md->uids = g_ptr_array_new();
 				md->dest = dest;
-				g_hash_table_insert(batch, mi->real->summary->folder, md);
+				g_hash_table_insert(batch, mi->summary->folder, md);
 			}
 
 			tuid = uids->pdata[i];
@@ -292,12 +293,14 @@
 	}
 }
 
+#warning rewrite the same way as camel-vee-summary.c
 static GPtrArray *
 vtrash_search_by_expression(CamelFolder *folder, const char *expression, CamelException *ex)
 {
 	GList *node;
 	GPtrArray *matches, *result = g_ptr_array_new(), *uids = g_ptr_array_new();
 	struct _CamelVeeFolderPrivate *p = ((CamelVeeFolder *)folder)->priv;
+	GPtrArray *infos = camel_folder_get_summary(folder);
 
 	/* we optimise the search by only searching for messages which we have anyway */
 	CAMEL_VEE_FOLDER_LOCK(folder, subfolder_lock);
@@ -306,17 +309,20 @@
 		CamelFolder *f = node->data;
 		int i;
 		char hash[8];
-		GPtrArray *infos = camel_folder_get_summary(f);
 
 		camel_vee_folder_hash_folder(f, hash);
 
 		for (i=0;i<infos->len;i++) {
-			CamelMessageInfo *mi = infos->pdata[i];
-
-			if (camel_message_info_flags(mi) & ((CamelVTrashFolder *)folder)->bit)
-				g_ptr_array_add(uids, (void *)camel_message_info_uid(mi));
+			CamelVeeMessageInfo  *vmi = (CamelVeeMessageInfo *) camel_folder_summary_uid (folder->summary, infos->pdata[i]);
+			if (!vmi)
+				continue;
+			//if (camel_message_info_flags(mi) & ((CamelVTrashFolder *)folder)->bit)
+			if (vmi->summary == f->summary) /* Belongs to this folder */
+				g_ptr_array_add(uids, (void *)camel_pstring_strdup(infos->pdata[i]+8));
+			camel_message_info_free (vmi);
 		}
 
+                #warning search in the DB of the folder, for the expression, with the vtrash bit (junk/trash)
 		if (uids->len > 0
 		    && (matches = camel_folder_search_by_uids(f, expression, uids, NULL))) {
 			for (i = 0; i < matches->len; i++) {
@@ -325,17 +331,19 @@
 				vuid = g_malloc(strlen(uid)+9);
 				memcpy(vuid, hash, 8);
 				strcpy(vuid+8, uid);
-				g_ptr_array_add(result, vuid);
+				g_ptr_array_add(result, camel_pstring_strdup(vuid));
+				g_free (vuid);
 			}
 			camel_folder_search_free(f, matches);
 		}
 		g_ptr_array_set_size(uids, 0);
-		camel_folder_free_summary(f, infos);
 
 		node = g_list_next(node);
 	}
+	camel_folder_free_summary (folder, infos);
 	CAMEL_VEE_FOLDER_UNLOCK(folder, subfolder_lock);
 
+	g_ptr_array_foreach (uids, camel_pstring_free, NULL);
 	g_ptr_array_free(uids, TRUE);
 
 	return result;
@@ -359,19 +367,22 @@
 		camel_vee_folder_hash_folder(f, hash);
 
 		/* map the vfolder uid's to the source folder uid's first */
-		g_ptr_array_set_size(uids, 0);
+		#warning "check this. is it uids od folder_uids"
+		//g_ptr_array_set_size(uids, 0);
+		g_ptr_array_set_size (folder_uids, 0);
 		for (i=0;i<uids->len;i++) {
 			char *uid = uids->pdata[i];
 			
-			if (strlen(uid) >= 8 && strncmp(uid, hash, 8) == 0) {
-				CamelMessageInfo *mi;
-
-				mi = camel_folder_get_message_info(f, uid+8);
-				if (mi) {
-					if(camel_message_info_flags(mi) & ((CamelVTrashFolder *)folder)->bit)
+			//if (strlen(uid) >= 8 && strncmp(uid, hash, 8) == 0) {
+			if (strncmp(uid, hash, 8) == 0) {				
+				//CamelMessageInfo *mi;
+				#warning "is it really reqd, if so uncomment it"
+				//mi = camel_folder_get_message_info(f, uid+8);
+				//if (mi) {
+				//	if(camel_message_info_flags(mi) & ((CamelVTrashFolder *)folder)->bit)
 						g_ptr_array_add(folder_uids, uid+8);
-					camel_folder_free_message_info(f, mi);
-				}
+				//	camel_folder_free_message_info(f, mi);
+				//}
 			}
 		}
 
@@ -383,7 +394,8 @@
 				vuid = g_malloc(strlen(uid)+9);
 				memcpy(vuid, hash, 8);
 				strcpy(vuid+8, uid);
-				g_ptr_array_add(result, vuid);
+				g_ptr_array_add(result, camel_pstring_strdup(vuid));
+				g_free (vuid);
 			}
 			camel_folder_search_free(f, matches);
 		}
@@ -415,7 +427,7 @@
 }
 
 static void
-vtrash_uid_added(CamelVTrashFolder *vf, const char *uid, CamelMessageInfo *info, char hash[8])
+vtrash_uid_added(CamelVTrashFolder *vf, const char *uid, CamelFolderSummary *ssummary, char hash[8])
 {
 	char *vuid;
 	CamelVeeMessageInfo *vinfo;
@@ -425,8 +437,12 @@
 	strcpy(vuid+8, uid);
 	vinfo = (CamelVeeMessageInfo *)camel_folder_summary_uid(((CamelFolder *)vf)->summary, vuid);
 	if (vinfo == NULL) {
-		camel_vee_summary_add((CamelVeeSummary *)((CamelFolder *)vf)->summary, info, hash);
-		camel_folder_change_info_add_uid(((CamelVeeFolder *)vf)->changes, vuid);
+		CamelMessageInfo *tinfo;
+		tinfo = camel_vee_summary_add((CamelVeeSummary *)((CamelFolder *)vf)->summary, ssummary, uid, hash);
+		if (tinfo) {
+			camel_folder_change_info_add_uid(((CamelVeeFolder *)vf)->changes, vuid);
+			camel_message_info_free (tinfo);
+		}
 	} else {
 		camel_folder_change_info_change_uid(((CamelVeeFolder *)vf)->changes, vuid);
 		camel_message_info_free(vinfo);
@@ -460,7 +476,7 @@
 		if ((camel_message_info_flags(info) & ((CamelVTrashFolder *)vf)->bit) == 0)
 			vtrash_uid_removed((CamelVTrashFolder *)vf, uid, hash);
 		else
-			vtrash_uid_added((CamelVTrashFolder *)vf, uid, info, hash);
+			vtrash_uid_added((CamelVTrashFolder *)vf, uid, sub->summary, hash);
 
 		camel_message_info_free(info);
 	}
@@ -474,7 +490,7 @@
 			continue;
 
 		if ((camel_message_info_flags(info) & ((CamelVTrashFolder *)vf)->bit) != 0)
-			vtrash_uid_added((CamelVTrashFolder *)vf, uid, info, hash);
+			vtrash_uid_added((CamelVTrashFolder *)vf, uid, sub->summary, hash);
 
 		camel_message_info_free(info);
 	}
@@ -495,7 +511,7 @@
 static void
 vtrash_add_folder(CamelVeeFolder *vf, CamelFolder *sub)
 {
-	GPtrArray *infos;
+	GPtrArray *infos=NULL;
 	int i;
 	char hash[8];
 	CamelFolderChangeInfo *vf_changes = NULL;
@@ -504,14 +520,25 @@
 
 	CAMEL_VEE_FOLDER_LOCK(vf, summary_lock);
 
-	infos = camel_folder_get_summary(sub);
-	for (i=0;i<infos->len;i++) {
-		CamelMessageInfo *info = infos->pdata[i];
+	#warning "Search for deleted /junk uids in the db and add them directly"
+	if (((CamelVTrashFolder *)vf)->bit == CAMEL_MESSAGE_DELETED)
+		infos = camel_db_get_folder_deleted_uids (sub->cdb, sub->full_name, NULL);
+	else if (((CamelVTrashFolder *)vf)->bit == CAMEL_MESSAGE_JUNK)
+		infos = camel_db_get_folder_junk_uids (sub->cdb, sub->full_name, NULL);
 
-		if ((camel_message_info_flags(info) & ((CamelVTrashFolder *)vf)->bit))
-			vtrash_uid_added((CamelVTrashFolder *)vf, camel_message_info_uid(info), info, hash);
+	if (!infos) {
+		CAMEL_VEE_FOLDER_UNLOCK(vf, summary_lock);
+		return;
 	}
-	camel_folder_free_summary(sub, infos);
+	
+	for (i=0;i<infos->len;i++) {
+		CamelMessageInfo *info;
+		char *uid = infos->pdata[i];
+		vtrash_uid_added((CamelVTrashFolder *)vf, uid, sub->summary, hash);
+	}
+	
+	g_ptr_array_foreach (infos, camel_pstring_free, NULL);
+	g_ptr_array_free (infos, TRUE);
 
 	if (camel_folder_change_info_changed(vf->changes)) {
 		vf_changes = vf->changes;
@@ -542,14 +569,18 @@
 
 	start = -1;
 	last = -1;
-	infos = camel_folder_get_summary(sub);
+	infos = camel_folder_get_summary ((CamelFolder *) vf);
 	for (i=0;i<infos->len;i++) {
-		CamelVeeMessageInfo *mi = infos->pdata[i];
 
-		if (mi == NULL || mi->real == NULL)
+		CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *) camel_folder_summary_uid (((CamelFolder *)vf)->summary, infos->pdata[i]);
+		if (mi == NULL)
 			continue;
+		if (mi->summary == NULL) {
+			camel_message_info_free (mi);
+			continue;
+		}
 
-		if (mi->real->summary == ssummary) {
+		if (mi->summary == ssummary) {
 			const char *uid = camel_message_info_uid(mi);
 
 			camel_folder_change_info_remove_uid(vf->changes, uid);
@@ -564,6 +595,7 @@
 				start = last = i;
 			}
 		}
+		camel_message_info_free (mi);
 	}
 	camel_folder_free_summary(sub, infos);
 

Added: trunk/camel/db-scrap-tools/db.c
==============================================================================
--- (empty file)
+++ trunk/camel/db-scrap-tools/db.c	Wed Jul 16 11:38:32 2008
@@ -0,0 +1,116 @@
+/* GPL v2 or later - Srinivasa Ragavan - sragavan novell com */
+
+#include <stdio.h>
+#include <sqlite3.h>
+
+
+sqlite3 *db;
+
+static int 
+callback (void *data, int argc, char **argv, char **azColName)
+{
+  	int i;
+  	for(i=0; i<argc; i++) {
+    		printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
+  	}
+  	printf("--DONE \n");
+
+  	return 0;
+}
+
+static int
+select_stmt (const char* stmt) {
+  	char *errmsg;
+  	int   ret;
+  	int   nrecs = 0;
+
+  	ret = sqlite3_exec(db, stmt, callback, &nrecs, &errmsg);
+
+  	if(ret!=SQLITE_OK) {
+    		printf("Error in select statement %s [%s].\n", stmt, errmsg);
+  	} else {
+    		printf("\n   %d records returned.\n", nrecs);
+  	}
+
+	return ret;
+}
+
+static int
+sql_stmt(const char* stmt) {
+  	char *errmsg;
+  	int   ret;
+
+  	ret = sqlite3_exec(db, stmt, 0, 0, &errmsg);
+
+  	if(ret != SQLITE_OK) {
+    		printf("Error in statement: %s [%s].\n", stmt, errmsg);
+		exit (1);
+ 	}
+
+	return ret;
+}
+
+#define CREATE_STMT "CREATE TABLE %s (uid TEXT PRIMARY KEY, gflags INTEGER, isize INTEGER, dsent INTEGER, dreceived INTEGER, jsubject TEXT, ffrom TEXT, tto TEXT, cc TEXT, mlist TEXT, part TEXT, userflags TEXT, usertags TEXT, bdata TEXT)"
+
+static int
+create_table (const char *tablename)
+{
+	char *cmd = malloc (sizeof(CREATE_STMT)+20);
+	sprintf(cmd, CREATE_STMT, tablename);
+	sql_stmt (cmd);
+}
+
+int sort_uid (void *foo, int len, void * data1, int len2, void *data2)
+{
+	printf("%s \n%s\n\n", data1, data2);
+	int a1 = atoi (data1);
+	int a2 = atoi (data2);
+	return a1 < a2;
+}
+
+int sort_cmp (void *foo, int len, void * data1, int len2, void *data2)
+{
+	printf("%s \n%s\n\n", data1, data2);
+	int a1 = atoi (data1);
+	int a2 = atoi (data2);
+	return a1 == a2 ? 0 : a1 < a2 ? -1 : 1;
+}
+
+int main(int argc, char **argv) {
+	char *zErrMsg = 0;
+	int rc;
+
+//  	rc = sqlite3_open_v2("test.db", &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE , NULL);
+	rc = sqlite3_open("test.db", &db);
+
+  	if( rc ) {
+    		fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
+    		sqlite3_close(db);
+    		exit(1);
+  	}
+
+	sqlite3_create_collation(db, "uidcmp", SQLITE_UTF8,  NULL, sort_cmp);
+	sqlite3_create_collation(db, "uidsort", SQLITE_UTF8,  NULL, sort_uid);
+
+	char *subject_san = "San?%*()-234 #$!@#$ #$%32424kar's Subject";
+	create_table ("table1");
+	sql_stmt (sqlite3_mprintf("INSERT INTO table1 (uid, gflags, isize, jsubject, mlist) VALUES ('5120', 100, 123, '%q', 'mlistbinary')", subject_san));
+	sql_stmt ("INSERT INTO table1 (uid, gflags, isize, jsubject, mlist) VALUES ('6103', 100, 123, 'nice subject', 'mlistbinary')");
+	sql_stmt ("INSERT INTO table1 (uid, gflags, isize, jsubject, mlist) VALUES ('3194', 100, 123, 'nice subject', 'mlistbinary')");
+	sql_stmt ("INSERT INTO table1 (uid, gflags, isize, jsubject, mlist) VALUES ('8130', 100, 123, 'nice subject', 'mlistbinary')");
+	sql_stmt ("INSERT INTO table1 (uid, gflags, isize, jsubject, mlist) VALUES ('9102', 100, 123, 'nice subject', 'mlistbinary')");
+	sql_stmt ("INSERT INTO table1 (uid, gflags, isize, jsubject, mlist) VALUES ('3112', 100, 123, 'nice subject', 'mlistbinary')");
+	sql_stmt ("INSERT INTO table1 (uid, gflags, isize, jsubject, mlist) VALUES ('1102', 100, 123, 'nice subject', 'mlistbinary')");
+	sql_stmt ("INSERT INTO table1 (uid, gflags, isize, jsubject, mlist) VALUES ('214', 100, 123, 'nice subject', 'mlistbinary')");
+	sql_stmt ("INSERT INTO table1 (uid, gflags, isize, jsubject, mlist) VALUES ('3161', 0, 1123, '12nice subject', '123mlistbinary')");
+	
+//	select_stmt ("select * from table1 where uid collate uidsort order by uid collate uidsort");
+	select_stmt ("select * from table1 where uid == 5120 collate uidcmp");
+	printf ("\n\aFrom teh C File: [%s] \n\a", subject_san);
+
+	printf("------\n");
+	select_stmt ("select count(isize) from table1");
+  	sqlite3_close(db);
+
+  	return 0;
+}

Modified: trunk/camel/providers/groupwise/camel-groupwise-folder.c
==============================================================================
--- trunk/camel/providers/groupwise/camel-groupwise-folder.c	(original)
+++ trunk/camel/providers/groupwise/camel-groupwise-folder.c	Wed Jul 16 11:38:32 2008
@@ -590,7 +590,7 @@
 static void 
 groupwise_sync_summary (CamelFolder *folder, CamelException *ex)
 {
-	camel_folder_summary_save (folder->summary);
+	camel_folder_summary_save_to_db (folder->summary, ex);
 	camel_store_summary_touch ((CamelStoreSummary *)((CamelGroupwiseStore *)folder->parent_store)->summary);
 	camel_store_summary_save ((CamelStoreSummary *)((CamelGroupwiseStore *)folder->parent_store)->summary);
 }
@@ -673,6 +673,7 @@
 				const char *uid;
 
 				gw_info->info.flags &= ~CAMEL_MESSAGE_FOLDER_FLAGGED;
+				gw_info->info.dirty = 1;
 				gw_info->server_flags = gw_info->info.flags;
 				uid = camel_message_info_uid (info);
 				if (diff.bits & CAMEL_MESSAGE_DELETED) {
@@ -1004,7 +1005,7 @@
 			}
 			camel_store_summary_info_free ((CamelStoreSummary *)((CamelGroupwiseStore *)folder->parent_store)->summary, si);
 		}
-		camel_folder_summary_save (folder->summary);
+		//camel_folder_summary_save_to_db (folder->summary, ex);
 		camel_store_summary_save ((CamelStoreSummary *)((CamelGroupwiseStore *)folder->parent_store)->summary);
 	} else {
 		/* We probably could not get the messages the first time. (get_folder) failed???!
@@ -1036,7 +1037,7 @@
 
 	/* Sync-up the (un)read changes before getting updates,
 	so that the getFolderList will reflect the most recent changes too */
-	groupwise_sync (folder, FALSE, ex);
+	//groupwise_sync (folder, FALSE, ex);
 
 	if (((CamelOfflineStore *) gw_store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) {
 		g_warning ("In offline mode. Cannot refresh!!!\n");
@@ -1969,7 +1970,8 @@
 	int index = 0;
 	GList *temp;
 	CamelFolderChangeInfo *changes = NULL;
-	CamelMessageInfo *info; 
+	char *uid;
+
 	changes = camel_folder_change_info_new ();
 
 	item_list = g_list_reverse (item_list);
@@ -1977,18 +1979,18 @@
 	summary = camel_folder_get_summary (folder);
 	/*item_ids : List of ids from the summary*/
 	while (index < summary->len) {
-		info = g_ptr_array_index (summary, index);
+		uid = g_ptr_array_index (summary, index);
 		temp = NULL; 
 
 		if (item_list) {
-			temp = g_list_find_custom (item_list, (const char *)info->uid, (GCompareFunc) strcmp);
+			temp = g_list_find_custom (item_list, (const char *)uid, (GCompareFunc) strcmp);
 		}
 
 		if (!temp) {
 			CAMEL_GROUPWISE_FOLDER_REC_LOCK (folder, cache_lock);
-			camel_folder_summary_remove_uid (folder->summary, info->uid);
-			camel_data_cache_remove (gw_folder->cache, "cache", info->uid, NULL);
-			camel_folder_change_info_remove_uid (changes, info->uid);
+			camel_folder_summary_remove_uid (folder->summary, uid);
+			camel_data_cache_remove (gw_folder->cache, "cache", uid, NULL);
+			camel_folder_change_info_remove_uid (changes, uid);
 			CAMEL_GROUPWISE_FOLDER_REC_UNLOCK (folder, cache_lock);
 		} else { 
 			item_list = g_list_delete_link (item_list, temp);

Modified: trunk/camel/providers/groupwise/camel-groupwise-store.c
==============================================================================
--- trunk/camel/providers/groupwise/camel-groupwise-store.c	(original)
+++ trunk/camel/providers/groupwise/camel-groupwise-store.c	Wed Jul 16 11:38:32 2008
@@ -634,7 +634,7 @@
 				CAMEL_SERVICE_REC_UNLOCK (gw_store, connect_lock);
 				e_gw_connection_destroy_cursor (priv->cnc, container_id, cursor);
 				//camel_folder_summary_clear (folder->summary);
-				camel_folder_summary_save (folder->summary);
+				camel_folder_summary_save_to_db (folder->summary, ex);
 				camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_INVALID, _("Authentication failed"));
 				camel_operation_end (NULL);
 				camel_object_unref (folder);
@@ -666,7 +666,7 @@
 		summary->time_string = g_strdup (e_gw_connection_get_server_time (priv->cnc));
 	}
 
-	camel_folder_summary_save (folder->summary);
+	camel_folder_summary_save_to_db (folder->summary, ex);
 
 	gw_store->current_folder = folder;
 	camel_object_ref (folder);
@@ -717,7 +717,7 @@
 
 	summary = (CamelGroupwiseSummary *) folder->summary;
 	camel_folder_summary_clear (folder->summary);
-	camel_folder_summary_save (folder->summary);
+	camel_folder_summary_save_to_db (folder->summary, ex);
 
 	summary_count = camel_folder_summary_count (folder->summary);
 	if(!summary_count || !summary->time_string) {
@@ -742,7 +742,7 @@
 			if (status != E_GW_CONNECTION_STATUS_OK) {
 				CAMEL_SERVICE_REC_UNLOCK (gw_store, connect_lock);
 				e_gw_connection_destroy_cursor (priv->cnc, container_id, cursor);
-				camel_folder_summary_save (folder->summary);
+				camel_folder_summary_save_to_db (folder->summary, ex);
 				camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_INVALID, _("Authentication failed"));
 				camel_operation_end (NULL);
 				g_free (container_id);
@@ -774,7 +774,7 @@
 		summary->time_string = g_strdup (e_gw_connection_get_server_time (priv->cnc));
 	}
 
-	camel_folder_summary_save (folder->summary);
+	camel_folder_summary_save_to_db (folder->summary, ex);
 
 	gw_store->current_folder = folder;
 	

Modified: trunk/camel/providers/groupwise/camel-groupwise-summary.c
==============================================================================
--- trunk/camel/providers/groupwise/camel-groupwise-summary.c	(original)
+++ trunk/camel/providers/groupwise/camel-groupwise-summary.c	Wed Jul 16 11:38:32 2008
@@ -42,6 +42,9 @@
 
 #define CAMEL_GW_SUMMARY_VERSION (1)
 
+#define EXTRACT_FIRST_DIGIT(val) part ? val=strtoul (part, &part, 10) : 0;
+#define EXTRACT_DIGIT(val) part++; part ? val=strtoul (part, &part, 10) : 0;
+
 /*Prototypes*/
 static int gw_summary_header_load (CamelFolderSummary *, FILE *);
 static int gw_summary_header_save (CamelFolderSummary *, FILE *);
@@ -53,6 +56,13 @@
 static int gw_content_info_save (CamelFolderSummary *s, FILE *out, CamelMessageContentInfo *info) ;
 static gboolean gw_info_set_flags(CamelMessageInfo *info, guint32 flags, guint32 set);		
 
+static int summary_header_from_db (CamelFolderSummary *s, CamelFIRecord *mir);
+static CamelFIRecord * summary_header_to_db (CamelFolderSummary *s, CamelException *ex);
+static CamelMIRecord * message_info_to_db (CamelFolderSummary *s, CamelMessageInfo *info);
+static CamelMessageInfo * message_info_from_db (CamelFolderSummary *s, CamelMIRecord *mir);
+static int content_info_to_db (CamelFolderSummary *s, CamelMessageContentInfo *info, CamelMIRecord *mir);
+static CamelMessageContentInfo * content_info_from_db (CamelFolderSummary *s, CamelMIRecord *mir);
+
 static void camel_groupwise_summary_class_init (CamelGroupwiseSummaryClass *klass);
 static void camel_groupwise_summary_init       (CamelGroupwiseSummary *obj);
 
@@ -112,6 +122,14 @@
 	cfs_class->content_info_load = gw_content_info_load;
 	cfs_class->content_info_save = gw_content_info_save;
 	cfs_class->info_set_flags = gw_info_set_flags;
+
+	cfs_class->summary_header_to_db = summary_header_to_db;
+	cfs_class->summary_header_from_db = summary_header_from_db;
+	cfs_class->message_info_to_db = message_info_to_db;
+	cfs_class->message_info_from_db = message_info_from_db;
+	cfs_class->content_info_to_db = content_info_to_db;
+	cfs_class->content_info_from_db = content_info_from_db;
+	
 }
 
 
@@ -141,53 +159,109 @@
 CamelFolderSummary *
 camel_groupwise_summary_new (struct _CamelFolder *folder, const char *filename)
 {
+	CamelException ex;
 	CamelFolderSummary *summary = CAMEL_FOLDER_SUMMARY (
 			camel_object_new (camel_groupwise_summary_get_type ()));
 	
 	summary->folder = folder ;
 	camel_folder_summary_set_build_content (summary, TRUE);
-	camel_folder_summary_set_filename (summary, filename);
 
-	if (camel_folder_summary_load (summary) == -1) {
+	camel_exception_init (&ex);
+	if (camel_folder_summary_load_from_db (summary, &ex) == -1) {
 		camel_folder_summary_clear (summary);
-		camel_folder_summary_touch (summary);
 	}
 
 	return summary;
 }
 
 static int
+summary_header_from_db (CamelFolderSummary *s, CamelFIRecord *mir)
+{
+	CamelGroupwiseSummary *gms = CAMEL_GROUPWISE_SUMMARY (s);
+	char *part;
+
+	if (camel_groupwise_summary_parent->summary_header_from_db (s, mir) == -1)
+		return -1 ;
+
+	part = mir->bdata;
+
+	if (part)
+		EXTRACT_FIRST_DIGIT(gms->version);
+
+	if (part)
+		EXTRACT_DIGIT (gms->validity);
+
+	if (part && part++) {
+		gms->time_string = g_strdup (part);
+	}
+		
+	return 0;
+}
+
+static int
 gw_summary_header_load (CamelFolderSummary *s, FILE *in)
 {
-	CamelGroupwiseSummary *ims = CAMEL_GROUPWISE_SUMMARY (s);
+	CamelGroupwiseSummary *gms = CAMEL_GROUPWISE_SUMMARY (s);
 
 	if (camel_groupwise_summary_parent->summary_header_load (s, in) == -1)
 		return -1 ;
 
-	if (camel_file_util_decode_fixed_int32(in, &ims->version) == -1
-			|| camel_file_util_decode_fixed_int32(in, &ims->validity) == -1)
+	if (camel_file_util_decode_fixed_int32(in, &gms->version) == -1
+			|| camel_file_util_decode_fixed_int32(in, &gms->validity) == -1)
 		return -1;
 	
-	if (camel_file_util_decode_string (in, &ims->time_string) == -1)
+	if (camel_file_util_decode_string (in, &gms->time_string) == -1)
 		return -1;
 	return 0 ;
 }
 
 
+
+
+
+static CamelFIRecord *
+summary_header_to_db (CamelFolderSummary *s, CamelException *ex)
+{
+	CamelGroupwiseSummary *ims = CAMEL_GROUPWISE_SUMMARY(s);
+	struct _CamelFIRecord *fir;
+	
+	fir = camel_groupwise_summary_parent->summary_header_to_db (s, ex);
+	if (!fir)
+		return NULL;
+	
+	fir->bdata = g_strdup_printf ("%d %d %s", CAMEL_GW_SUMMARY_VERSION, ims->validity, ims->time_string);
+
+	return fir;
+	
+}
+
 static int
 gw_summary_header_save (CamelFolderSummary *s, FILE *out)
 {
-	CamelGroupwiseSummary *ims = CAMEL_GROUPWISE_SUMMARY(s);
+	CamelGroupwiseSummary *gms = CAMEL_GROUPWISE_SUMMARY(s);
 
 	if (camel_groupwise_summary_parent->summary_header_save (s, out) == -1)
 		return -1;
 
 	camel_file_util_encode_fixed_int32(out, CAMEL_GW_SUMMARY_VERSION);
-	camel_file_util_encode_fixed_int32(out, ims->validity);
-	return camel_file_util_encode_string (out, ims->time_string);
+	camel_file_util_encode_fixed_int32(out, gms->validity);
+	return camel_file_util_encode_string (out, gms->time_string);
+}
 
+static CamelMessageInfo * 
+message_info_from_db (CamelFolderSummary *s, CamelMIRecord *mir)
+{
+	CamelMessageInfo *info;
+	CamelGroupwiseMessageInfo *iinfo;
 
-}
+	info = camel_groupwise_summary_parent->message_info_from_db (s, mir);
+	if (info) {
+		char *part = mir->bdata;
+		iinfo = (CamelGroupwiseMessageInfo *)info;
+		EXTRACT_FIRST_DIGIT (iinfo->server_flags)
+	}
+
+	return info;}
 
 static CamelMessageInfo *
 gw_message_info_load (CamelFolderSummary *s, FILE *in)
@@ -209,6 +283,18 @@
 	return NULL ;
 }
 
+static CamelMIRecord * 
+message_info_to_db (CamelFolderSummary *s, CamelMessageInfo *info)
+{
+	CamelGroupwiseMessageInfo *iinfo = (CamelGroupwiseMessageInfo *)info;
+	struct _CamelMIRecord *mir;
+
+	mir = camel_groupwise_summary_parent->message_info_to_db (s, info);
+	if (mir) 
+		mir->bdata = g_strdup_printf ("%u", iinfo->server_flags);
+
+	return mir;	
+}
 
 static int
 gw_message_info_save (CamelFolderSummary *s, FILE *out, CamelMessageInfo *info)
@@ -221,6 +307,21 @@
 	return camel_file_util_encode_uint32 (out, gw_info->server_flags);
 }
 
+static CamelMessageContentInfo * 
+content_info_from_db (CamelFolderSummary *s, CamelMIRecord *mir)
+{
+	char *part = mir->cinfo;
+	guint32 type=0;
+	
+	if (part) {
+		EXTRACT_FIRST_DIGIT (type);
+	}
+	if (type)
+		return camel_groupwise_summary_parent->content_info_from_db (s, mir);
+	else
+		return camel_folder_summary_content_info_new (s);
+}
+
 
 static CamelMessageContentInfo *
 gw_content_info_load (CamelFolderSummary *s, FILE *in)
@@ -231,6 +332,18 @@
 		return camel_folder_summary_content_info_new (s);
 }
 
+static int 
+content_info_to_db (CamelFolderSummary *s, CamelMessageContentInfo *info, CamelMIRecord *mir)
+{
+
+	if (info->type) {
+		mir->cinfo = g_strdup ("1");
+		return camel_groupwise_summary_parent->content_info_to_db (s, info, mir);
+	} else {
+		mir->cinfo = g_strdup ("0");
+		return 0;
+	}
+}
 
 static int
 gw_content_info_save (CamelFolderSummary *s, FILE *out,
@@ -355,7 +468,7 @@
 	}
 
 	camel_folder_summary_clear (summary);
-	camel_folder_summary_save (summary);
+	//camel_folder_summary_save (summary);
 
 	if (uncache)
 		camel_data_cache_clear (((CamelGroupwiseFolder *) summary->folder)->cache, "cache", NULL);

Modified: trunk/camel/providers/imap/camel-imap-folder.c
==============================================================================
--- trunk/camel/providers/imap/camel-imap-folder.c	(original)
+++ trunk/camel/providers/imap/camel-imap-folder.c	Wed Jul 16 11:38:32 2008
@@ -306,11 +306,10 @@
 	CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder);
 	CamelImapSummary *imap_summary = CAMEL_IMAP_SUMMARY (folder->summary);
 	unsigned long exists = 0, validity = 0, val, uid;
-	CamelMessageInfo *info;
 	guint32 perm_flags = 0;
 	GData *fetch_data;
 	int i, count;
-	char *resp;
+	char *resp, *old_uid;
 	
 	count = camel_folder_summary_count (folder->summary);
 	
@@ -408,11 +407,13 @@
 		}
 		camel_imap_response_free_without_processing (store, response);
 		
-		info = camel_folder_summary_index (folder->summary, count - 1);
-		val = strtoul (camel_message_info_uid (info), NULL, 10);
-		camel_message_info_free(info);
-		if (uid == 0 || uid != val)
-			imap_folder->need_rescan = TRUE;
+		old_uid = camel_folder_summary_uid_from_index (folder->summary, 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;
+		}
 	}
 	
 	/* Now rescan if we need to */
@@ -725,7 +726,7 @@
 done:
 	CAMEL_SERVICE_REC_UNLOCK (imap_store, connect_lock);
 
-	camel_folder_summary_save(folder->summary);
+	camel_folder_summary_save_to_db (folder->summary, ex);
 	camel_store_summary_save((CamelStoreSummary *)((CamelImapStore *)folder->parent_store)->summary);
 }
 
@@ -738,7 +739,7 @@
 	array_str = g_strsplit (custom_flags, " ", -1);
 
 	while (array_str[index] != NULL) {
-		camel_message_info_set_user_flag (mi, array_str[index], TRUE);
+		camel_flag_set(&((CamelMessageInfoBase *)mi)->user_flags, array_str[index], TRUE);
 		++ index;
 	}
 
@@ -791,7 +792,8 @@
 			/* If this value came from the server, then add it to our local summary,
 			   otherwise it was in local summary, but isn't on the server, thus remove it. */
 			changed = TRUE;
-			camel_message_info_set_user_flag (mi, p->data, g_hash_table_lookup (server, p->data) != NULL);
+			camel_flag_set (mi, p->data, g_hash_table_lookup (server, p->data) != NULL);
+			((CamelMessageInfoBase *) mi)->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED;
 		}
 	}
 
@@ -814,7 +816,7 @@
 		guint32 flags;
 		char *custom_flags;
 	} *new;
-	char *resp;
+	char *resp, *uid;
 	CamelImapResponseType type;
 	int i, seq, summary_len, summary_got;
 	CamelMessageInfo *info;
@@ -837,11 +839,17 @@
 	
 	/* Check UIDs and flags of all messages we already know of. */
 	camel_operation_start (NULL, _("Scanning for changed messages in %s"), folder->name);
-	info = camel_folder_summary_index (folder->summary, summary_len - 1);
+	uid = camel_folder_summary_uid_from_index (folder->summary, summary_len - 1);
+
+	if (!uid) {
+		camel_operation_end (NULL);
+		return;
+	}
+
 	ok = camel_imap_command_start (store, folder, ex,
 				       "UID FETCH 1:%s (FLAGS)",
-				       camel_message_info_uid (info));
-	camel_message_info_free(info);
+				       uid);
+	g_free (uid);
 	if (!ok) {
 		camel_operation_end (NULL);
 		return;
@@ -875,6 +883,11 @@
 		g_datalist_clear (&data);
 	}
 
+	if (summary_got == 0) {
+		CAMEL_SERVICE_REC_UNLOCK (store, connect_lock);
+		g_free(new);
+		return;
+	}
 	camel_operation_end (NULL);
 	if (type == CAMEL_IMAP_RESPONSE_ERROR || camel_application_is_exiting) {
 		for (i = 0; i < summary_len && new[i].uid; i++) {
@@ -900,21 +913,35 @@
 	 * from the summary.
 	 */
 	removed = g_array_new (FALSE, FALSE, sizeof (int));
+	
+	if (summary_len - camel_folder_summary_cache_size (folder->summary) > 50)
+		camel_folder_summary_reload_from_db (folder->summary, ex);
+	
 	for (i = 0; i < summary_len && new[i].uid; i++) {
 		gboolean changed = FALSE;
 
-		info = camel_folder_summary_index (folder->summary, i);
-		iinfo = (CamelImapMessageInfo *)info;
+		uid = camel_folder_summary_uid_from_index (folder->summary, i);
 		
-		if (strcmp (camel_message_info_uid (info), new[i].uid) != 0) {
-			camel_message_info_free(info);
+		if (!uid) 
+			continue; 
+
+		info = camel_folder_summary_uid (folder->summary, uid);
+
+		iinfo = (CamelImapMessageInfo *)info;
+
+		if (strcmp (uid, new[i].uid) != 0) {
+			g_free (uid);
+
 			seq = i + 1;
 			g_array_append_val (removed, seq);
 			i--;
 			summary_len--;
+			camel_message_info_free(info);
 			continue;
 		}
 		
+		g_free (uid);
+
 		/* Update summary flags */
 		if (new[i].flags != iinfo->server_flags) {
 			guint32 server_set, server_cleared;
@@ -984,7 +1011,7 @@
  * caller must free the infos, the array, and the set string.
  */
 static GPtrArray *
-get_matching (CamelFolder *folder, guint32 flags, guint32 mask, CamelMessageInfo *master_info, char **set)
+get_matching (CamelFolder *folder, guint32 flags, guint32 mask, CamelMessageInfo *master_info, char **set, GPtrArray *summary)
 {
 	GPtrArray *matches;
 	CamelImapMessageInfo *info;
@@ -992,6 +1019,7 @@
 	GString *gset;
 	GSList *list1 = NULL;
 	int count1 = 0;
+	char *uid;
 
 	#define close_range()										\
 		if (range != -1) {									\
@@ -1004,10 +1032,16 @@
 
 	matches = g_ptr_array_new ();
 	gset = g_string_new ("");
-	max = camel_folder_summary_count (folder->summary);
+	max = summary->len;	
 	range = -1;
 	for (i = 0; i < max && !UID_SET_FULL (gset->len, UID_SET_LIMIT); i++) {
-		info = (CamelImapMessageInfo *)camel_folder_summary_index (folder->summary, i);
+		uid = summary->pdata[i];
+
+		if (uid) {
+			info = (CamelImapMessageInfo *) camel_folder_summary_uid (folder->summary, uid);
+		} else
+			continue;
+		
 		if (!info)
 			continue;
 		if ((info->info.flags & mask) != flags) {
@@ -1059,6 +1093,10 @@
 		}
 		
 		g_ptr_array_add (matches, info);
+		/* Remove the uid from the list, to optimize*/
+		camel_pstring_free(summary->pdata[i]);
+		summary->pdata[i] = NULL;
+		
 		if (range != -1)
 			continue;
 		range = i;
@@ -1116,7 +1154,7 @@
 		}
 	}
 
-	camel_folder_summary_save (folder->summary);
+	camel_folder_summary_save_to_db (folder->summary, ex);
 	camel_store_summary_save((CamelStoreSummary *)((CamelImapStore *)folder->parent_store)->summary);
 }
 
@@ -1126,8 +1164,9 @@
 	CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store);
 	CamelImapMessageInfo *info;
 	CamelException local_ex;
-	GPtrArray *matches;
-	char *set, *flaglist;
+
+	GPtrArray *matches, *summary;
+	char *set, *flaglist, *uid;
 	int i, j, max;
 	
 	if (folder->permanent_flags == 0) {
@@ -1142,14 +1181,22 @@
 	 * messages like it, sync them as a group, mark them as
 	 * updated, and continue.
 	 */
-	max = camel_folder_summary_count (folder->summary);
+	summary = camel_folder_summary_get_changed (folder->summary); /* These should be in memory anyways*/
+	max = summary->len;
+		
 	for (i = 0; i < max; i++) {
 		gboolean unset = FALSE;
 		CamelImapResponse *response = NULL;
 
-		if (!(info = (CamelImapMessageInfo *)camel_folder_summary_index (folder->summary, i)))
+		uid = summary->pdata[i];
+
+		if (!uid) /* Possibly it was sync by matching flags, which we NULLify */
 			continue;
-		
+
+		if (!(info = (CamelImapMessageInfo *) camel_folder_summary_uid (folder->summary, uid))) {
+			continue;
+		}
+
 		if (!(info->info.flags & CAMEL_MESSAGE_FOLDER_FLAGGED)) {
 			camel_message_info_free((CamelMessageInfo *)info);
 			continue;
@@ -1161,7 +1208,7 @@
 		   they will be scooped up later by our parent loop (I
 		   think?). -- Jeff */
 		matches = get_matching (folder, info->info.flags & (folder->permanent_flags | CAMEL_MESSAGE_FOLDER_FLAGGED),
-					folder->permanent_flags | CAMEL_MESSAGE_FOLDER_FLAGGED, (CamelMessageInfo *)info, &set);
+					folder->permanent_flags | CAMEL_MESSAGE_FOLDER_FLAGGED, (CamelMessageInfo *)info, &set, summary);
 		camel_message_info_free(info);
 		if (matches == NULL)
 			continue;
@@ -1231,6 +1278,9 @@
 		/* Re-lock the connect_lock */
 		CAMEL_SERVICE_REC_LOCK (store, connect_lock);
 	}
+
+	g_ptr_array_foreach (summary, camel_pstring_free, NULL);
+	g_ptr_array_free (summary, TRUE);
 	
 	/* Save the summary */
 	imap_sync_offline (folder, ex);
@@ -1271,7 +1321,7 @@
 		 * the cached data may be useful in replaying a COPY later.
 		 */
 	}
-	camel_folder_summary_save (folder->summary);
+	camel_folder_summary_save_to_db (folder->summary, ex);
 
 	camel_disco_diary_log (CAMEL_DISCO_STORE (folder->parent_store)->diary,
 			       CAMEL_DISCO_DIARY_FOLDER_EXPUNGE, folder, uids);
@@ -2834,7 +2884,7 @@
 	GString *header_spec = NULL;
 	CamelImapMessageInfo *mi, *info;
 	CamelStream *stream;
-	char *uid, *resp;
+	char *uid, *resp, *tempuid;
 	GData *data;
 	extern int camel_application_is_exiting;
 
@@ -2869,9 +2919,13 @@
 	seq = camel_folder_summary_count (folder->summary);
 	first = seq + 1;
 	if (seq > 0) {
-		mi = (CamelImapMessageInfo *)camel_folder_summary_index (folder->summary, seq - 1);
-		uidval = strtoul(camel_message_info_uid (mi), NULL, 10);
-		camel_message_info_free(&mi->info);
+		tempuid = camel_folder_summary_uid_from_index (folder->summary, seq -1 );
+
+		if (tempuid) {
+			uidval = strtoul(tempuid, NULL, 10);
+			g_free (tempuid);
+		} else
+			uidval = 0;
 	} else
 		uidval = 0;
 	
@@ -2891,10 +2945,13 @@
 	 */
 	fetch_data = g_ptr_array_new ();
 	messages = g_ptr_array_new ();
+	int k = 0, ct;
+	ct = exists - seq;
 	while ((type = camel_imap_command_response (store, &resp, ex)) ==
 	       CAMEL_IMAP_RESPONSE_UNTAGGED && !camel_application_is_exiting) {
 		data = parse_fetch_response (imap_folder, resp);
 		g_free (resp);
+		k++;
 		if (!data)
 			continue;
 		
@@ -2919,7 +2976,7 @@
 			g_datalist_set_data (&data, "BODY_PART_STREAM", NULL);
 		}
 
-		camel_operation_progress (NULL, got * 100 / size);
+		camel_operation_progress (NULL, k * 100 / ct);
 		g_ptr_array_add (fetch_data, data);
 	}
 	camel_operation_end (NULL);
@@ -3047,7 +3104,7 @@
 		
 		uid = g_datalist_get_data (&data, "UID");
 		if (uid)
-			mi->info.uid = g_strdup (uid);
+			mi->info.uid = camel_pstring_strdup (uid);
 		flags = GPOINTER_TO_INT (g_datalist_get_data (&data, "FLAGS"));
 		if (flags) {
 			char *custom_flags = NULL;
@@ -3098,22 +3155,26 @@
 					      i + first);
 			break;
 		}
-		info = (CamelImapMessageInfo *)camel_folder_summary_uid(folder->summary, uid);
-		if (info) {
-			for (seq = 0; seq < camel_folder_summary_count (folder->summary); seq++) {
-				if (folder->summary->messages->pdata[seq] == info)
-					break;
-			}
 
-			g_warning("Message already present? %s", camel_message_info_uid(mi));
-			camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
-					      _("Unexpected server response: Identical UIDs provided for messages %d and %d"),
-					      seq + 1, i + first);
-
-			camel_message_info_free(&info->info);
-			break;
-		} 
+		/* FIXME: If it enters if(info) it will always match the exception. So stupid */
+		#warning "Use a db query to see if the DB exists"
+/* 		info = (CamelImapMessageInfo *)camel_folder_summary_uid(folder->summary, uid); */
+/* 		if (info) { */
+/* 			for (seq = 0; seq < camel_folder_summary_count (folder->summary); seq++) { */
+/* 				if (folder->summary->messages->pdata[seq] == info) */
+/* 					break; */
+/* 			} */
+
+/* 			g_warning("Message already present? %s", camel_message_info_uid(mi)); */
+/* 			camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, */
+/* 					      _("Unexpected server response: Identical UIDs provided for messages %d and %d"), */
+/* 					      seq + 1, i + first); */
+
+/* 			camel_message_info_free(&info->info); */
+/* 			break; */
+/* 		}  */
 
+		((CamelMessageInfoBase *)mi)->dirty = TRUE;
 		camel_folder_summary_add (folder->summary, (CamelMessageInfo *)mi);
 		camel_folder_change_info_add_uid (changes, camel_message_info_uid (mi));
 
@@ -3123,11 +3184,6 @@
 			camel_folder_change_info_recent_uid (changes, camel_message_info_uid (mi));
 	}
 
-	for ( ; i < messages->len; i++) {
-		if ((mi = messages->pdata[i]))
-			camel_message_info_free(&mi->info);
-	}
-	
 	g_ptr_array_free (messages, TRUE);
 	
 	return;
@@ -3159,26 +3215,27 @@
 	CamelFolderChangeInfo *changes;
 	CamelMessageInfo *info;
 	int len;
-	
+	char *uid;
+
 	changes = camel_folder_change_info_new ();
 	if (expunged) {
 		int i, id;
 		
 		for (i = 0; i < expunged->len; i++) {
 			id = g_array_index (expunged, int, i);
-			info = camel_folder_summary_index (folder->summary, id - 1);
-			if (info == NULL) {
+			uid = camel_folder_summary_uid_from_index (folder->summary, id - 1);
+			if (uid == NULL) {
 				/* FIXME: danw: does this mean that the summary is corrupt? */
 				/* I guess a message that we never retrieved got expunged? */
 				continue;
 			}
 			
-			camel_folder_change_info_remove_uid (changes, camel_message_info_uid (info));
+			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, camel_message_info_uid (info));
+			camel_imap_message_cache_remove (imap_folder->cache, uid);
 			CAMEL_IMAP_FOLDER_REC_UNLOCK (imap_folder, cache_lock);
-			camel_folder_summary_remove (folder->summary, info);
-			camel_message_info_free(info);
+			camel_folder_summary_remove_uid (folder->summary, uid);
+			g_free (uid);
 		}
 	}
 
@@ -3190,7 +3247,7 @@
 		camel_object_trigger_event (CAMEL_OBJECT (folder), "folder_changed", changes);
 
 	camel_folder_change_info_free (changes);
-	camel_folder_summary_save (folder->summary);
+	camel_folder_summary_save_to_db (folder->summary, ex);
 }
 
 static void

Modified: trunk/camel/providers/imap/camel-imap-message-cache.c
==============================================================================
--- trunk/camel/providers/imap/camel-imap-message-cache.c	(original)
+++ trunk/camel/providers/imap/camel-imap-message-cache.c	Wed Jul 16 11:38:32 2008
@@ -179,12 +179,17 @@
 		else
 			uid = g_strdup (dname);
 
+		#warning "this could be wrong"
+		if (summary->loaded_infos && g_hash_table_lookup (summary->loaded_infos, uid))
+			cache_put (cache, uid, dname, NULL);
+
+		/*
 		info = camel_folder_summary_uid (summary, uid);
 		if (info) {
 			camel_message_info_free(info);
 			cache_put (cache, uid, dname, NULL);
 		} else
-			g_ptr_array_add (deletes, g_strdup_printf ("%s/%s", cache->path, dname));
+			g_ptr_array_add (deletes, g_strdup_printf ("%s/%s", cache->path, dname)); */
 		g_free (uid);
 	}
 	g_dir_close (dir);

Modified: trunk/camel/providers/imap/camel-imap-store.c
==============================================================================
--- trunk/camel/providers/imap/camel-imap-store.c	(original)
+++ trunk/camel/providers/imap/camel-imap-store.c	Wed Jul 16 11:38:32 2008
@@ -2660,10 +2660,15 @@
 
 	folder = camel_object_bag_peek(store->folders, fi->full_name);
 	if (folder) {
-		fi->unread = camel_folder_get_unread_message_count(folder);
-		fi->total = camel_folder_get_message_count(folder);
+		CamelImapSummary *ims;
+		ims = (CamelImapSummary *) camel_imap_summary_new (folder, NULL);
+
+		fi->unread = ((CamelFolderSummary *)ims)->unread_count;
+		fi->total = ((CamelFolderSummary *)ims)->saved_count;
+
+		camel_object_unref(ims);
 		camel_object_unref(folder);
-	}
+	} 
 }
 
 struct _refresh_msg {

Modified: trunk/camel/providers/imap/camel-imap-summary.c
==============================================================================
--- trunk/camel/providers/imap/camel-imap-summary.c	(original)
+++ trunk/camel/providers/imap/camel-imap-summary.c	Wed Jul 16 11:38:32 2008
@@ -38,6 +38,9 @@
 
 #define CAMEL_IMAP_SUMMARY_VERSION (3)
 
+#define EXTRACT_FIRST_DIGIT(val) val=strtoul (part, &part, 10);
+#define EXTRACT_DIGIT(val) part++; val=strtoul (part, &part, 10);
+
 static int summary_header_load (CamelFolderSummary *, FILE *);
 static int summary_header_save (CamelFolderSummary *, FILE *);
 
@@ -49,9 +52,19 @@
 static int content_info_save (CamelFolderSummary *s, FILE *out,
 			      CamelMessageContentInfo *info);
 
+static int summary_header_from_db (CamelFolderSummary *s, CamelFIRecord *mir);
+static CamelFIRecord * summary_header_to_db (CamelFolderSummary *s, CamelException *ex);
+static CamelMIRecord * message_info_to_db (CamelFolderSummary *s, CamelMessageInfo *info);
+static CamelMessageInfo * message_info_from_db (CamelFolderSummary *s, CamelMIRecord *mir);
+static int content_info_to_db (CamelFolderSummary *s, CamelMessageContentInfo *info, CamelMIRecord *mir);
+static CamelMessageContentInfo * content_info_from_db (CamelFolderSummary *s, CamelMIRecord *mir);
+
+
 static void camel_imap_summary_class_init (CamelImapSummaryClass *klass);
 static void camel_imap_summary_init       (CamelImapSummary *obj);
 
+static int uid_compare (const void *va, const void *vb);
+
 static CamelFolderSummaryClass *camel_imap_summary_parent;
 
 CamelType
@@ -103,6 +116,13 @@
 	cfs_class->message_info_save = message_info_save;
 	cfs_class->content_info_load = content_info_load;
 	cfs_class->content_info_save = content_info_save;
+	
+	cfs_class->summary_header_to_db = summary_header_to_db;
+	cfs_class->summary_header_from_db = summary_header_from_db;
+	cfs_class->message_info_to_db = message_info_to_db;
+	cfs_class->message_info_from_db = message_info_from_db;
+	cfs_class->content_info_to_db = content_info_to_db;
+	cfs_class->content_info_from_db = content_info_from_db;
 
 	cfs_class->info_set_user_flag = info_set_user_flag;
 }
@@ -131,21 +151,55 @@
 camel_imap_summary_new (struct _CamelFolder *folder, const char *filename)
 {
 	CamelFolderSummary *summary = CAMEL_FOLDER_SUMMARY (camel_object_new (camel_imap_summary_get_type ()));
+	CamelException ex;
+	camel_exception_init (&ex);
 
 	summary->folder = folder;
 
 	camel_folder_summary_set_build_content (summary, TRUE);
-	camel_folder_summary_set_filename (summary, filename);
 
-	if (camel_folder_summary_load (summary) == -1) {
-		camel_folder_summary_clear (summary);
-		camel_folder_summary_touch (summary);
+	if (camel_folder_summary_load_from_db (summary, &ex) == -1) {
+		/* 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);
+		g_warning ("Unable to load summary %s\n", camel_exception_get_description (&ex));
+		camel_exception_clear (&ex);
 	}
 
+	g_ptr_array_sort (summary->uids, (GCompareFunc) uid_compare); 
 	return summary;
 }
 
 static int
+summary_header_from_db (CamelFolderSummary *s, CamelFIRecord *mir)
+{
+	CamelImapSummary *ims = CAMEL_IMAP_SUMMARY (s);
+	char *part;
+
+	if (camel_imap_summary_parent->summary_header_from_db (s, mir) == -1)
+		return -1;
+
+	part = mir->bdata;
+
+	if (part) {
+		EXTRACT_FIRST_DIGIT (ims->version)
+	}
+	
+	if (part) {
+		EXTRACT_DIGIT (ims->validity)
+	}
+	
+	if (ims->version > CAMEL_IMAP_SUMMARY_VERSION) {
+		g_warning("Unkown summary version\n");
+		errno = EINVAL;
+		return -1;
+	}
+
+	return 0;
+}
+
+static int
 summary_header_load (CamelFolderSummary *s, FILE *in)
 {
 	CamelImapSummary *ims = CAMEL_IMAP_SUMMARY (s);
@@ -181,6 +235,20 @@
 	return 0;
 }
 
+static CamelFIRecord *
+summary_header_to_db (CamelFolderSummary *s, CamelException *ex)
+{
+	CamelImapSummary *ims = CAMEL_IMAP_SUMMARY(s);
+	struct _CamelFIRecord *fir;
+	
+	fir = camel_imap_summary_parent->summary_header_to_db (s, ex);
+	if (!fir)
+		return NULL;
+	fir->bdata = g_strdup_printf ("%d %u", CAMEL_IMAP_SUMMARY_VERSION, ims->validity);
+
+	return fir;
+}
+
 static int
 summary_header_save (CamelFolderSummary *s, FILE *out)
 {
@@ -195,6 +263,22 @@
 }
 
 static CamelMessageInfo *
+message_info_from_db (CamelFolderSummary *s, CamelMIRecord *mir)
+{
+	CamelMessageInfo *info;
+	CamelImapMessageInfo *iinfo;
+
+	info = camel_imap_summary_parent->message_info_from_db (s, mir);
+	if (info) {
+		char *part = g_strdup (mir->bdata);
+		iinfo = (CamelImapMessageInfo *)info;
+		EXTRACT_FIRST_DIGIT (iinfo->server_flags)
+	}
+
+	return info;
+}
+
+static CamelMessageInfo *
 message_info_load (CamelFolderSummary *s, FILE *in)
 {
 	CamelMessageInfo *info;
@@ -214,6 +298,19 @@
 	return NULL;
 }
 
+static CamelMIRecord *
+message_info_to_db (CamelFolderSummary *s, CamelMessageInfo *info)
+{
+	CamelImapMessageInfo *iinfo = (CamelImapMessageInfo *)info;
+	struct _CamelMIRecord *mir;
+
+	mir = camel_imap_summary_parent->message_info_to_db (s, info);
+	if (mir) 
+		mir->bdata = g_strdup_printf ("%u", iinfo->server_flags);
+
+	return mir;
+}
+
 static int
 message_info_save (CamelFolderSummary *s, FILE *out, CamelMessageInfo *info)
 {
@@ -240,6 +337,22 @@
 }
 
 static CamelMessageContentInfo *
+content_info_from_db (CamelFolderSummary *s, CamelMIRecord *mir)
+{
+	char *part = mir->cinfo;
+	guint32 type=0;
+	
+	if (part) {
+		EXTRACT_FIRST_DIGIT (type);
+	}
+	mir->cinfo = part;
+	if (type)
+		return camel_imap_summary_parent->content_info_from_db (s, mir);
+	else
+		return camel_folder_summary_content_info_new (s);
+}
+
+static CamelMessageContentInfo *
 content_info_load (CamelFolderSummary *s, FILE *in)
 {
 	if (fgetc (in))
@@ -249,6 +362,18 @@
 }
 
 static int
+content_info_to_db (CamelFolderSummary *s, CamelMessageContentInfo *info, CamelMIRecord *mir)
+{
+	if (info->type) {
+		mir->cinfo = g_strdup ("1");
+		return camel_imap_summary_parent->content_info_to_db (s, info, mir);
+	} else {
+		mir->cinfo = g_strdup ("0");
+		return 0;
+	}
+}
+
+static int
 content_info_save (CamelFolderSummary *s, FILE *out,
 		   CamelMessageContentInfo *info)
 {
@@ -286,7 +411,7 @@
 	}
 
 	mi->info.size = camel_message_info_size(info);
-	mi->info.uid = g_strdup (uid);
+	mi->info.uid = camel_pstring_strdup (uid);
 
 	camel_folder_summary_add (summary, (CamelMessageInfo *)mi);
 }
@@ -298,7 +423,25 @@
 	CamelImapMessageInfo *mi;
 
 	mi = camel_message_info_clone(info);
-	mi->info.uid = g_strdup(uid);
+	mi->info.uid = camel_pstring_strdup(uid);
 
 	camel_folder_summary_add (summary, (CamelMessageInfo *)mi);
 }
+
+
+static int
+uid_compare (const void *va, const void *vb)
+{
+	const char **sa = (const char **)va, **sb = (const char **)vb;
+	unsigned long 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;
+}
+

Modified: trunk/camel/providers/imap/camel-imap-utils.c
==============================================================================
--- trunk/camel/providers/imap/camel-imap-utils.c	(original)
+++ trunk/camel/providers/imap/camel-imap-utils.c	Wed Jul 16 11:38:32 2008
@@ -1179,10 +1179,12 @@
 {
 	CamelMessageInfo *info;
 	unsigned long uid;
-	
-	info = camel_folder_summary_index (summary, index);
-	uid = strtoul (camel_message_info_uid (info), NULL, 10);
-	camel_message_info_free(info);
+	char *suid;
+
+	suid = camel_folder_summary_uid_from_index (summary, index);
+	uid = strtoul (suid, NULL, 10);
+	g_free (suid);
+
 	return uid;
 }
 

Modified: trunk/camel/providers/local/camel-local-folder.c
==============================================================================
--- trunk/camel/providers/local/camel-local-folder.c	(original)
+++ trunk/camel/providers/local/camel-local-folder.c	Wed Jul 16 11:38:32 2008
@@ -289,6 +289,14 @@
 	folder->summary = (CamelFolderSummary *)CLOCALF_CLASS(lf)->create_summary(lf, lf->summary_path, lf->folder_path, lf->index);
 	if (camel_local_summary_load((CamelLocalSummary *)folder->summary, forceindex, NULL) == -1) {
 		/* ? */
+		if (camel_local_summary_check((CamelLocalSummary *)folder->summary, lf->changes, ex) == 0) {
+			/* we sync here so that any hard work setting up the folder isn't lost */
+			if (camel_local_summary_sync((CamelLocalSummary *)folder->summary, FALSE, lf->changes, ex) == -1) {
+				camel_object_unref (CAMEL_OBJECT (folder));
+				g_free(name);
+				return NULL;
+			}		
+		}
 	}
 
 	/* We don't need to sync here ..., it can sync later on when it calls refresh info */

Modified: trunk/camel/providers/local/camel-local-store.c
==============================================================================
--- trunk/camel/providers/local/camel-local-store.c	(original)
+++ trunk/camel/providers/local/camel-local-store.c	Wed Jul 16 11:38:32 2008
@@ -100,6 +100,18 @@
 {
 	if (local_store->toplevel_dir)
 		g_free (local_store->toplevel_dir);
+
+	CamelStore *store;
+
+	store = ((CamelStore *)local_store); 
+	d(printf ("\n\aLocal Store Finalize \n\a"));
+
+	if (store && store->cdb) {
+	d(printf ("\n\aClosing Store DB for hte local provider \n\a"));
+		camel_db_close (store->cdb);
+		store->cdb = NULL;
+	}
+
 }
 
 CamelType

Modified: trunk/camel/providers/local/camel-local-summary.c
==============================================================================
--- trunk/camel/providers/local/camel-local-summary.c	(original)
+++ trunk/camel/providers/local/camel-local-summary.c	Wed Jul 16 11:38:32 2008
@@ -46,6 +46,11 @@
 
 #define CAMEL_LOCAL_SUMMARY_VERSION (1)
 
+#define EXTRACT_FIRST_DIGIT(val) val=strtoul (part, &part, 10);
+
+static CamelFIRecord * summary_header_to_db (CamelFolderSummary *, CamelException *ex);
+static int summary_header_from_db (CamelFolderSummary *, CamelFIRecord *);
+
 static int summary_header_load (CamelFolderSummary *, FILE *);
 static int summary_header_save (CamelFolderSummary *, FILE *);
 
@@ -91,7 +96,10 @@
 
 	sklass->summary_header_load = summary_header_load;
 	sklass->summary_header_save = summary_header_save;
-
+	
+	sklass->summary_header_from_db = summary_header_from_db;
+	sklass->summary_header_to_db = summary_header_to_db;
+	
 	sklass->message_info_new_from_header  = message_info_new_from_header;
 
 	klass->load = local_summary_load;
@@ -140,20 +148,17 @@
 static int
 local_summary_load(CamelLocalSummary *cls, int forceindex, CamelException *ex)
 {
-	return camel_folder_summary_load((CamelFolderSummary *)cls);
+	d(g_print ("\nlocal_summary_load called \n"));
+	return camel_folder_summary_load_from_db ((CamelFolderSummary *)cls, ex);
 }
 
 /* load/check the summary */
 int
 camel_local_summary_load(CamelLocalSummary *cls, int forceindex, CamelException *ex)
 {
-	struct stat st;
-	CamelFolderSummary *s = (CamelFolderSummary *)cls;
-
 	d(printf("Loading summary ...\n"));
 
 	if (forceindex
-	    || g_stat(s->summary_path, &st) == -1
 	    || ((CamelLocalSummaryClass *)(CAMEL_OBJECT_GET_CLASS(cls)))->load(cls, forceindex, ex) == -1) {
 		w(g_warning("Could not load summary: flags may be reset"));
 		camel_folder_summary_clear((CamelFolderSummary *)cls);
@@ -403,13 +408,10 @@
 {
 	int ret = 0;
 
-	ret = camel_folder_summary_save((CamelFolderSummary *)cls);
+	ret = camel_folder_summary_save_to_db ((CamelFolderSummary *)cls, ex);
 	if (ret == -1) {
-		camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
-				      _("Could not save summary: %s: %s"),
-				      cls->folder_path, g_strerror (errno));
-		
-		g_warning ("Could not save summary for %s: %s", cls->folder_path, strerror (errno));
+		g_warning ("Could not save summary for local providers");
+		return -1;
 	}
 
 	if (cls->index && camel_index_sync(cls->index) == -1)
@@ -428,7 +430,7 @@
 	
 	mi = (CamelLocalMessageInfo *)camel_folder_summary_add_from_message((CamelFolderSummary *)cls, msg);
 	if (mi) {
-		d(printf("Added, uid = %s\n", mi->uid));
+		//d(printf("Added, uid = %s\n", mi->uid));
 		if (info) {
 			const CamelTag *tag = camel_message_info_user_tags(info);
 			const CamelFlag *flag = camel_message_info_user_flags(info);
@@ -583,12 +585,34 @@
 		camel_header_param_list_free(params);
 	}
 
-	mi->info.uid = g_strdup(uidstr);
+	mi->info.uid = camel_pstring_strdup(uidstr);
 	mi->info.flags = flags;
 
 	return 0;
 }
 
+
+static int 
+summary_header_from_db (CamelFolderSummary *s, CamelFIRecord *fir)
+{
+	CamelLocalSummary *cls = (CamelLocalSummary *)s;
+	char *part;
+
+	/* We dont actually add our own headers, but version that we don't anyway */
+
+	if (((CamelFolderSummaryClass *)camel_local_summary_parent)->summary_header_from_db(s, fir) == -1)
+		return -1;
+
+	part = fir->bdata;
+	if (part) {
+		EXTRACT_FIRST_DIGIT (cls->version)
+	}
+	fir->bdata = part;
+
+	return 0;
+}
+
+
 static int
 summary_header_load(CamelFolderSummary *s, FILE *in)
 {
@@ -607,6 +631,18 @@
 	return camel_file_util_decode_fixed_int32(in, &cls->version);
 }
 
+static struct _CamelFIRecord * 
+summary_header_to_db (CamelFolderSummary *s, CamelException *ex)
+{
+	struct _CamelFIRecord *fir;
+	
+	fir = ((CamelFolderSummaryClass *)camel_local_summary_parent)->summary_header_to_db (s, ex);
+	if (fir)
+		fir->bdata = g_strdup_printf ("%d", CAMEL_LOCAL_SUMMARY_VERSION);
+	
+	return fir;
+}
+ 
 static int
 summary_header_save(CamelFolderSummary *s, FILE *out)
 {
@@ -633,8 +669,8 @@
 		if (xev==NULL || camel_local_summary_decode_x_evolution(cls, xev, mi) == -1) {
 			/* to indicate it has no xev header */
 			mi->info.flags |= CAMEL_MESSAGE_FOLDER_FLAGGED | CAMEL_MESSAGE_FOLDER_NOXEV;
-			g_free (mi->info.uid);
-			mi->info.uid = camel_folder_summary_next_uid_string(s);
+			camel_pstring_free (mi->info.uid);
+			mi->info.uid = camel_pstring_add (camel_folder_summary_next_uid_string(s), TRUE);
 
 			/* shortcut, no need to look it up in the index library */
 			doindex = TRUE;

Modified: trunk/camel/providers/local/camel-maildir-summary.c
==============================================================================
--- trunk/camel/providers/local/camel-maildir-summary.c	(original)
+++ trunk/camel/providers/local/camel-maildir-summary.c	Wed Jul 16 11:38:32 2008
@@ -726,7 +726,8 @@
 
 	/* sort the summary based on receive time, since the directory order is not useful */
 	CAMEL_SUMMARY_LOCK(s, summary_lock);
-	qsort(s->messages->pdata, s->messages->len, sizeof(CamelMessageInfo *), sort_receive_cmp);
+	#warning Add support for sorting via the DB.
+/* 	qsort(s->messages->pdata, s->messages->len, sizeof(CamelMessageInfo *), sort_receive_cmp); */
 	CAMEL_SUMMARY_UNLOCK(s, summary_lock);
 
 	g_mutex_unlock (((CamelMaildirSummary *) cls)->priv->summary_lock);

Modified: trunk/camel/providers/local/camel-mbox-store.c
==============================================================================
--- trunk/camel/providers/local/camel-mbox-store.c	(original)
+++ trunk/camel/providers/local/camel-mbox-store.c	Wed Jul 16 11:38:32 2008
@@ -101,7 +101,7 @@
 }
 
 static char *extensions[] = {
-	".msf", ".ev-summary", ".ev-summary-meta", ".ibex.index", ".ibex.index.data", ".cmeta", ".lock"
+	".msf", ".ev-summary", ".ev-summary-meta", ".ibex.index", ".ibex.index.data", ".cmeta", ".lock", ".db"
 };
 
 static gboolean
@@ -638,7 +638,8 @@
 		folderpath = camel_local_store_get_full_path(store, fi->full_name);
 		
 		mbs = (CamelMboxSummary *)camel_mbox_summary_new(NULL, path, folderpath, NULL);
-		if (camel_folder_summary_header_load((CamelFolderSummary *)mbs) != -1) {
+		#warning "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;
 		}

Modified: trunk/camel/providers/local/camel-mbox-summary.c
==============================================================================
--- trunk/camel/providers/local/camel-mbox-summary.c	(original)
+++ trunk/camel/providers/local/camel-mbox-summary.c	Wed Jul 16 11:38:32 2008
@@ -42,6 +42,9 @@
 #include "camel-private.h"
 
 #include "camel-mbox-summary.h"
+#include "camel-string-utils.h"
+#include "camel-store.h"
+#include "camel-folder.h"
 
 #define io(x)
 #define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/
@@ -49,6 +52,15 @@
 
 #define CAMEL_MBOX_SUMMARY_VERSION (1)
 
+#define EXTRACT_DIGIT(val) part++; val=strtoul (part, &part, 10);
+#define EXTRACT_FIRST_DIGIT(val) val=strtoul (part, &part, 10);
+ 
+static CamelFIRecord * summary_header_to_db (CamelFolderSummary *, CamelException *ex);
+static int 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);
+
+
 static int summary_header_load (CamelFolderSummary *, FILE *);
 static int summary_header_save (CamelFolderSummary *, FILE *);
 
@@ -154,6 +166,11 @@
 	sklass->summary_header_load = summary_header_load;
 	sklass->summary_header_save = summary_header_save;
 
+	sklass->summary_header_from_db = summary_header_from_db;
+	sklass->summary_header_to_db = summary_header_to_db;
+	sklass->message_info_from_db = message_info_from_db;
+	sklass->message_info_to_db = message_info_to_db;
+	
 	sklass->message_info_new_from_header  = message_info_new_from_header;
 	sklass->message_info_new_from_parser = message_info_new_from_parser;
 	sklass->message_info_load = message_info_load;
@@ -238,6 +255,24 @@
 	}
 }
 
+static int 
+summary_header_from_db (CamelFolderSummary *s, struct _CamelFIRecord *fir)
+{
+	CamelMboxSummary *mbs = CAMEL_MBOX_SUMMARY(s);
+	char *part;
+
+	((CamelFolderSummaryClass *)camel_mbox_summary_parent)->summary_header_from_db(s, fir);
+
+	part = fir->bdata;
+	if (part) {
+		EXTRACT_DIGIT(mbs->version)
+		EXTRACT_DIGIT(mbs->folder_size)
+	}
+	
+	return 0;
+}
+
+
 static int
 summary_header_load(CamelFolderSummary *s, FILE *in)
 {
@@ -258,6 +293,23 @@
 	return 0;
 }
 
+static CamelFIRecord * 
+summary_header_to_db (CamelFolderSummary *s, CamelException *ex)
+{
+	CamelMboxSummary *mbs = CAMEL_MBOX_SUMMARY(s);
+	struct _CamelFIRecord *fir;
+	char *tmp;
+
+	fir = ((CamelFolderSummaryClass *)camel_mbox_summary_parent)->summary_header_to_db (s, ex);
+	if (fir) {
+		tmp = fir->bdata;
+		fir->bdata = g_strdup_printf ("%s %d %d", tmp ? tmp : "", CAMEL_MBOX_SUMMARY_VERSION, mbs->folder_size);
+		g_free (tmp);
+	}
+	
+	return fir;
+}
+
 static int
 summary_header_save(CamelFolderSummary *s, FILE *out)
 {
@@ -324,8 +376,8 @@
 
 		if (add&1) {
 			mi->info.info.flags |= CAMEL_MESSAGE_FOLDER_FLAGGED | CAMEL_MESSAGE_FOLDER_NOXEV;
-			g_free (mi->info.info.uid);
-			mi->info.info.uid = camel_folder_summary_next_uid_string(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));
 		}
@@ -366,6 +418,25 @@
 	return mi;
 }
 
+static CamelMessageInfo * 
+message_info_from_db(CamelFolderSummary *s, struct _CamelMIRecord *mir)
+{
+	CamelMessageInfo *mi;
+	char *part;
+
+	mi = ((CamelFolderSummaryClass *)camel_mbox_summary_parent)->message_info_from_db(s, mir);
+
+	if (mi) {
+		CamelMboxMessageInfo *mbi = (CamelMboxMessageInfo *)mi;
+		part = mir->bdata;
+		if (part) {
+			EXTRACT_FIRST_DIGIT (mbi->frompos)
+		}
+	}
+
+	return mi;
+}
+
 static CamelMessageInfo *
 message_info_load(CamelFolderSummary *s, FILE *in)
 {
@@ -401,6 +472,19 @@
 	return 0;
 }
 
+static struct _CamelMIRecord * 
+message_info_to_db(CamelFolderSummary *s, CamelMessageInfo *info)
+{
+	CamelMboxMessageInfo *mbi = (CamelMboxMessageInfo *)info;
+	struct _CamelMIRecord *mir;
+
+	mir = ((CamelFolderSummaryClass *)camel_mbox_summary_parent)->message_info_to_db(s, info);
+	mir->bdata = g_strdup_printf("%lu", mbi->frompos);
+
+	return mir;
+}
+
+
 static int
 message_info_save(CamelFolderSummary *s, FILE *out, CamelMessageInfo *mi)
 {
@@ -575,7 +659,7 @@
 				ret = summary_update(cls, mbs->folder_size, changes, ex);
 			} else {
 				d(printf("folder shrank!  rebuilding from start\n"));
-				ret = summary_update(cls, 0, changes, ex);
+				 ret = summary_update(cls, 0, changes, ex);
 			}
 		} else {
 			d(printf("Folder unchanged, do nothing\n"));
@@ -698,7 +782,7 @@
 	const char *xev;
 	int len;
 	off_t lastpos;
-
+	GPtrArray *summary = NULL;
 	int mbox_file_is_corrupt = 0;
 
 	d(printf("Performing quick summary sync\n"));
@@ -730,16 +814,15 @@
 	camel_mime_parser_scan_pre_from(mp, TRUE);
 	camel_mime_parser_init_with_fd(mp, pfd);
 
-	count = camel_folder_summary_count(s);
-	for (i = 0; i < count; i++) {
+	/* Sync only the changes */
+	summary = camel_folder_summary_get_changed ((CamelFolderSummary *)mbs);
+	for (i = 0; i < summary->len; i++) {
 		int xevoffset;
-		int pc = (i+1)*100/count;
+		int pc = (i+1)*100/summary->len;
 
 		camel_operation_progress(NULL, pc);
 
-		info = (CamelMboxMessageInfo *)camel_folder_summary_index(s, i);
-
-		g_assert(info);
+		info = (CamelMboxMessageInfo *)camel_folder_summary_uid(s, summary->pdata[i]);
 
 		d(printf("Checking message %s %08x\n", camel_message_info_uid(info), info->info.flags));
 
@@ -862,12 +945,16 @@
 		goto error;
 	}
 
+	g_ptr_array_foreach (summary, camel_pstring_free, NULL);
+	g_ptr_array_free (summary, TRUE);
 	camel_object_unref((CamelObject *)mp);
 
 	camel_operation_end(NULL);
 	
 	return 0;
  error:
+	g_ptr_array_foreach (summary, camel_pstring_free, NULL);
+	g_ptr_array_free (summary, TRUE);	
 	if (fd != -1)
 		close(fd);
 	if (mp)
@@ -889,28 +976,41 @@
 	int i, count;
 	int quick = TRUE, work=FALSE;
 	int ret;
-
+	GPtrArray *summary = NULL;
+	
 	/* first, sync ourselves up, just to make sure */
 	if (camel_local_summary_check(cls, changeinfo, ex) == -1)
 		return -1;
 
-	count = camel_folder_summary_count(s);
-	if (count == 0)
-		return 0;
+	/* Sync only the changes */
 
-	/* check what work we have to do, if any */
-	for (i=0;quick && i<count; i++) {
-		CamelMboxMessageInfo *info = (CamelMboxMessageInfo *)camel_folder_summary_index(s, i);
 
-		g_assert(info);
+	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]);
+		
 		if ((expunge && (info->info.info.flags & CAMEL_MESSAGE_DELETED)) ||
 		    (info->info.info.flags & (CAMEL_MESSAGE_FOLDER_NOXEV|CAMEL_MESSAGE_FOLDER_XEVCHANGE)))
 			quick = FALSE;
 		else
 			work |= (info->info.info.flags & CAMEL_MESSAGE_FOLDER_FLAGGED) != 0;
-		camel_message_info_free(info);
+		camel_message_info_free(info);		
 	}
 
+	g_ptr_array_foreach (summary, camel_pstring_free, NULL);
+	g_ptr_array_free (summary, TRUE);
+	
+	if (quick && expunge) {
+		int dcount =0;
+
+	
+		if (camel_db_count_deleted_message_info (s->folder->cdb, s->folder->full_name, &dcount, ex) == -1)
+			return -1;
+		if (dcount)
+			quick = FALSE;
+	}
+	
+
 	/* yuck i hate this logic, but its to simplify the 'all ok, update summary' and failover cases */
 	ret = -1;
 	if (quick) {

Modified: trunk/camel/providers/local/camel-mh-summary.c
==============================================================================
--- trunk/camel/providers/local/camel-mh-summary.c	(original)
+++ trunk/camel/providers/local/camel-mh-summary.c	Wed Jul 16 11:38:32 2008
@@ -294,7 +294,10 @@
 
 	/* sort the summary based on message number (uid), since the directory order is not useful */
 	CAMEL_SUMMARY_LOCK(s, summary_lock);
-	qsort(s->messages->pdata, s->messages->len, sizeof(CamelMessageInfo *), sort_uid_cmp);
+/* 	qsort(s->uids->pdata, s->uids->len, sizeof(CamelMessageInfo *), sort_uid_cmp); */
+	#warning "verify if strcmp works the same as the other one. Too busy to check this."
+    #warning "lets build a sort support for uid fetching from the db"
+	qsort(s->uids->pdata, s->uids->len, sizeof(CamelMessageInfo *), strcmp);	
 	CAMEL_SUMMARY_UNLOCK(s, summary_lock);
 
 	return 0;

Modified: trunk/camel/providers/nntp/camel-nntp-folder.c
==============================================================================
--- trunk/camel/providers/nntp/camel-nntp-folder.c	(original)
+++ trunk/camel/providers/nntp/camel-nntp-folder.c	Wed Jul 16 11:38:32 2008
@@ -105,7 +105,7 @@
 nntp_folder_sync_online (CamelFolder *folder, CamelException *ex)
 {
 	CAMEL_SERVICE_REC_LOCK(folder->parent_store, connect_lock);
-	camel_folder_summary_save (folder->summary);
+	camel_folder_summary_save_to_db (folder->summary, ex);
 	CAMEL_SERVICE_REC_UNLOCK(folder->parent_store, connect_lock);
 }
 
@@ -113,7 +113,7 @@
 nntp_folder_sync_offline (CamelFolder *folder, CamelException *ex)
 {
 	CAMEL_SERVICE_REC_LOCK(folder->parent_store, connect_lock);
-	camel_folder_summary_save (folder->summary);
+	camel_folder_summary_save_to_db (folder->summary, ex);
 	CAMEL_SERVICE_REC_UNLOCK(folder->parent_store, connect_lock);
 }
 
@@ -419,8 +419,12 @@
 nntp_folder_finalise (CamelNNTPFolder *nntp_folder)
 {
 	struct _CamelNNTPFolderPrivate *p;
+
+	CamelException ex;
+
+	camel_exception_init (&ex);
 	
-	camel_folder_summary_save (((CamelFolder*) nntp_folder)->summary);
+	camel_folder_summary_save_to_db (((CamelFolder*) nntp_folder)->summary, &ex);
 	
 	p = nntp_folder->priv;
 	g_mutex_free (p->search_lock);
@@ -512,7 +516,8 @@
 	root = g_strdup_printf("%s.ev-summary", nntp_folder->storage_path);
 	folder->summary = (CamelFolderSummary *) camel_nntp_summary_new (folder, root);
 	g_free(root);
-	camel_folder_summary_load (folder->summary);
+
+	camel_folder_summary_load_from_db (folder->summary, ex);
 	
 	si = camel_store_summary_path ((CamelStoreSummary *) ((CamelNNTPStore*) parent)->summary, folder_name);
 	if (si) {

Modified: trunk/camel/providers/nntp/camel-nntp-summary.c
==============================================================================
--- trunk/camel/providers/nntp/camel-nntp-summary.c	(original)
+++ trunk/camel/providers/nntp/camel-nntp-summary.c	Wed Jul 16 11:38:32 2008
@@ -51,6 +51,9 @@
 
 #define CAMEL_NNTP_SUMMARY_VERSION (1)
 
+#define EXTRACT_FIRST_DIGIT(val) val=strtoul (part, &part, 10);
+#define EXTRACT_DIGIT(val) part++; val=strtoul (part, &part, 10);
+
 struct _CamelNNTPSummaryPrivate {
 	char *uid;
 
@@ -63,6 +66,8 @@
 static CamelMessageInfo * message_info_new_from_header (CamelFolderSummary *, struct _camel_header_raw *);
 static int summary_header_load(CamelFolderSummary *, FILE *);
 static int summary_header_save(CamelFolderSummary *, FILE *);
+static int summary_header_from_db (CamelFolderSummary *s, CamelFIRecord *mir);
+static CamelFIRecord * summary_header_to_db (CamelFolderSummary *s, CamelException *ex);
 
 static void camel_nntp_summary_class_init (CamelNNTPSummaryClass *klass);
 static void camel_nntp_summary_init       (CamelNNTPSummary *obj);
@@ -97,6 +102,8 @@
 	sklass->message_info_new_from_header  = message_info_new_from_header;
 	sklass->summary_header_load = summary_header_load;
 	sklass->summary_header_save = summary_header_save;
+	sklass->summary_header_from_db = summary_header_from_db;
+	sklass->summary_header_to_db = summary_header_to_db;
 }
 
 static void
@@ -160,6 +167,33 @@
 }
 
 static int
+summary_header_from_db (CamelFolderSummary *s, CamelFIRecord *mir)
+{
+	CamelNNTPSummary *cns = CAMEL_NNTP_SUMMARY(s);
+	char *part;
+
+	
+	if (camel_nntp_summary_parent->summary_header_from_db (s, mir) == -1)
+		return -1;
+
+	part = mir->bdata;
+
+	if (part) {
+		EXTRACT_FIRST_DIGIT (cns->version)
+	}
+	
+	if (part) {
+		EXTRACT_DIGIT (cns->high)
+	}
+
+	if (part) {
+		EXTRACT_DIGIT (cns->low)
+	}
+
+	return 0;
+}
+
+static int
 summary_header_load(CamelFolderSummary *s, FILE *in)
 {
 	CamelNNTPSummary *cns = CAMEL_NNTP_SUMMARY(s);
@@ -189,6 +223,21 @@
 	return 0;
 }
 
+
+static CamelFIRecord *
+summary_header_to_db (CamelFolderSummary *s, CamelException *ex)
+{
+	CamelNNTPSummary *cns = CAMEL_NNTP_SUMMARY(s);
+	struct _CamelFIRecord *fir;
+	
+	fir = camel_nntp_summary_parent->summary_header_to_db (s, ex);
+	if (!fir)
+		return NULL;
+	fir->bdata = g_strdup_printf ("%d %d %d", CAMEL_NNTP_SUMMARY_VERSION, cns->high, cns->low);
+
+	return fir;
+}
+
 static int
 summary_header_save(CamelFolderSummary *s, FILE *out)
 {
@@ -427,28 +476,24 @@
 	if (cns->low != f) {
 		count = camel_folder_summary_count(s);
 		for (i = 0; i < count; i++) {
-			CamelMessageInfo *mi = camel_folder_summary_index(s, i);
+			const char *uid;
+			const char *msgid;
 
-			if (mi) {
-				const char *uid = camel_message_info_uid(mi);
-				const char *msgid;
+			uid  = camel_folder_summary_uid_from_index(s, i);
+			n = strtoul(uid, NULL, 10);
 
-				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);
-					camel_folder_summary_remove(s, mi);
-					count--;
-					i--;
-				}
-				
-				camel_message_info_free(mi);
+			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);
+				camel_folder_summary_remove_uid (s, uid);
+				count--;
+				i--;
 			}
 		}
 		cns->low = f;
@@ -467,7 +512,7 @@
 
 	/* TODO: not from here */
 	camel_folder_summary_touch(s);
-	camel_folder_summary_save(s);
+	camel_folder_summary_save_to_db (s, ex);
 update:
 	/* update store summary if we have it */
 	if (folder

Modified: trunk/camel/providers/nntp/camel-nntp-utils.c
==============================================================================
--- trunk/camel/providers/nntp/camel-nntp-utils.c	(original)
+++ trunk/camel/providers/nntp/camel-nntp-utils.c	Wed Jul 16 11:38:32 2008
@@ -227,16 +227,10 @@
 {
 	char *tmp;
 	char *brk;
-	CamelMessageInfo *minfo;
 	int ret;
 	
-	minfo = camel_folder_summary_index(summary, index);
-	if(minfo == NULL)
-		return 0;
+	tmp = camel_folder_summary_uid_from_index(summary, index);
 
-	tmp = g_strdup(camel_message_info_uid(minfo));
-	camel_message_info_free(minfo);
-	
 	if((brk = strchr(tmp, ',')) == NULL)
 		ret = 0;
 	else {

Modified: trunk/configure.in
==============================================================================
--- trunk/configure.in	(original)
+++ trunk/configure.in	Wed Jul 16 11:38:32 2008
@@ -31,6 +31,7 @@
 m4_define([libxml_minimum_version], [2.0.0])            # XXX Just a Guess
 m4_define([libsoup_minimum_version], [2.3.0])
 m4_define([gnome_keyring_minimum_version], [2.20.1])
+m4_define([sqlite_minimum_version], [3.5])
 
 dnl *************************************************************************************************
 dnl Base Version
@@ -238,7 +239,8 @@
          libglade-2.0 >= libglade_minimum_version
          libgnome-2.0 >= libgnome_minimum_version
          libxml-2.0 >= libxml_minimum_version
-         libsoup-2.4 >= libsoup_minimum_version])
+         libsoup-2.4 >= libsoup_minimum_version
+		 sqlite3 >= sqlite_minimum_version])
 
 dnl **************************************************
 dnl * regex checking
@@ -1443,7 +1445,7 @@
 
 dnl --- libedataserver, libedataserverui, libebackend flags
 
-E_DATA_SERVER_DEPS="libxml-2.0 libbonobo-2.0 libsoup-2.4 gconf-2.0 $mozilla_nspr"
+E_DATA_SERVER_DEPS="libxml-2.0 libbonobo-2.0 libsoup-2.4 gconf-2.0 $mozilla_nspr sqlite3"
 
 EVO_SET_COMPILE_FLAGS(E_DATA_SERVER, $E_DATA_SERVER_DEPS, $THREADS_CFLAGS $MANUAL_NSPR_CFLAGS, $THREADS_LIBS $MANUAL_NSPR_LIBS)
 AC_SUBST(E_DATA_SERVER_CFLAGS)
@@ -1495,6 +1497,8 @@
 AC_SUBST(SOUP_LIBS)
 
 dnl --- Camel flags
+SQLITE_REQUIRED=sqlite_minimum_version
+AC_SUBST(SQLITE_REQUIRED)
 
 zlib_found=false
 dnl deflateInit is a #define, use deflateEnd instead

Modified: trunk/libedataserver/e-sexp.c
==============================================================================
--- trunk/libedataserver/e-sexp.c	(original)
+++ trunk/libedataserver/e-sexp.c	Wed Jul 16 11:38:32 2008
@@ -251,6 +251,9 @@
 
 	r = e_sexp_result_new(f, ESEXP_RES_UNDEFINED);
 
+	char *oper = "AND";
+	f->operators = g_slist_prepend (f->operators, oper);
+
 	for (i=0;bool && i<argc;i++) {
 		r1 = e_sexp_term_eval(f, argv[i]);
 		if (type == -1)
@@ -291,6 +294,7 @@
 	}
 
 	g_hash_table_destroy(ht);
+	f->operators = g_slist_remove (f->operators, oper);
 
 	return r;
 }
@@ -307,6 +311,9 @@
 
 	r(printf("(or \n"));
 
+	char *oper = "OR";
+	f->operators = g_slist_prepend (f->operators, oper);
+
 	r = e_sexp_result_new(f, ESEXP_RES_UNDEFINED);
 
 	for (i=0;!bool && i<argc;i++) {
@@ -345,6 +352,7 @@
 	}
 	g_hash_table_destroy(ht);
 
+	f->operators = g_slist_remove (f->operators, oper);
 	return r;
 }
 
@@ -887,6 +895,12 @@
 	return terms;
 }
 
+ESExpTerm * e_sexp_parse_value (ESExp *f) 
+{
+	return parse_value (f);
+}
+
+
 static struct _ESExpTerm *
 parse_value(ESExp *f)
 {

Modified: trunk/libedataserver/e-sexp.h
==============================================================================
--- trunk/libedataserver/e-sexp.h	(original)
+++ trunk/libedataserver/e-sexp.h	Wed Jul 16 11:38:32 2008
@@ -117,6 +117,7 @@
 	/* private stuff */
 	jmp_buf failenv;
 	char *error;
+	GSList *operators;
 
 	/* TODO: may also need a pool allocator for term strings, so we dont lose them
 	   in error conditions? */
@@ -173,6 +174,8 @@
 /* return the error string */
 const char     *e_sexp_error		(struct _ESExp *f);
 
+ESExpTerm * e_sexp_parse_value(ESExp *f);
+
 G_END_DECLS
 
 #endif /* _E_SEXP_H */



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