File bnc-159934-eds-CPU-spikes.patch of Package evolution-data-server

--- ../temp/evolution-data-server/evolution-data-server-1.6.0/addressbook/backends/groupwise/e-book-backend-groupwise.c	2006-04-19 19:11:23.000000000 +0530
+++ addressbook/backends/groupwise/e-book-backend-groupwise.c	2006-04-19 13:13:06.000000000 +0530
@@ -22,13 +22,16 @@
  */
 
 #include <config.h>
-
+#include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/time.h>
 #include <time.h>
 #include <unistd.h>
+#include <errno.h>
+#include "db.h"
 
 #include <glib.h>
 #include <glib/gstdio.h>
@@ -36,12 +39,13 @@
 
 #include "libedataserver/e-sexp.h"
 #include "libedataserver/e-data-server-util.h"
+#include "libedataserver/e-db3-utils.h"
 #include "libedataserver/e-url.h" 
 #include "libebook/e-contact.h"
 #include "libedata-book/e-book-backend-sexp.h"
 #include "libedata-book/e-data-book.h"
 #include "libedata-book/e-data-book-view.h"
-#include "libedata-book/e-book-backend-cache.h"
+#include "libedata-book/e-book-backend-db-cache.h"
 #include "libedata-book/e-book-backend-summary.h"
 #include "e-book-backend-groupwise.h"
 
@@ -68,15 +72,21 @@ struct _EBookBackendGroupwisePrivate {
 	char *use_ssl;
 	int mode;
 	int cache_timeout;
-	EBookBackendCache *cache;
 	EBookBackendSummary *summary;
 	GMutex *update_mutex;
+	DB     *file_db;
+	DB_ENV *env;
 	/* for future use */
 	void *reserved1;
 	void *reserved2;
-	void *reserved3;
 };
 
+static GStaticMutex global_env_lock = G_STATIC_MUTEX_INIT;
+static struct {
+	int ref_count;
+	DB_ENV *env;
+} global_env;
+
 #define ELEMENT_TYPE_SIMPLE 0x01
 #define ELEMENT_TYPE_COMPLEX 0x02 /* fields which require explicit functions to set values into EContact and EGwItem */
 #define SUMMARY_FLUSH_TIMEOUT 5000
@@ -919,7 +929,7 @@ set_organization_in_gw_item (EGwItem *it
 			e_contact_set (contact, E_CONTACT_FULL_NAME, organization_name);
 			/* book uri is always set outside fill_contact_from_gw_item() */
 			e_contact_set (contact, E_CONTACT_BOOK_URI, egwb->priv->original_uri);
-			e_book_backend_cache_add_contact (egwb->priv->cache, contact);
+			e_book_backend_db_cache_add_contact (egwb->priv->file_db, contact);
 			e_book_backend_summary_add_contact (egwb->priv->summary, contact);
 			g_object_unref (contact);
 		}
