[evolution-couchdb] Add a cache for contacts



commit f975ee23c372bfb8d78fba19b8c7123649d1b2b8
Author: Rodrigo Moya <rodrigo gnome-db org>
Date:   Wed Apr 21 16:10:39 2010 +0200

    Add a cache for contacts

 addressbook/e-book-backend-couchdb.c |  209 +++++++++++++++++-----------------
 addressbook/e-book-backend-couchdb.h |    2 +
 2 files changed, 107 insertions(+), 104 deletions(-)
---
diff --git a/addressbook/e-book-backend-couchdb.c b/addressbook/e-book-backend-couchdb.c
index 5861462..b8718f9 100644
--- a/addressbook/e-book-backend-couchdb.c
+++ b/addressbook/e-book-backend-couchdb.c
@@ -46,8 +46,8 @@ get_current_time (gchar time_string[100])
 		strftime (time_string, 100, "%Y-%m-%dT%H:%M:%SZ", tm);
 }
 
-static char *
-vcard_from_couch_document (CouchdbDocument *document)
+static EContact *
+contact_from_couch_document (CouchdbDocument *document)
 {
 	EContact *contact;
 	char *str;
@@ -480,12 +480,7 @@ vcard_from_couch_document (CouchdbDocument *document)
 		e_contact_set (contact, E_CONTACT_REV, time_string);
 	}
 
-	/* convert the contact to a VCARD string to be returned */
-	str = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
-
-	g_object_unref (G_OBJECT (contact));
-
-	return str;
+	return contact;
 }
 
 static CouchdbStructField *