@@ -1159,7 +1169,7 @@ e_book_backend_groupwise_create_contact 
 		if (status == E_GW_CONNECTION_STATUS_OK && id) {
 			e_contact_set (contact, E_CONTACT_UID, id);
 			g_free (id);
-			e_book_backend_cache_add_contact (egwb->priv->cache, contact);
+			e_book_backend_db_cache_add_contact (egwb->priv->file_db, contact);
 			e_book_backend_summary_add_contact (egwb->priv->summary, contact);
 			e_data_book_respond_create(book, opid, GNOME_Evolution_Addressbook_Success, contact);
 			
@@ -1210,7 +1220,7 @@ e_book_backend_groupwise_remove_contacts
 			id = (char*) id_list->data;
 			e_gw_connection_remove_item (ebgw->priv->cnc, ebgw->priv->container_id, id);
 			deleted_ids =  g_list_append (deleted_ids, id);
-			e_book_backend_cache_remove_contact (ebgw->priv->cache, id);
+			e_book_backend_db_cache_remove_contact (ebgw->priv->file_db, id);
 			e_book_backend_summary_remove_contact (ebgw->priv->summary, id);
 		}
 		e_data_book_respond_remove_contacts (book, opid,
@@ -1345,9 +1355,9 @@ e_book_backend_groupwise_modify_contact 
 		status = e_gw_connection_modify_item (egwb->priv->cnc, id, new_item);
 		if (status == E_GW_CONNECTION_STATUS_OK) {
 			e_data_book_respond_modify (book, opid, GNOME_Evolution_Addressbook_Success, contact);
-			e_book_backend_cache_remove_contact (egwb->priv->cache, id);
+			e_book_backend_db_cache_remove_contact (egwb->priv->file_db, id);
 			e_book_backend_summary_remove_contact (egwb->priv->summary, id);
-			e_book_backend_cache_add_contact (egwb->priv->cache, contact);
+			e_book_backend_db_cache_add_contact (egwb->priv->file_db, contact);
 			e_book_backend_summary_add_contact (egwb->priv->summary, contact);
 		}
 		else 
@@ -1381,7 +1391,7 @@ e_book_backend_groupwise_get_contact (EB
 	switch (gwb->priv->mode) {
 
 	case GNOME_Evolution_Addressbook_MODE_LOCAL :
-		contact = e_book_backend_cache_get_contact (gwb->priv->cache, id);
+		contact = e_book_backend_db_cache_get_contact (gwb->priv->file_db, id);
 		vcard =  e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
 		if (contact) {
 			e_data_book_respond_get_contact(book, opid, GNOME_Evolution_Addressbook_Success, vcard);
@@ -1836,14 +1846,14 @@ e_book_backend_groupwise_get_contact_lis
 				char *uid = g_ptr_array_index (ids, i);
 
 				EContact *contact = 
-					e_book_backend_cache_get_contact (egwb->priv->cache, uid);
+					e_book_backend_db_cache_get_contact (egwb->priv->file_db, uid);
 				contacts = g_list_append (contacts, contact);	
 				g_object_unref (contact);
 			}
 			g_ptr_array_free (ids, TRUE);
 		}
 		else
-			contacts = e_book_backend_cache_get_contacts (egwb->priv->cache, query);
+			contacts = e_book_backend_db_cache_get_contacts (egwb->priv->file_db, query);
 
 		temp = contacts;
 		for (; contacts != NULL; contacts = g_list_next(contacts)) { 
@@ -1882,7 +1892,7 @@ e_book_backend_groupwise_get_contact_lis
 					int i;
 					for (i = 0; i < ids->len; i ++) {
 						char *uid = g_ptr_array_index (ids, i);
-						contact = e_book_backend_cache_get_contact (egwb->priv->cache, uid);
+						contact = e_book_backend_db_cache_get_contact (egwb->priv->file_db, uid);
 						vcard_list = g_list_append (vcard_list,
                                                             e_vcard_to_string (E_VCARD (contact),
                                                             EVC_FORMAT_VCARD_30));
@@ -1893,7 +1903,7 @@ e_book_backend_groupwise_get_contact_lis
 				}
 			}
 			else {
-				ids = e_book_backend_cache_search (egwb->priv->cache, query);
+				ids = e_book_backend_db_cache_search (egwb->priv->file_db, query);
 			}
 
 			if (ids->len > 0) {
@@ -2001,7 +2011,7 @@ get_closure (EDataBookView *book_view)
 }
 
 static void
-get_contacts_from_cache (EBookBackendGroupwisePrivate *priv, 
+get_contacts_from_cache (EBookBackendGroupwise *ebgw, 
 			 const char *query,
 			 GPtrArray *ids,
 			 EDataBookView *book_view, 
@@ -2023,9 +2033,11 @@ get_contacts_from_cache (EBookBackendGro
 			break;	
 
 		EContact *contact = 
-			e_book_backend_cache_get_contact (priv->cache, uid);
-		e_data_book_view_notify_update (book_view, contact);
-		g_object_unref (contact);
+			e_book_backend_db_cache_get_contact (ebgw->priv->file_db, uid);
+		if (contact) {
+			e_data_book_view_notify_update (book_view, contact);
+			g_object_unref (contact);
+		}
 	}
 	if (!stopped)
 		e_data_book_view_notify_complete (book_view, 
@@ -2067,7 +2079,7 @@ book_view_thread (gpointer data)
 	switch (gwb->priv->mode) {
 
 	case GNOME_Evolution_Addressbook_MODE_LOCAL :
-		if (!gwb->priv->cache) {
+		if (!gwb->priv->file_db) {
 			e_data_book_view_notify_complete (book_view, GNOME_Evolution_Addressbook_Success);
 			return NULL;
 		}
@@ -2078,7 +2090,7 @@ book_view_thread (gpointer data)
 				printf ("reading the uids from summary \n");
 			ids = e_book_backend_summary_search (gwb->priv->summary, query);
 			if (ids && ids->len > 0) {
-				get_contacts_from_cache (gwb->priv, query, ids, book_view, closure);
+				get_contacts_from_cache (gwb, query, ids, book_view, closure);
 				g_ptr_array_free (ids, TRUE);
 			}
 			bonobo_object_unref (book_view);
@@ -2088,7 +2100,7 @@ book_view_thread (gpointer data)
 		/* fall back to cache */
 		if (enable_debug)
 			printf ("summary not found, reading the uids from cache\n");
-		contacts = e_book_backend_cache_get_contacts (gwb->priv->cache, query);
+		contacts = e_book_backend_db_cache_get_contacts (gwb->priv->file_db, query);
 		temp_list = contacts;
 		for (; contacts != NULL; contacts = g_list_next(contacts)) {
 			g_mutex_lock (closure->mutex);
@@ -2170,7 +2182,7 @@ book_view_thread (gpointer data)
 				if (!is_auto_completion)
 					e_data_book_view_notify_status_message (book_view, 
 										_("Searching..."));
-				get_contacts_from_cache (gwb->priv, query, ids, book_view, closure);
+				get_contacts_from_cache (gwb, query, ids, book_view, closure);
 				g_ptr_array_free (ids, TRUE);
 				bonobo_object_unref (book_view);
 				if (enable_debug) {
@@ -2330,11 +2342,11 @@ static EDataBookView *
 find_book_view (EBookBackendGroupwise *ebgw)
 {
 	EList *views = e_book_backend_get_book_views (E_BOOK_BACKEND (ebgw));
-       if (!views)
-               return NULL;
+	if (!views)
+		return NULL;
 	EIterator *iter = e_list_get_iterator (views);
 	EDataBookView *rv = NULL;
-	
+
 	if (!iter) {
 		g_object_unref (views);
 		return NULL;
@@ -2353,35 +2365,110 @@ find_book_view (EBookBackendGroupwise *e
 	return rv;
 }
 
+static void 
+get_sequence_from_cache (DB *db,
+		gdouble *cache_first_sequence,
+		gdouble *cache_last_sequence,
+		gdouble *cache_last_po_rebuild_time)
+{
+	DBT uid_dbt, vcard_dbt;
+	int db_error;
+
+	string_to_dbt ("firstSequence", &uid_dbt);
+	memset (&vcard_dbt, 0, sizeof(vcard_dbt));
+	vcard_dbt.flags = DB_DBT_MALLOC;
+
+	db_error = db->get (db, NULL, &uid_dbt, &vcard_dbt, 0);
+	if (db_error != 0) {
+		g_warning ("db->get failed with %d", db_error);
+	}
+	else {
+		*cache_first_sequence = strtod (g_strdup (vcard_dbt.data), NULL);
+		g_free (vcard_dbt.data);
+	}
+	
+	string_to_dbt ("lastSequence", &uid_dbt);
+	memset (&vcard_dbt, 0, sizeof(vcard_dbt));
+	vcard_dbt.flags = DB_DBT_MALLOC;
+
+	db_error = db->get (db, NULL, &uid_dbt, &vcard_dbt, 0);
+	if (db_error != 0) {
+		g_warning ("db->get failed with %d", db_error);
+	}
+	else {
+		*cache_last_sequence = strtod (g_strdup (vcard_dbt.data), NULL);
+		g_free (vcard_dbt.data);
+	}
+
+	string_to_dbt ("lastTimePORebuild", &uid_dbt);
+	memset (&vcard_dbt, 0, sizeof(vcard_dbt));
+	vcard_dbt.flags = DB_DBT_MALLOC;
+
+	db_error = db->get (db, NULL, &uid_dbt, &vcard_dbt, 0);
+	if (db_error != 0) {
+		g_warning ("db->get failed with %d", db_error);
+	}
+	else {
+		*cache_last_po_rebuild_time = strtod (g_strdup (vcard_dbt.data), NULL);
+		g_free (vcard_dbt.data);
+	}
+
+	if (enable_debug) {
+		printf("Read sequences from cache\n");
+		printf("firstSequence:%lf, lastSequence:%lf, lastPoRebuildTime:%lf\n", *cache_first_sequence, *cache_last_sequence, *cache_last_po_rebuild_time);
+	}
+		
+}
 static void
-add_sequence_to_cache (EBookBackendCache *cache, 
-                      gdouble first_sequence,
-                      gdouble last_sequence,
-                      gdouble last_po_rebuild_time)
+add_sequence_to_cache (DB *db, 
+		       gdouble first_sequence,
+		       gdouble last_sequence,
+		       gdouble last_po_rebuild_time)
 {
 		gchar *tmp;
+		DBT   uid_dbt, vcard_dbt;
+		int db_error;
+
+		if (enable_debug) {
+			printf("Adding sequences to cache\n");
+			printf("firstSequence:%lf, lastSequence:%lf, lastPoRebuildTime:%lf\n", first_sequence, last_sequence, last_po_rebuild_time);
+		}
+
+		string_to_dbt ("firstSequence",&uid_dbt );
+		tmp = g_strdup_printf("%lf", first_sequence);
+		string_to_dbt (tmp, &vcard_dbt);
+
+		db_error = db->put (db, NULL, &uid_dbt, &vcard_dbt, 0);
 
-		/* This is the system address book. Let try add the sequence to maintain deltas */
-               tmp = g_strdup_printf("%lf", first_sequence);
-		if (!e_file_cache_get_object (E_FILE_CACHE(cache), "firstSequence"))	
-			e_file_cache_add_object (E_FILE_CACHE(cache), "firstSequence", tmp);
-		else
-			e_file_cache_replace_object (E_FILE_CACHE(cache), "firstSequence", tmp);	
 		g_free (tmp);
 
-               tmp = g_strdup_printf("%lf", last_sequence);
-		if (!e_file_cache_get_object (E_FILE_CACHE(cache), "lastSequence"))
-			e_file_cache_add_object (E_FILE_CACHE(cache), "lastSequence", tmp);
-		else
-			e_file_cache_replace_object (E_FILE_CACHE(cache), "lastSequence", tmp);
+		if (db_error != 0) {
+			g_warning ("db->put failed with %d", db_error);
+		}
+
+		string_to_dbt ("lastSequence",&uid_dbt );
+		tmp = g_strdup_printf("%lf", last_sequence);
+		string_to_dbt (tmp, &vcard_dbt);
+
+		db_error = db->put (db, NULL, &uid_dbt, &vcard_dbt, 0);
+
 		g_free (tmp);
+
+		if (db_error != 0) {
+			g_warning ("db->put failed with %d", db_error);
+		}
 		
-               tmp = g_strdup_printf("%lf", last_po_rebuild_time);
-		if (!e_file_cache_get_object (E_FILE_CACHE(cache), "lastTimePORebuild"))
-			e_file_cache_add_object (E_FILE_CACHE(cache), "lastTimePORebuild", tmp);
-		else
-			e_file_cache_replace_object (E_FILE_CACHE(cache), "lastTimePORebuild", tmp);
+		string_to_dbt ("lastTimePORebuild",&uid_dbt );
+		tmp = g_strdup_printf("%lf", last_po_rebuild_time);
+		string_to_dbt (tmp, &vcard_dbt);
+
+		db_error = db->put (db, NULL, &uid_dbt, &vcard_dbt, 0);
+
 		g_free (tmp);
+
+		if (db_error != 0) {
+			g_warning ("db->put failed with %d", db_error);
+		}
 }
 
 #define CURSOR_ITEM_LIMIT 100
@@ -2446,10 +2533,9 @@ build_cache (EBookBackendGroupwise *ebgw
 	GTimeVal tstart, tend;
 	unsigned long diff;
 
-       if(!ebgw)
-               return FALSE;
+	if(!ebgw)
+		return FALSE;
 
-       printf("build cache\n");
 	if (enable_debug) {
 		g_get_current_time(&start);
 		printf("Building the cache for %s \n", ebgw->priv->book_name);
@@ -2467,14 +2553,13 @@ build_cache (EBookBackendGroupwise *ebgw
 	if (book_view) {
 		closure = get_closure (book_view);
 		bonobo_object_ref (book_view);
-               if (closure) {
-                       g_mutex_lock (closure->mutex);
-                       g_cond_signal (closure->cond);
-                       g_mutex_unlock (closure->mutex);
-               }
+		if (closure) {
+			g_mutex_lock (closure->mutex);
+			g_cond_signal (closure->cond);
+			g_mutex_unlock (closure->mutex);
+		}
 	}
 
-	e_file_cache_freeze_changes (E_FILE_CACHE (priv->cache));
 	while (!done) {
 
 		if (enable_debug) 
@@ -2496,7 +2581,7 @@ build_cache (EBookBackendGroupwise *ebgw
 			fill_contact_from_gw_item (contact, E_GW_ITEM (l->data), 
 						   ebgw->priv->categories_by_id);
 			e_contact_set (contact, E_CONTACT_BOOK_URI, priv->original_uri);
-			e_book_backend_cache_add_contact (ebgw->priv->cache, contact);
+			e_book_backend_db_cache_add_contact (ebgw->priv->file_db, contact);
 			e_book_backend_summary_add_contact (ebgw->priv->summary, contact);
 
 			/* Since we get contacts incrementally, 100 at a time, we can not
@@ -2516,7 +2601,7 @@ build_cache (EBookBackendGroupwise *ebgw
 			
 		}
 		if (!gw_items) {
-			e_book_backend_cache_set_populated (priv->cache);
+			e_book_backend_db_cache_set_populated (ebgw->priv->file_db);
 			done = TRUE;
 			priv->is_cache_ready=TRUE;
 			priv->is_summary_ready = TRUE;
@@ -2526,7 +2611,8 @@ build_cache (EBookBackendGroupwise *ebgw
 		gw_items = NULL;
 		position = E_GW_CURSOR_POSITION_CURRENT;
 	}
-	e_file_cache_thaw_changes (E_FILE_CACHE (priv->cache));
+
+	ebgw->priv->file_db->sync(ebgw->priv->file_db, 0);
 
 	if (book_view) {
 		e_data_book_view_notify_complete (book_view,
@@ -2547,7 +2633,7 @@ build_cache (EBookBackendGroupwise *ebgw
 }
 
 static void
-build_summary (EBookBackendGroupwisePrivate *priv)
+build_summary (EBookBackendGroupwise *ebgw)
 {
 	gchar *query_string;
 	GList *contacts, *temp_list = NULL;
@@ -2557,7 +2643,7 @@ build_summary (EBookBackendGroupwisePriv
 	if (enable_debug) {
 		g_get_current_time(&start);
 		printf ("summary file not found or not up-to-date, building summary for %s\n", 
-			priv->book_name);
+			ebgw->priv->book_name);
 	}
 
 	/* build summary from cache */
@@ -2565,23 +2651,23 @@ build_summary (EBookBackendGroupwisePriv
 					"    (beginswith \"full_name\" \"\") "
 					"    (beginswith \"email\" \"\") "
 					"    (beginswith \"nickname\" \"\"))");
-	contacts = e_book_backend_cache_get_contacts (priv->cache, query_string);
+	contacts = e_book_backend_db_cache_get_contacts (ebgw->priv->file_db, query_string);
 	g_free (query_string);
 	temp_list = contacts;
 	for (; contacts != NULL; contacts = g_list_next(contacts)) {
-		e_book_backend_summary_add_contact (priv->summary, contacts->data);
+		e_book_backend_summary_add_contact (ebgw->priv->summary, contacts->data);
 		g_object_unref (contacts->data);
 	}
 	if (temp_list)
 		g_list_free (temp_list);
-	priv->is_summary_ready = TRUE;
+	ebgw->priv->is_summary_ready = TRUE;
 	
 	if (enable_debug) {
 		g_get_current_time(&end);
 		diff = end.tv_sec * 1000 + end.tv_usec/1000;
 		diff -= start.tv_sec * 1000 + start.tv_usec/1000;
 		printf("building summary for %s took %ld.%03ld seconds \n", 
-			priv->book_name, diff / 1000, diff % 1000);
+			ebgw->priv->book_name, diff / 1000, diff % 1000);
 	}
 }
 
@@ -2602,10 +2688,9 @@ update_cache (EBookBackendGroupwise *ebg
 	GTimeVal start, end;
 	unsigned long diff;
 
-       if (!ebgw)
-               return FALSE;
+	if (!ebgw)
+		return FALSE;
 
-       printf("Inside update cache\n");
 	if (enable_debug) {
 		g_get_current_time(&start);
 		printf("updating cache for %s\n", ebgw->priv->book_name);
@@ -2615,14 +2700,14 @@ update_cache (EBookBackendGroupwise *ebg
 	if (book_view) {
 		closure = get_closure (book_view);
 		bonobo_object_ref (book_view);
-               if (closure) {
-                       g_mutex_lock (closure->mutex);
-                       g_cond_signal (closure->cond);
-                       g_mutex_unlock (closure->mutex);
-               }
+		if (closure) {
+			g_mutex_lock (closure->mutex);
+			g_cond_signal (closure->cond);
+			g_mutex_unlock (closure->mutex);
+		}
 	}
 
-	cache_file_name = e_file_cache_get_filename (E_FILE_CACHE(ebgw->priv->cache));
+	cache_file_name = e_book_backend_db_cache_get_filename(ebgw->priv->file_db);
 	g_stat (cache_file_name, &buf);
 	mod_time = buf.st_mtime;
 	tm = gmtime (&mod_time);
@@ -2631,7 +2716,7 @@ update_cache (EBookBackendGroupwise *ebg
 	if (e_book_backend_summary_load (ebgw->priv->summary) == FALSE || 
 	    e_book_backend_summary_is_up_to_date (ebgw->priv->summary, mod_time) == FALSE) {
 		/* build summary */
-		 build_summary (ebgw->priv);
+		 build_summary (ebgw);
 	}
 	
 	filter = e_gw_filter_new ();
@@ -2647,7 +2732,6 @@ update_cache (EBookBackendGroupwise *ebg
 		return FALSE;
 	}
 	
-	e_file_cache_freeze_changes (E_FILE_CACHE (ebgw->priv->cache));
 	for (; gw_items != NULL; gw_items = g_list_next(gw_items)) { 
 		const char *id;
 
@@ -2665,13 +2749,12 @@ update_cache (EBookBackendGroupwise *ebg
 			g_free (status_msg);
 		}
 
-		if (e_book_backend_cache_check_contact (ebgw->priv->cache, id)) {
-			e_book_backend_cache_remove_contact (ebgw->priv->cache, id);
-			e_book_backend_cache_add_contact (ebgw->priv->cache, contact);
+		if (e_book_backend_db_cache_check_contact (ebgw->priv->file_db, id)) {
+			e_book_backend_db_cache_add_contact (ebgw->priv->file_db, contact);
 			e_book_backend_summary_remove_contact (ebgw->priv->summary, id);
 			e_book_backend_summary_add_contact (ebgw->priv->summary, contact);
 		} else {
-			e_book_backend_cache_add_contact (ebgw->priv->cache, contact);
+			e_book_backend_db_cache_add_contact (ebgw->priv->file_db, contact);
 			e_book_backend_summary_add_contact (ebgw->priv->summary, contact);
 		}
 		
@@ -2681,7 +2764,9 @@ update_cache (EBookBackendGroupwise *ebg
 	
 	ebgw->priv->is_cache_ready = TRUE;
 	ebgw->priv->is_summary_ready = TRUE;
-	e_file_cache_thaw_changes (E_FILE_CACHE (ebgw->priv->cache));
+	
+	ebgw->priv->file_db->sync(ebgw->priv->file_db, 0);
+
 	if (book_view) {
 		e_data_book_view_notify_complete (book_view,
 						  GNOME_Evolution_Addressbook_Success);
@@ -2704,23 +2789,22 @@ static gboolean
 update_address_book_deltas (EBookBackendGroupwise *ebgw)
 {
 	int status, contact_num = 0;
-       gdouble server_first_sequence = -1, server_last_sequence = -1, server_last_po_rebuild_time = -1;
-       gdouble cache_last_sequence = -1, cache_last_po_rebuild_time = -1;
-	const char *cache_obj;
-	char *tmp, *count, *sequence, *status_msg;
+	gdouble server_first_sequence = -1, server_last_sequence = -1, server_last_po_rebuild_time = -1;
+	gdouble cache_first_sequence = -1, cache_last_sequence = -1, cache_last_po_rebuild_time = -1;
+	char *count, *sequence, *status_msg;
+	gboolean sync_required = FALSE;
 	GList *add_list = NULL, *delete_list = NULL;
 	EContact *contact;
 	EDataBookView *book_view;
 	GroupwiseBackendSearchClosure *closure;
 
-       if (!ebgw)
-               return FALSE;
+	if (!ebgw)
+		return FALSE;
 
 	EBookBackendGroupwisePrivate *priv = ebgw->priv;
-	EBookBackendCache *cache = priv->cache;
-	
-	g_mutex_lock (priv->update_mutex);
 
+	g_mutex_lock (priv->update_mutex);
+	
 	if (enable_debug)
 		printf("\nupdating GroupWise system address book cache \n");
 		
@@ -2733,7 +2817,7 @@ update_address_book_deltas (EBookBackend
 	if (status != E_GW_CONNECTION_STATUS_OK) {
 		if (enable_debug)
 			printf("No connection with the server \n");
-		g_mutex_unlock(priv->update_mutex);
+		g_mutex_unlock (priv->update_mutex);
 		return FALSE;
 	}
 
@@ -2743,18 +2827,12 @@ update_address_book_deltas (EBookBackend
 		if (enable_debug)
 			printf ("sequence is reset, rebuilding cache...\n");
 		build_cache (ebgw);
-		g_mutex_unlock(priv->update_mutex);
+		g_mutex_unlock (priv->update_mutex);
 		return TRUE;
 	}
 
-	/* Read the last sequence and last poa rebuild time from cache */	
-	cache_obj = e_file_cache_get_object (E_FILE_CACHE (cache), "lastSequence");
-	if (cache_obj)
-               cache_last_sequence = strtod (cache_obj, NULL);
-	
-	cache_obj = e_file_cache_get_object (E_FILE_CACHE (cache), "lastTimePORebuild");
-	if (cache_obj)
-               cache_last_po_rebuild_time = strtod (cache_obj, NULL);
+	/* Read the last sequence and last poa rebuild time from cache */
+	get_sequence_from_cache(priv->file_db, &cache_first_sequence, &cache_last_sequence, &cache_last_po_rebuild_time);
 
 	/* check whether the all the sequences are available and also whether the PO is rebuilt */
 	if (server_first_sequence > cache_last_sequence || cache_last_sequence == -1 || 
@@ -2763,9 +2841,9 @@ update_address_book_deltas (EBookBackend
 		if (enable_debug)
 			printf ("either the sequences missing or PO is rebuilt...rebuilding the cache\n");
 		build_cache (ebgw);
-		add_sequence_to_cache (cache, server_first_sequence, 
+		add_sequence_to_cache (priv->file_db, server_first_sequence, 
 				       server_last_sequence, server_last_po_rebuild_time);
-		g_mutex_unlock(priv->update_mutex);
+		ebgw->priv->file_db->sync (ebgw->priv->file_db, 0);
 		return TRUE;
 	}
 
@@ -2782,32 +2860,34 @@ update_address_book_deltas (EBookBackend
 	if (book_view) {
 		closure = get_closure (book_view);
 		bonobo_object_ref (book_view);
-               if (closure){
-                       g_mutex_lock (closure->mutex);
-                       g_cond_signal (closure->cond);
-                       g_mutex_unlock (closure->mutex);
-               }
+		if (closure){
+			g_mutex_lock (closure->mutex);
+			g_cond_signal (closure->cond);
+			g_mutex_unlock (closure->mutex);
+		}
 	}
 
 	/* update the cache */
-       sequence = g_strdup_printf ("%lf", cache_last_sequence +1);
+	sequence = g_strdup_printf ("%lf", cache_last_sequence +1);
 	count = g_strdup_printf ("%d", CURSOR_ITEM_LIMIT);
 
 	/* load summary file */
-	cache_file_name = e_file_cache_get_filename (E_FILE_CACHE(ebgw->priv->cache));
+	cache_file_name = e_book_backend_db_cache_get_filename(ebgw->priv->file_db);
 	g_stat (cache_file_name, &buf);
 	mod_time = buf.st_mtime;
 	if (e_book_backend_summary_load (ebgw->priv->summary) == FALSE || 
 	    e_book_backend_summary_is_up_to_date (ebgw->priv->summary, mod_time) == FALSE) {
 		/* build summary */
-		 build_summary (ebgw->priv);
+		 build_summary (ebgw);
 	}
 
 	if (cache_last_sequence != server_last_sequence) {
-		e_file_cache_freeze_changes (E_FILE_CACHE (cache));
 
 		while (cache_last_sequence < server_last_sequence) {
-                       printf("Calling get_items_delta\n");
+			if (enable_debug) {
+				printf("cache_last_sequence:%lf, server_last_sequence:%lf\n", cache_last_sequence, server_last_sequence);
+				printf("Calling get_items_delta\n");
+			}
 			e_gw_connection_get_items_delta (priv->cnc, 
 							 ebgw->priv->container_id, 
 							 "name email sync", count, 
@@ -2819,9 +2899,10 @@ update_address_book_deltas (EBookBackend
 					printf("sequence differs but no changes found !!!\n");
 				break;
 			}
+			sync_required = TRUE;
 			if (enable_debug) {
-                	       printf("add_list size:%d\n", g_list_length(add_list));
-	                       printf("delete_list size:%d\n", g_list_length(delete_list));
+				printf("add_list size:%d\n", g_list_length(add_list));
+				printf("delete_list size:%d\n", g_list_length(delete_list));
 			}
 
 			for (; delete_list != NULL; delete_list = g_list_next(delete_list)) { 
@@ -2839,7 +2920,7 @@ update_address_book_deltas (EBookBackend
 					       priv->original_uri);
 				id =  e_contact_get_const (contact, E_CONTACT_UID);
 
-				if (e_book_backend_cache_check_contact (ebgw->priv->cache, id)) {
+				if (e_book_backend_db_cache_check_contact (ebgw->priv->file_db, id)) {
 					contact_num++;
 
 					if (book_view) {
@@ -2848,7 +2929,7 @@ update_address_book_deltas (EBookBackend
 						book_view_notify_status (book_view, status_msg);
 						g_free (status_msg);
 					}
-					e_book_backend_cache_remove_contact (ebgw->priv->cache, id);
+					e_book_backend_db_cache_remove_contact (ebgw->priv->file_db, id);
 					e_book_backend_summary_remove_contact (ebgw->priv->summary, id);
 				}
 				g_object_unref(contact);
@@ -2863,6 +2944,9 @@ update_address_book_deltas (EBookBackend
 				fill_contact_from_gw_item (contact, 
 							   E_GW_ITEM (add_list->data), 
 							   ebgw->priv->categories_by_id);
+
+				if (enable_debug)
+					printf("contact email:%s, contact name:%s\n", (char *)e_contact_get(contact, E_CONTACT_EMAIL_1),(char *) e_contact_get(contact, E_CONTACT_GIVEN_NAME));
 				e_contact_set (contact, 
 					       E_CONTACT_BOOK_URI, 
 					       priv->original_uri);
@@ -2875,41 +2959,32 @@ update_address_book_deltas (EBookBackend
 					book_view_notify_status (book_view, status_msg);
 					g_free (status_msg);
 				}
-				if (e_book_backend_cache_check_contact (ebgw->priv->cache, id)) {
-					e_book_backend_cache_remove_contact (ebgw->priv->cache, id);
+				if (e_book_backend_db_cache_check_contact (ebgw->priv->file_db, id)) {
+					if (enable_debug)
+						printf("contact already there\n");
 					e_book_backend_summary_remove_contact (ebgw->priv->summary, id);
-					e_book_backend_cache_add_contact (ebgw->priv->cache, contact);
+					e_book_backend_db_cache_add_contact (ebgw->priv->file_db, contact);
 					e_book_backend_summary_add_contact (ebgw->priv->summary, contact);
 				} else {
-		    			e_book_backend_cache_add_contact (ebgw->priv->cache, contact);
+					if (enable_debug)
+						printf("contact not there\n");
+		    			e_book_backend_db_cache_add_contact (ebgw->priv->file_db, contact);
 					e_book_backend_summary_add_contact (ebgw->priv->summary, contact);
 				}
 
 				g_object_unref(contact);
 				g_object_unref (add_list->data);
 			}
-
 			cache_last_sequence += contact_num;
 		}
 
 		/* cache is updated, now adding the sequence information to the cache */
 
-               tmp = g_strdup_printf("%lf", server_first_sequence);
-		e_file_cache_replace_object (E_FILE_CACHE(cache), "firstSequence", tmp);		
-		g_free (tmp);
-	
-               tmp = g_strdup_printf("%lf", server_last_sequence);
-		e_file_cache_replace_object (E_FILE_CACHE(cache), "lastSequence", tmp);
-		g_free (tmp);
-	
-               tmp = g_strdup_printf("%lf", server_last_po_rebuild_time);
-		e_file_cache_replace_object (E_FILE_CACHE(cache), "lastTimePORebuild", tmp);
-		g_free (tmp);
+		add_sequence_to_cache (priv->file_db, server_first_sequence, 
+				       server_last_sequence, server_last_po_rebuild_time);
 
 		g_list_free (add_list);
 		g_list_free (delete_list);
-
-		e_file_cache_thaw_changes (E_FILE_CACHE (cache));
 	}
 	
 	g_free (sequence);
@@ -2917,6 +2992,10 @@ update_address_book_deltas (EBookBackend
 	ebgw->priv->is_cache_ready = TRUE;
 	ebgw->priv->is_summary_ready = TRUE;
 
+	if (sync_required)
+		ebgw->priv->file_db->sync(ebgw->priv->file_db, 0);
+
+
 	if (book_view) {
 		e_data_book_view_notify_complete (book_view,
 						  GNOME_Evolution_Addressbook_Success);
@@ -2975,7 +3054,8 @@ e_book_backend_groupwise_authenticate_us
 	const char *cache_refresh_interval_set;
 	int cache_refresh_interval = CACHE_REFRESH_INTERVAL;
 
-	printf ("authenticate user ............\n");
+	if (enable_debug)
+		printf ("authenticate user ............\n");
 	ebgw = E_BOOK_BACKEND_GROUPWISE (backend);
 	priv = ebgw->priv;
 
@@ -2996,7 +3076,7 @@ e_book_backend_groupwise_authenticate_us
 	case GNOME_Evolution_Addressbook_MODE_REMOTE:
 		
 		if (priv->cnc) { /*we have already authenticated to server */
-                       printf("already authenticated\n");
+			printf("already authenticated\n");
 			e_data_book_respond_authenticate_user (book, opid, GNOME_Evolution_Addressbook_Success); 
 			return;
 		}
@@ -3014,8 +3094,9 @@ e_book_backend_groupwise_authenticate_us
 		
 		id = NULL;
 		is_writable = FALSE;
-               if(priv->book_name)
-                       printf("book_name:%s\n", priv->book_name);
+		if (enable_debug)
+ 			if(priv->book_name)
+				printf("book_name:%s\n", priv->book_name);
 		status = e_gw_connection_get_address_book_id (priv->cnc,  priv->book_name, &id, &is_writable); 
 		if (status == E_GW_CONNECTION_STATUS_INVALID_CONNECTION)
 			status = e_gw_connection_get_address_book_id (priv->cnc,  priv->book_name, &id, &is_writable); 
@@ -3051,24 +3132,29 @@ e_book_backend_groupwise_authenticate_us
 		priv->summary = e_book_backend_summary_new (priv->summary_file_name, 
 							    SUMMARY_FLUSH_TIMEOUT);
 		
-		if (e_book_backend_cache_is_populated (priv->cache)) {
-                       printf("cache is populated\n");
-                       if (priv->is_writable){
-                               printf("is writable\n");
-                               printf("creating update_cache thread\n");
+		if (e_book_backend_db_cache_is_populated (ebgw->priv->file_db)) {
+			if (enable_debug)
+				printf("cache is populated\n");
+			if (priv->is_writable){
+				if (enable_debug) {
+					printf("is writable\n");
+					printf("creating update_cache thread\n");
+				}
 				g_thread_create ((GThreadFunc) update_cache, ebgw, FALSE, NULL);
-                       }
+			}
 			else if (priv->marked_for_offline) {
-                               printf("marked for offline\n");
+				if (enable_debug)
+					printf("marked for offline\n");
 				GThread *t;
-                               printf("creating update_address_book_deltas thread\n");
+				if (enable_debug)
+					printf("creating update_address_book_deltas thread\n");
 
 				t = g_thread_create ((GThreadFunc) update_address_book_deltas, ebgw, TRUE, NULL);
 
 				/* spawn a thread to update the system address book cache 
 	 			 * at given intervals
 	 			 */
-                               cache_refresh_interval_set = g_getenv ("BOOK_CACHE_REFRESH_INTERVAL");
+				cache_refresh_interval_set = g_getenv ("BOOK_CACHE_REFRESH_INTERVAL");
 				if (cache_refresh_interval_set) {
 					cache_refresh_interval = g_ascii_strtod (cache_refresh_interval_set, 
 										NULL); /* use this */
@@ -3086,16 +3172,20 @@ e_book_backend_groupwise_authenticate_us
 		}
 		else if (priv->is_writable) {  /* for personal books we always cache */
 			/* Personal address book and frequent contacts */
-                       printf("else if is _writable");
-                       printf("build_cahe thread");
+			if (enable_debug) {
+				printf("else if is _writable");
+				printf("build_cahe thread");
+			}
 			g_thread_create ((GThreadFunc) build_cache, ebgw, FALSE, NULL);
 		}
 		else if(priv->marked_for_offline) { 
-                       printf("else if marked_for_offline\n");
+			if (enable_debug)
+				printf("else if marked_for_offline\n");
 			GThread *t;
 			/* System address book */
 			/* cache is not populated and book is not writable and marked for offline usage */
-                       printf("creating update_address_book_deltas thread\n");
+			if (enable_debug)
+				printf("creating update_address_book_deltas thread\n");
 			t = g_thread_create ((GThreadFunc) update_address_book_deltas, ebgw, TRUE, NULL);
 			g_thread_join (t);
 			/* set the cache refresh time */
@@ -3164,6 +3254,12 @@ e_book_backend_groupwise_cancel_operatio
 	return GNOME_Evolution_Addressbook_CouldNotCancel;
 }
 
+static void
+file_errcall (const char *buf1, char *buf2)
+{
+	g_warning ("libdb error: %s", buf2);
+}
+
 static GNOME_Evolution_Addressbook_CallStatus
 e_book_backend_groupwise_load_source (EBookBackend           *backend,
 				      ESource                *source,
@@ -3171,10 +3267,14 @@ e_book_backend_groupwise_load_source (EB
 {
 	EBookBackendGroupwise *ebgw;
 	EBookBackendGroupwisePrivate *priv;
+	char *dirname, *filename;
         char *book_name;
         char *uri;
 	char **tokens;
    	const char *port;
+	int db_error;
+	DB *db;
+	DB_ENV *env;
 	EUri *parsed_uri;
 	int i;
 	const char *use_ssl;
@@ -3240,7 +3340,7 @@ e_book_backend_groupwise_load_source (EB
 	}
 
 	if (priv->mode == GNOME_Evolution_Addressbook_MODE_LOCAL) 
-		if (!e_book_backend_cache_exists (priv->original_uri)) {
+		if (!e_book_backend_db_cache_exists (priv->original_uri)) {
 			g_free (uri);
 			e_uri_free (parsed_uri);
 			return GNOME_Evolution_Addressbook_OfflineUnavailable;
@@ -3249,15 +3349,117 @@ e_book_backend_groupwise_load_source (EB
         g_free (priv->summary_file_name);
 	priv->summary_file_name = g_build_filename (g_get_home_dir(), ".evolution/addressbook" , uri, priv->book_name, NULL);
         priv->summary_file_name = g_strconcat (ebgw->priv->summary_file_name, ".summary", NULL);
+
+	dirname = g_build_filename (g_get_home_dir(), ".evolution/cache/addressbook", uri, priv->book_name, NULL);
+	filename = g_build_filename (dirname, "cache.db", NULL);
+
+	db_error = e_db3_utils_maybe_recover (filename);
+	if (db_error !=0) {
+		g_warning ("db recovery failed with %d", db_error);
+		g_free (dirname);
+		g_free (filename);
+		return GNOME_Evolution_Addressbook_OtherError;
+	}
+	
+	g_static_mutex_lock(&global_env_lock);
+	if (global_env.ref_count > 0) {
+		env = global_env.env;
+		global_env.ref_count++;
+	} 
+	else {
+		db_error = db_env_create (&env, 0);
+		if (db_error != 0) {
+			g_warning ("db_env_create failed with %d", db_error);
+			g_static_mutex_unlock (&global_env_lock);
+			g_free (dirname);
+			g_free (filename);
+			return GNOME_Evolution_Addressbook_OtherError;
+		}
+
+		db_error = env->open (env, NULL, DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE | DB_THREAD, 0);
+		if (db_error != 0) {
+			env->close(env, 0);
+			g_warning ("db_env_open failed with %d", db_error);
+			g_static_mutex_unlock(&global_env_lock);
+			g_free(dirname);
+			g_free(filename);
+			return GNOME_Evolution_Addressbook_OtherError;
+		}
+
+		env->set_errcall (env, file_errcall);
+
+		global_env.env = env;
+		global_env.ref_count = 1;
+	}
+	g_static_mutex_unlock(&global_env_lock);
+
+	ebgw->priv->env = env;
+
+	db_error = db_create (&db, env, 0);
+	if (db_error != 0) {
+		g_warning ("db_create failed with %d", db_error);
+		g_free(dirname);
+		g_free(filename);
+		return GNOME_Evolution_Addressbook_OtherError;
+	}
+
+	db_error = db->open (db, NULL, filename, NULL, DB_HASH, DB_THREAD, 0666);
+
+	if (db_error == DB_OLD_VERSION) {
+		db_error = e_db3_utils_upgrade_format (filename);
+
+		if (db_error != 0) {
+			g_warning ("db format upgrade failed with %d", db_error);
+			g_free(filename);
+			g_free(dirname);
+			return GNOME_Evolution_Addressbook_OtherError;
+		}
+		
+		db_error = db->open (db, NULL, filename, NULL, DB_HASH, DB_THREAD, 0666);
+	}
+
+	ebgw->priv->file_db = db;
+
+	if (db_error != 0) {
+		int rv;
+
+		/* the databade didn't exist, so we create the 
+		   directory then the .db */
+		rv = e_util_mkdir_hier (dirname, 0777);
+		if (rv == -1 && errno != EEXIST) {
+			g_warning ("failed to make directory %s: %s", dirname, strerror (errno));
+			g_free (dirname);
+			g_free (filename);
+			if (errno == EACCES || errno == EPERM)
+				return GNOME_Evolution_Addressbook_PermissionDenied;
+			else
+				return GNOME_Evolution_Addressbook_OtherError;
+		}
+
+		db_error = db->open (db, NULL, filename, NULL, DB_HASH, DB_CREATE | DB_THREAD, 0666);
+		if (db_error != 0) {
+			g_warning ("db->open (...DB_CREATE...) failed with %d", db_error);
+		}
+
+	}
+
+	if (db_error != 0) {
+		ebgw->priv->file_db = NULL;
+		g_free(filename);
+		g_free(dirname);
+		return GNOME_Evolution_Addressbook_OtherError;
+	}
 	
+	e_book_backend_db_cache_set_filename (ebgw->priv->file_db, filename);
+	g_free(filename);
+	g_free(dirname);
 	g_free (uri);
 	e_uri_free (parsed_uri);
 
-	priv->cache = e_book_backend_cache_new (priv->original_uri);
-	if (enable_debug) {
+	/*if (enable_debug) {
 		printf ("summary file name = %s\ncache file name = %s \n", 
 			 priv->summary_file_name, e_file_cache_get_filename (E_FILE_CACHE(priv->cache)));
-	}
+	}*/
 
 	return GNOME_Evolution_Addressbook_Success;
 }
@@ -3286,7 +3488,7 @@ e_book_backend_groupwise_remove (EBookBa
 		e_data_book_respond_remove (book,  opid, GNOME_Evolution_Addressbook_Success);
 	else
 		e_data_book_respond_remove (book,  opid, GNOME_Evolution_Addressbook_OtherError);
-	g_unlink (e_file_cache_get_filename (E_FILE_CACHE (ebgw->priv->cache)));
+	g_unlink (e_book_backend_db_cache_get_filename(ebgw->priv->file_db));
 }
 
 static char *
@@ -3380,6 +3582,16 @@ e_book_backend_groupwise_dispose (GObjec
 	bgw = E_BOOK_BACKEND_GROUPWISE (object);
                                                                                                                              
 	if (bgw->priv) {
+		if (bgw->priv->file_db)
+			bgw->priv->file_db->close (bgw->priv->file_db, 0);
+
+		g_static_mutex_lock(&global_env_lock);
+		global_env.ref_count--;
+		if (global_env.ref_count == 0) {
+			global_env.env->close (global_env.env, 0);
+			global_env.env = NULL;
+		}
+		g_static_mutex_unlock(&global_env_lock);
 		if (bgw->priv->uri) {
 			g_free (bgw->priv->uri);
 			bgw->priv->uri = NULL;
@@ -3406,9 +3618,6 @@ e_book_backend_groupwise_dispose (GObjec
 			g_free (bgw->priv->summary_file_name);
 			bgw->priv->summary_file_name = NULL;
 		}
-		if (bgw->priv->cache) {
-			g_object_unref (bgw->priv->cache);
-		}
 		if (bgw->priv->summary) {
 			e_book_backend_summary_save(bgw->priv->summary);
 			g_object_unref (bgw->priv->summary);
@@ -3422,7 +3631,7 @@ e_book_backend_groupwise_dispose (GObjec
 			bgw->priv->cache_timeout = 0;
 		}
 		if (bgw->priv->update_mutex)
-			g_mutex_free(bgw->priv->update_mutex);
+			g_mutex_free (bgw->priv->update_mutex);
 		
 		g_free (bgw->priv);
 		bgw->priv = NULL;
@@ -3477,14 +3686,12 @@ e_book_backend_groupwise_init (EBookBack
 	priv->is_summary_ready = FALSE;
 	priv->marked_for_offline = FALSE;
 	priv->use_ssl = NULL;
-	priv->cache=NULL;
-       priv->cnc = NULL;
+	priv->cnc = NULL;
 	priv->original_uri = NULL;
 	priv->cache_timeout = 0;
 	priv->update_mutex = g_mutex_new();
 	priv->reserved1 = NULL;
 	priv->reserved2 = NULL;
-	priv->reserved3 = NULL;
        	backend->priv = priv;
 
 	if (g_getenv ("GROUPWISE_DEBUG")) { 
Index: addressbook/backends/groupwise/Makefile.am
===================================================================
RCS file: /cvs/gnome/evolution-data-server/addressbook/backends/groupwise/Makefile.am,v
retrieving revision 1.9
diff -u -p -r1.9 Makefile.am
--- addressbook/backends/groupwise/Makefile.am	22 Jun 2005 12:34:21 -0000	1.9
+++ addressbook/backends/groupwise/Makefile.am	11 Apr 2006 05:14:12 -0000
@@ -5,6 +5,7 @@ INCLUDES =						\
 	-I$(top_srcdir)/addressbook			\
 	-I$(top_builddir)/addressbook			\
 	-I$(top_srcdir)/servers/groupwise               \
+	-I$(top_srcdir)/libdb/dist			\
 	$(EVOLUTION_ADDRESSBOOK_CFLAGS)                 \
 	$(SOUP_CFLAGS)	
 extension_LTLIBRARIES = libebookbackendgroupwise.la
@@ -19,6 +20,7 @@ libebookbackendgroupwise_la_LIBADD =				
 	$(top_builddir)/addressbook/libebook/libebook-1.2.la		\
 	$(top_builddir)/addressbook/libedata-book/libedata-book-1.2.la	\
 	$(top_builddir)/libedataserver/libedataserver-1.2.la		\
+	$(top_builddir)/libdb/dist/libdb-4.1.la				\
 	$(EVOLUTION_ADDRESSBOOK_LIBS)					\
 	$(SOUP_LIBS)
 
--- /dev/null	2006-04-11 14:30:05.384262500 +0530
+++ addressbook/libedata-book/e-book-backend-db-cache.c	2006-04-05 20:04:23.000000000 +0530
@@ -0,0 +1,416 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* A class to cache address  book conents on local file system
+ *
+ * Copyright (C) 2004 Novell, Inc.
+ *
+ * Authors: Devashish Sharma <sdevashish@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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include "e-book-backend-db-cache.h"
+#include "e-book-backend.h"
+#include "e-book-backend-sexp.h"
+
+void 
+string_to_dbt(const char *str, DBT *dbt)
+{
+	memset(dbt, 0, sizeof(dbt));
+	dbt->data = (void *)str;
+	dbt->size = strlen(str) + 1;
+	dbt->flags = DB_DBT_USERMEM;
+}
+
+static char *
+get_filename_from_uri (const char *uri)
+{
+	char *mangled_uri, *filename;
+	int i;
+
+	/* mangle the URI to not contain invalid characters */
+	mangled_uri = g_strdup (uri);
+	for (i = 0; i < strlen (mangled_uri); i++) {
+		switch (mangled_uri[i]) {
+		case ':' :
+		case '/' :
+			mangled_uri[i] = '_';
+		}
+	}
+
+	/* generate the file name */
+	filename = g_build_filename (g_get_home_dir (), ".evolution/cache/addressbook",
+				     mangled_uri, "cache.db", NULL);
+
+	/* free memory */
+	g_free (mangled_uri);
+
+	return filename;
+}
+
+/**
+ * e_book_backend_db_cache_set_filename:
+ * @db:  DB Handle
+ * @filename: filename to be set
+ *
+ * Set the filename for db cacahe file.
+ **/
+
+void 
+e_book_backend_db_cache_set_filename(DB *db, const char *filename)
+{
+	DBT uid_dbt, vcard_dbt;
+	int db_error;
+
+	string_to_dbt ("filename", &uid_dbt);
+	string_to_dbt (filename, &vcard_dbt);
+
+	db_error = db->put (db, NULL, &uid_dbt, &vcard_dbt, 0);
+	if (db_error != 0) {
+		g_warning ("db->put failed with %d", db_error);
+	}
+	
+}
+
+/**
+ * e_book_backend_db_cache_get_filename:
+ * @db:  DB Handle
+ *
+ * Get the filename for db cacahe file.
+ **/
+
+char *
+e_book_backend_db_cache_get_filename(DB *db)
+{
+	DBT  uid_dbt, vcard_dbt;
+	int db_error;
+	char *filename;
+
+	string_to_dbt ("filename", &uid_dbt);
+	memset (&vcard_dbt, 0 , sizeof(vcard_dbt));
+	vcard_dbt.flags = DB_DBT_MALLOC;
+	
+	db_error = db->get (db, NULL, &uid_dbt, &vcard_dbt, 0);
+	if (db_error != 0) {
+		g_warning ("db-<get failed with %d", db_error);
+		return NULL;
+	}
+	else {
+		filename = g_strdup (vcard_dbt.data);
+		g_free (vcard_dbt.data);
+		return filename;
+	}
+}
+
+/**
+ * e_book_backend_db_cache_get_contact:
+ * @db: DB Handle
+ * @uid: a unique contact ID
+ *
+ * Get a cached contact. Note that the returned #EContact will be
+ * newly created, and must be unreffed by the caller when no longer
+ * needed.
+ *
+ * Return value: A cached #EContact, or %NULL if @uid is not cached.
+ **/
+EContact *
+e_book_backend_db_cache_get_contact (DB *db, const char *uid)
+{
+	DBT        uid_dbt, vcard_dbt;
+	int        db_error;
+	const char *vcard_str;
+
+	g_return_val_if_fail (uid != NULL, NULL);
+
+	string_to_dbt (uid, &uid_dbt);
+	memset (&vcard_dbt, 0 , sizeof(vcard_dbt));
+	vcard_dbt.flags = DB_DBT_MALLOC;
+	
+	db_error = db->get (db, NULL, &uid_dbt, &vcard_dbt,0);
+	if (db_error != 0) { 
+		g_warning ("db->get failed with %d", db_error);
+		return NULL;
+	}
+	
+	vcard_str = g_strdup (vcard_dbt.data);
+	g_free (vcard_dbt.data);
+	
+	return e_contact_new_from_vcard (vcard_str);
+}
+
+/**
+ * e_book_backend_db_cache_add_contact:
+ * @db: DB Handle
+ * @contact: an #EContact
+ *
+ * Adds @contact to @cache.
+ *
+ * Return value: %TRUE if the contact was cached successfully, %FALSE otherwise.
+ **/
+gboolean
+e_book_backend_db_cache_add_contact (DB *db,
+				   EContact *contact)
+{
+	DBT        uid_dbt, vcard_dbt;
+	int        db_error;
+	char       *vcard_str;
+	const char *uid;
+
+	uid = e_contact_get_const (contact, E_CONTACT_UID);
+	if (!uid) {
+		printf ("no uid\n");
+		printf("name:%s, email:%s\n", e_contact_get (contact, E_CONTACT_GIVEN_NAME), e_contact_get (contact, E_CONTACT_EMAIL_1));
+		return NULL; 
+	}
+	string_to_dbt (uid, &uid_dbt);
+	
+	vcard_str = e_vcard_to_string (E_VCARD(contact), EVC_FORMAT_VCARD_30);
+	string_to_dbt (vcard_str, &vcard_dbt);
+
+	//db_error = db->del (db, NULL, &uid_dbt, 0);
+	db_error = db->put (db, NULL, &uid_dbt, &vcard_dbt, 0);
+
+	g_free (vcard_str);
+
+	if (db_error != 0) { 
+		g_warning ("db->put failed with %d", db_error);
+		return FALSE;
+	}
+	else 
+		return TRUE;
+}
+
+/**
+ * e_book_backend_db_cache_remove_contact:
+ * @db: DB Handle
+ * @uid: a unique contact ID
+ *
+ * Removes the contact identified by @uid from @cache.
+ *
+ * Return value: %TRUE if the contact was found and removed, %FALSE otherwise.
+ **/
+gboolean
+e_book_backend_db_cache_remove_contact (DB *db,
+				    const char *uid)
+				      
+{
+	DBT        uid_dbt;
+	int        db_error;
+
+	g_return_val_if_fail (uid != NULL, FALSE);
+
+	string_to_dbt (uid, &uid_dbt);
+	db_error = db->del (db, NULL, &uid_dbt, 0);
+
+	if (db_error != 0) { 
+		g_warning ("db->del failed with %d", db_error);
+		return FALSE;
+	}
+	else 
+		return TRUE;
+
+}
+
+/**
+ * e_book_backend_db_cache_check_contact:
+ * @db: DB Handle
+ * @uid: a unique contact ID
+ *
+ * Checks if the contact identified by @uid exists in @cache.
+ *
+ * Return value: %TRUE if the cache contains the contact, %FALSE otherwise.
+ **/
+gboolean 
+e_book_backend_db_cache_check_contact (DB *db, const char *uid)
+{
+	DBT        uid_dbt, vcard_dbt;
+	int        db_error;
+
+	g_return_val_if_fail (uid != NULL, FALSE);
+
+	string_to_dbt (uid, &uid_dbt);
+	memset (&vcard_dbt, 0 , sizeof(vcard_dbt));
+	vcard_dbt.flags = DB_DBT_MALLOC;
+	
+	db_error = db->get (db, NULL, &uid_dbt, &vcard_dbt,0);
+	if (db_error != 0) 
+		return FALSE;
+ 	else {
+		free (vcard_dbt.data);
+		return TRUE;
+	}
+}
+
+/**
+ * e_book_backend_db_cache_get_contacts:
+ * @db: DB Handle
+ * @query: an s-expression
+ *
+ * Returns a list of #EContact elements from @cache matching @query.
+ * When done with the list, the caller must unref the contacts and
+ * free the list.
+ *
+ * Return value: A #GList of pointers to #EContact.
+ **/
+GList *
+e_book_backend_db_cache_get_contacts (DB *db, const char *query)
+{
+	DBC        *dbc;
+	DBT        uid_dbt, vcard_dbt;
+	int        db_error;
+	GList *list = NULL;
+        EBookBackendSExp *sexp = NULL;
+	EContact *contact;
+
+	if (query) {
+		sexp = e_book_backend_sexp_new (query);
+		if (!sexp)
+			return NULL;
+	}
+
+	db_error = db->cursor (db, NULL, &dbc, 0);
+	if (db_error != 0) { 
+		g_warning ("db->cursor failed with %d", db_error);
+		return NULL;
+	}
+
+	memset(&vcard_dbt, 0 , sizeof(vcard_dbt));
+	memset(&uid_dbt, 0, sizeof(uid_dbt));
+	db_error = dbc->c_get(dbc, &uid_dbt, &vcard_dbt, DB_FIRST);
+
+	while(db_error == 0) {
+		if (vcard_dbt.data && !strncmp (vcard_dbt.data, "BEGIN:VCARD", 11))
+		if (e_book_backend_sexp_match_vcard(sexp, vcard_dbt.data)) {
+			contact = e_contact_new_from_vcard (vcard_dbt.data);
+			list = g_list_append (list, contact);
+		}
+		db_error = dbc->c_get (dbc, &uid_dbt, &vcard_dbt, DB_NEXT);
+	}
+
+	db_error = dbc->c_close (dbc);
+	if(db_error != 0)
+		g_warning ("db->c_close failed with %d", db_error);
+		
+	if (sexp)
+		g_object_unref (sexp);
+
+        return list;
+}
+
+/**
+ * e_book_backend_db_cache_search:
+ * @backend: an #EBookBackend
+ * @query: an s-expression
+ *
+ * Returns an array of pointers to unique contact ID strings for contacts
+ * in @cache matching @query. When done with the array, the caller must
+ * free the ID strings and the array.
+ *
+ * Return value: A #GPtrArray of pointers to contact ID strings.
+ **/
+GPtrArray *
+e_book_backend_db_cache_search (DB *db, const char *query)
+{
+	GList *matching_contacts, *temp;
+	GPtrArray *ptr_array;
+	
+	matching_contacts = e_book_backend_db_cache_get_contacts (db, query);
+	ptr_array = g_ptr_array_new ();
+	
+	temp = matching_contacts;
+	for (; matching_contacts != NULL; matching_contacts = g_list_next (matching_contacts)) {
+		g_ptr_array_add (ptr_array, e_contact_get (matching_contacts->data, E_CONTACT_UID));
+		g_object_unref (matching_contacts->data);
+	}
+	g_list_free (temp);
+	
+	return ptr_array;
+}
+
+/**
+ * e_book_backend_db_cache_exists:
+ * @uri: URI for the cache
+ *
+ * Checks if an #EBookBackendCache exists at @uri.
+ *
+ * Return value: %TRUE if cache exists, %FALSE if not.
+ **/
+gboolean 
+e_book_backend_db_cache_exists (const char *uri)
+{
+	char *file_name;
+	gboolean exists = FALSE;
+	file_name = get_filename_from_uri (uri);
+	
+	if (file_name && g_file_test (file_name, G_FILE_TEST_EXISTS)) {
+		exists = TRUE;
+		g_free (file_name);
+	}
+	
+	return exists;
+}
+
+/**
+ * e_book_backend_db_cache_set_populated:
+ * @backend: an #EBookBackend
+ *
+ * Flags @cache as being populated - that is, it is up-to-date on the 
+ * contents of the book it's caching.
+ **/
+void
+e_book_backend_db_cache_set_populated (DB *db)
+{
+	DBT        uid_dbt, vcard_dbt;
+	int        db_error;
+
+	string_to_dbt ("populated", &uid_dbt);
+	string_to_dbt ("TRUE", &vcard_dbt);
+	db_error = db->put (db, NULL, &uid_dbt, &vcard_dbt, 0);
+	if (db_error != 0) { 
+		g_warning ("db->put failed with %d", db_error);
+	}
+	
+}
+
+/**
+ * e_book_backend_cache_is_populated:
+ * @db: DB Handle
+ *
+ * Checks if @cache is populated.
+ *
+ * Return value: %TRUE if @cache is populated, %FALSE otherwise.
+ **/
+gboolean
+e_book_backend_db_cache_is_populated (DB *db)
+{
+	DBT        uid_dbt, vcard_dbt;
+	int        db_error;
+	
+	string_to_dbt ("populated", &uid_dbt);
+	memset(&vcard_dbt, 0, sizeof(vcard_dbt));
+	vcard_dbt.flags = DB_DBT_MALLOC;
+
+	db_error = db->get (db, NULL, &uid_dbt, &vcard_dbt, 0);
+	if (db_error != 0){
+		return FALSE;
+	}
+	else {
+		free(vcard_dbt.data);
+		return TRUE;
+	}
+}
--- /dev/null	2006-04-11 14:30:05.384262500 +0530
+++ addressbook/libedata-book/e-book-backend-db-cache.h	2006-04-11 10:49:48.000000000 +0530
@@ -0,0 +1,49 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* 
+ * 
+ * Copyright (C) 2004 Novell, Inc.
+ *
+ * Authors: Devashish Sharma <sdevashish@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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef E_BOOK_BACKEND_DB_CACHE_H
+#define E_BOOK_BACKEND_DB_CACHE_H
+
+#include <libebook/e-contact.h>
+#include "db.h"
+
+EContact* e_book_backend_db_cache_get_contact (DB *db, const char *uid);
+void string_to_dbt(const char *str, DBT *dbt);
+char *e_book_backend_db_cache_get_filename(DB *db);
+void e_book_backend_db_cache_set_filename(DB *db, const char *filename);
+gboolean e_book_backend_db_cache_add_contact (DB *db,
+					   EContact *contact);
+gboolean e_book_backend_db_cache_remove_contact (DB *db,
+					      const char *uid);
+gboolean e_book_backend_db_cache_check_contact (DB *db, const char *uid);
+GList*   e_book_backend_db_cache_get_contacts (DB *db, const char *query);
+gboolean e_book_backend_db_cache_exists (const char *uri);
+void     e_book_backend_db_cache_set_populated (DB *db);
+gboolean e_book_backend_db_cache_is_populated (DB *db);
+GPtrArray* e_book_backend_db_cache_search (DB *db, const char *query);
+
+
+
+
+G_END_DECLS
+
+#endif
+
Index: addressbook/libedata-book/Makefile.am
===================================================================
RCS file: /cvs/gnome/evolution-data-server/addressbook/libedata-book/Makefile.am,v
retrieving revision 1.14
diff -u -p -r1.14 Makefile.am
--- addressbook/libedata-book/Makefile.am	22 Jun 2005 12:34:23 -0000	1.14
+++ addressbook/libedata-book/Makefile.am	11 Apr 2006 05:22:41 -0000
@@ -4,6 +4,7 @@ INCLUDES =						\
 	-I$(top_builddir)				\
 	-I$(top_srcdir)/addressbook			\
 	-I$(top_builddir)/addressbook			\
+	-I$(top_srcdir)/libdb/dist			\
         $(EVOLUTION_ADDRESSBOOK_CFLAGS)
 
 # The corba stubs and skels
@@ -38,6 +39,7 @@ libedata_book_1_2_la_SOURCES =				\
 	e-book-backend-sexp.c				\
 	e-book-backend-summary.c			\
 	e-book-backend-cache.c                          \
+	e-book-backend-db-cache.c                       \
 	e-book-backend-sync.c				\
 	e-book-backend.c				\
 	e-data-book-factory.c				\
@@ -48,7 +50,8 @@ libedata_book_1_2_la_SOURCES =				\
 libedata_book_1_2_la_LIBADD =					\
 	$(EVOLUTION_ADDRESSBOOK_LIBS)				\
 	$(top_builddir)/addressbook/libebook/libebook-1.2.la	\
-	$(top_builddir)/libedataserver/libedataserver-1.2.la
+	$(top_builddir)/libedataserver/libedataserver-1.2.la	\
+	$(top_builddir)/libdb/dist/libdb-4.1.la
 
 libedata_book_1_2_la_LDFLAGS = \
 	-version-info $(LIBEDATABOOK_CURRENT):$(LIBEDATABOOK_REVISION):$(LIBEDATABOOK_AGE) $(NO_UNDEFINED)
@@ -66,7 +69,8 @@ libedata_bookinclude_HEADERS =				\
 	e-data-book-types.h				\
 	e-data-book-view.h				\
 	e-data-book.h                                   \
-	e-book-backend-cache.h 								
+	e-book-backend-cache.h 				\
+	e-book-backend-db-cache.h 								
 
 %-$(API_VERSION).pc: %.pc
 	 cp $< $@
openSUSE Build Service is sponsored by