@@ -945,24 +940,22 @@ couch_document_from_contact (EBookBackendCouchDB *couchdb_backend, EContact *con
 static void
 document_updated_cb (CouchdbSession *couchdb, const char *dbname, CouchdbDocument *document, gpointer user_data)
 {
-	char *vcard;
 	EContact *contact;
 	EBookBackendCouchDB *couchdb_backend = E_BOOK_BACKEND_COUCHDB (user_data);
 
 	if (g_strcmp0 (dbname, couchdb_backend->dbname) != 0)
 		return;
 
-	vcard = vcard_from_couch_document (document);
-	if (!vcard)
+	contact = contact_from_couch_document (document);
+	if (!contact)
 		return;
 
-	contact = e_contact_new_from_vcard (vcard);
-	if (contact != NULL) {
-		e_book_backend_notify_update (E_BOOK_BACKEND (couchdb_backend), contact);
-		g_object_unref (G_OBJECT (contact));
-	}
+	e_book_backend_notify_update (E_BOOK_BACKEND (couchdb_backend), contact);
+
+	/* Add the contact to the cache */
+	e_book_backend_cache_add_contact (couchdb_backend->cache, contact);
 
-	g_free (vcard);
+	g_object_unref (G_OBJECT (contact));
 }
 
 static void
@@ -974,6 +967,9 @@ document_deleted_cb (CouchdbSession *couchdb, const char *dbname, const char *do
 		return;
 
 	e_book_backend_notify_remove (E_BOOK_BACKEND (couchdb_backend), docid);
+
+	/* Remove the contact from the cache */
+	e_book_backend_cache_remove_contact (couchdb_backend->cache, docid);
 }
 
 static GNOME_Evolution_Addressbook_CallStatus
@@ -985,14 +981,17 @@ e_book_backend_couchdb_load_source (EBookBackend *backend,
 	const gchar *property;
 	CouchdbDatabaseInfo *db_info;
 	GError *error = NULL;
+	GSList *doc_list, *sl;
 	EBookBackendCouchDB *couchdb_backend = E_BOOK_BACKEND_COUCHDB (backend);
 
 	g_return_val_if_fail (E_IS_BOOK_BACKEND_COUCHDB (couchdb_backend), GNOME_Evolution_Addressbook_OtherError);
 
-	if (couchdb_backend->couchdb)
-		g_object_unref (couchdb_backend->couchdb);
-	if (couchdb_backend->dbname)
+	if (couchdb_backend->couchdb != NULL)
+		g_object_unref (G_OBJECT (couchdb_backend->couchdb));
+	if (couchdb_backend->dbname != NULL)
 		g_free (couchdb_backend->dbname);
+	if (couchdb_backend->cache != NULL)
+		g_object_unref (G_OBJECT (couchdb_backend->cache));
 
 	/* create CouchDB main object */
 	couchdb_backend->dbname = g_strdup ("contacts");
@@ -1014,7 +1013,7 @@ e_book_backend_couchdb_load_source (EBookBackend *backend,
 
 		if (! (couchdb_backend->couchdb = couchdb_session_new (uri))) {
 			g_free (uri);
-			return GNOME_Evolution_Addressbook_OtherError;
+			return GNOME_Evolution_Addressbook_NoSuchBook;
 		}
 
 		g_free (uri);
@@ -1047,8 +1046,41 @@ e_book_backend_couchdb_load_source (EBookBackend *backend,
 	} else
 		couchdb_database_info_unref (db_info);
 
-	e_book_backend_set_is_loaded (backend, TRUE);
-	e_book_backend_set_is_writable (backend, TRUE);
+	/* Create cache */
+	uri = e_source_get_uri (source);
+	couchdb_backend->cache = e_book_backend_cache_new ((const gchar *) uri);
+	g_free (uri);
+
+	/* Populate the cache */
+	e_book_backend_cache_clean (couchdb_backend->cache);
+	error = NULL;
+	doc_list = couchdb_session_list_documents (couchdb_backend->couchdb,
+						   couchdb_backend->dbname,
+						   &error);
+	for (sl = doc_list; sl != NULL; sl = sl->next) {
+		EContact *contact;
+		CouchdbDocument *document;
+		CouchdbDocumentInfo *doc_info = (CouchdbDocumentInfo *) sl->data;
+
+		/* Retrieve this document */
+		error = NULL;
+		document = couchdb_document_get (couchdb_backend->couchdb,
+						 couchdb_backend->dbname,
+						 couchdb_document_info_get_docid (doc_info),
+						 &error);
+		if (!document)
+			continue;
+
+		contact = contact_from_couch_document (document);
+		if (contact != NULL) {
+			e_book_backend_cache_add_contact (couchdb_backend->cache, contact);
+			g_object_unref (G_OBJECT (contact));
+		}
+
+		g_object_unref (G_OBJECT (document));
+	}
+
+	couchdb_session_free_document_list (doc_list);
 
 	/* Listen for changes on database */
 	g_signal_connect (G_OBJECT (couchdb_backend->couchdb), "document_created",
@@ -1059,6 +1091,9 @@ e_book_backend_couchdb_load_source (EBookBackend *backend,
 			  G_CALLBACK (document_deleted_cb), couchdb_backend);
 	couchdb_session_listen_for_changes (couchdb_backend->couchdb, couchdb_backend->dbname);
 
+	e_book_backend_set_is_loaded (backend, TRUE);
+	e_book_backend_set_is_writable (backend, TRUE);
+
 	return GNOME_Evolution_Addressbook_Success;
 }
 
@@ -1067,6 +1102,12 @@ e_book_backend_couchdb_remove (EBookBackend *backend, EDataBook *book, guint32 o
 {
 	EBookBackendCouchDB *couchdb_backend = E_BOOK_BACKEND_COUCHDB (backend);
 
+	/* Remove the cache */
+	if (couchdb_backend->cache != NULL) {
+		g_object_unref (G_OBJECT (couchdb_backend->cache));
+		couchdb_backend->cache = NULL;
+	}
+
 	/* We don't remove data from CouchDB, since it would affect other apps,
 	   so just report success */
 	e_data_book_respond_remove (book, opid, GNOME_Evolution_Addressbook_Success);
@@ -1085,13 +1126,12 @@ put_document (EBookBackendCouchDB *couchdb_backend, CouchdbDocument *document)
 
 	if (couchdb_document_put (document, couchdb_backend->dbname, &error)) {
 		EContact *new_contact;
-		char *vcard_str;
 
 		/* couchdb_document_put sets the ID for new documents, so need to send that back */
-		vcard_str = vcard_from_couch_document (document);
-		new_contact = e_contact_new_from_vcard (vcard_str);
+		new_contact = contact_from_couch_document (document);
 
-		g_free (vcard_str);
+		/* Add the new contact to the cache */
+		e_book_backend_cache_add_contact (couchdb_backend->cache, new_contact);
 
 		return new_contact;
 	} else {
@@ -1178,9 +1218,10 @@ e_book_backend_couchdb_remove_contacts (EBookBackend *backend,
 				desktopcouch_document_set_application_annotations (document, app_annotations);
 
 				/* Now put the new revision of the document */
-				if (couchdb_document_put (document, couchdb_backend->dbname, &error))
+				if (couchdb_document_put (document, couchdb_backend->dbname, &error)) {
 					deleted_ids = g_list_append (deleted_ids, (gpointer) uid);
-				else {
+					e_book_backend_cache_remove_contact (couchdb_backend->cache, uid);
+				} else {
 					if (error != NULL) {
 						g_debug ("Error deleting document: %s", error->message);
 						g_error_free (error);
@@ -1193,9 +1234,10 @@ e_book_backend_couchdb_remove_contacts (EBookBackend *backend,
 				couchdb_struct_field_unref (u1_annotations);
 				couchdb_struct_field_unref (private_annotations);
 			} else {
-				if (couchdb_document_delete (document, &error))
+				if (couchdb_document_delete (document, &error)) {
 					deleted_ids = g_list_append (deleted_ids, (gpointer) uid);
-				else {
+					e_book_backend_cache_remove_contact (couchdb_backend->cache, uid);
+				} else {
 					if (error != NULL) {
 						g_debug ("Error deleting document: %s", error->message);
 						g_error_free (error);
@@ -1263,18 +1305,15 @@ e_book_backend_couchdb_get_contact (EBookBackend *backend,
 				    const char *id)
 {
 	GError *error = NULL;
-	CouchdbDocument *document;
+	EContact *contact;
 	EBookBackendCouchDB *couchdb_backend = E_BOOK_BACKEND_COUCHDB (backend);
 
-	document = couchdb_document_get (couchdb_backend->couchdb,
-					 couchdb_backend->dbname,
-					 id,
-					 &error);
-	if (document) {
-		char *vcard = vcard_from_couch_document (document);
+	contact = e_book_backend_cache_get_contact (couchdb_backend->cache, id);
+	if (contact != NULL) {
+		char *vcard = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
 
-		g_object_unref (G_OBJECT (document));
-		if (vcard) {
+		g_object_unref (G_OBJECT (contact));
+		if (vcard != NULL) {
 			e_data_book_respond_get_contact (book,
 							 opid,
 							 GNOME_Evolution_Addressbook_Success,
@@ -1292,51 +1331,24 @@ e_book_backend_couchdb_get_contact_list (EBookBackend *backend,
 					 EDataBook *book,
 					 guint32 opid, const char *query)
 {
-	GSList *doc_list, *sl;
-	GList *contacts = NULL;
+	GList *doc_list, *contacts = NULL;
 	GError *error = NULL;
-	EBookBackendSExp *card_sexp = NULL;
 	EBookBackendCouchDB *couchdb_backend = E_BOOK_BACKEND_COUCHDB (backend);
 
-	card_sexp = e_book_backend_sexp_new (query);
-	if (!card_sexp) {
-		/* XXX this needs to be an invalid query error of some sort*/
-		e_data_book_respond_get_contact_list (book, opid, GNOME_Evolution_Addressbook_OtherError, NULL);
-		return;
-	}
-
-	/* Get the list of documents from CouchDB */
-	doc_list = couchdb_session_list_documents (couchdb_backend->couchdb,
-						   couchdb_backend->dbname,
-						   &error);
-	for (sl = doc_list; sl != NULL; sl = sl->next) {
+	/* Get the list of documents from cache */
+	doc_list = e_book_backend_cache_get_contacts (couchdb_backend->cache, query);
+	while (doc_list != NULL) {
 		char *vcard;
-		CouchdbDocument *document;
-		CouchdbDocumentInfo *doc_info = (CouchdbDocumentInfo *) sl->data;
+		EContact *contact = E_CONTACT (doc_list->data);
 
-		/* Retrieve this document */
-		error = NULL;
-		document = couchdb_document_get (couchdb_backend->couchdb,
-						 couchdb_backend->dbname,
-						 couchdb_document_info_get_docid (doc_info),
-						 &error);
-		if (!document)
-			continue;
+		vcard = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
+		if (vcard != NULL)
+			contacts = g_list_prepend (contacts, vcard);
 
-		vcard = vcard_from_couch_document (document);
-		if (vcard != NULL) {
-			if (e_book_backend_sexp_match_vcard (card_sexp, vcard))
-				contacts = g_list_prepend (contacts, vcard);
-			else
-				g_free (vcard);
-		}
-
-		g_object_unref (G_OBJECT (document));
+		doc_list = g_list_remove (doc_list, contact);
+		g_object_unref (G_OBJECT (contact));
 	}
 
-	g_object_unref (card_sexp);
-	couchdb_session_free_document_list (doc_list);
-
 	e_data_book_respond_get_contact_list (book, opid, GNOME_Evolution_Addressbook_Success, contacts);
 }
 
@@ -1344,45 +1356,28 @@ static void
 e_book_backend_couchdb_start_book_view (EBookBackend *backend,
 					EDataBookView *book_view)
 {
-	EBookBackendSExp *sexp;
-	GError *error;
-	GSList *doc_list, *sl;
+	GList *doc_list;
 	EBookBackendCouchDB *couchdb_backend = E_BOOK_BACKEND_COUCHDB (backend);
 
 	e_book_backend_add_book_view (backend, book_view);
-	sexp = e_data_book_view_get_card_sexp  (book_view);
 
-	/* Get the list of documents from CouchDB */
-	doc_list = couchdb_session_list_documents (couchdb_backend->couchdb,
-						   couchdb_backend->dbname,
-						   &error);
-	for (sl = doc_list; sl != NULL; sl = sl->next) {
-		CouchdbDocument *document;
+	/* Get the list of documents from cache */
+	doc_list = e_book_backend_cache_get_contacts (couchdb_backend->cache,
+						      e_data_book_view_get_card_query (book_view));
+	while (doc_list != NULL) {
 		char *vcard;
-		CouchdbDocumentInfo *doc_info = (CouchdbDocumentInfo *) sl->data;
+		EContact *contact = E_CONTACT (doc_list->data);
 
-		/* Retrieve this document */
-		error = NULL;
-		document = couchdb_document_get (couchdb_backend->couchdb,
-						 couchdb_backend->dbname,
-						 couchdb_document_info_get_docid (doc_info),
-						 &error);
-		if (!document)
-			continue;
-
-		vcard = vcard_from_couch_document (document);
+		vcard = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
 		if (!vcard)
 			continue;
 
-		if (e_book_backend_sexp_match_vcard (sexp, (const gchar *) vcard))
-			e_data_book_view_notify_update_vcard (book_view, vcard);
-		else
-			g_free (vcard);
+		e_data_book_view_notify_update_vcard (book_view, vcard);
 
-		g_object_unref (G_OBJECT (document));
+		doc_list = g_list_remove (doc_list, contact);
+		g_object_unref (G_OBJECT (contact));
 	}
 
-	couchdb_session_free_document_list (doc_list);
 	e_data_book_view_notify_complete (book_view, GNOME_Evolution_Addressbook_Success);
 }
 
@@ -1555,6 +1550,11 @@ e_book_backend_couchdb_dispose (GObject *object)
 		couchdb_backend->couchdb = NULL;
 	}
 
+	if (couchdb_backend->cache != NULL) {
+		g_object_unref (G_OBJECT (couchdb_backend->cache));
+		couchdb_backend->cache = NULL;
+	}
+
 	if (couchdb_backend->dbname) {
 		g_free (couchdb_backend->dbname);
 		couchdb_backend->dbname = NULL;
@@ -1596,4 +1596,5 @@ e_book_backend_couchdb_init (EBookBackendCouchDB *backend)
 {
 	backend->couchdb = NULL;
 	backend->dbname = NULL;
+	backend->cache = NULL;
 }
diff --git a/addressbook/e-book-backend-couchdb.h b/addressbook/e-book-backend-couchdb.h
index 89989e3..4e1966b 100644
--- a/addressbook/e-book-backend-couchdb.h
+++ b/addressbook/e-book-backend-couchdb.h
@@ -26,6 +26,7 @@
 #include <couchdb-glib.h>
 #include <desktopcouch-glib.h>
 #include <libedata-book/e-book-backend.h>
+#include <libedata-book/e-book-backend-cache.h>
 
 #define E_TYPE_BOOK_BACKEND_COUCHDB        (e_book_backend_couchdb_get_type ())
 #define E_BOOK_BACKEND_COUCHDB(o)          (G_TYPE_CHECK_INSTANCE_CAST ((o), E_TYPE_BOOK_BACKEND_COUCHDB, EBookBackendCouchDB))
@@ -38,6 +39,7 @@ typedef struct {
 	EBookBackend parent_object;
 
 	CouchdbSession *couchdb;
+	EBookBackendCache *cache;
 	char *dbname;
 	gboolean using_desktopcouch;
 } EBookBackendCouchDB;



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