Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:jberkman
evolution-exchange-2.6
gal-db-fix.diff
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File gal-db-fix.diff of Package evolution-exchange-2.6
--- addressbook/e-book-backend-gal-copy.c 2006-12-21 15:21:44.000000000 +0530 +++ addressbook/e-book-backend-gal.c 2006-12-21 14:49:20.000000000 +0530 @@ -28,6 +28,8 @@ #include <stdlib.h> #include <fcntl.h> #include <string.h> +#include <time.h> +#include <errno.h> #include <glib/gprintf.h> #include <e2k-utils.h> @@ -44,18 +46,22 @@ #undef LDAP_DEBUG #endif -#define d(x) x +#define d(x) #include <sys/time.h> #include <libedataserver/e-sexp.h> +#include <libedataserver/e-db3-utils.h> +#include <libedataserver/e-data-server-util.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 "e-book-backend-db-cache.h" +#include "libedata-book/e-book-backend-summary.h" #include "e-book-backend-gal.h" +#include "db.h" /* interval for our poll_ldap timeout */ #define LDAP_POLL_INTERVAL 20 @@ -84,7 +90,6 @@ struct _EBookBackendGALPrivate { LDAP *ldap; ExchangeAccount *account; - EBookBackendCache *cache; gboolean marked_for_offline; GMutex *ldap_lock; @@ -94,8 +99,22 @@ struct _EBookBackendGALPrivate { int active_ops; int mode; int poll_timeout; + DB *file_db; + DB_ENV *env; + + /* Summary */ + char *summary_file_name; + gboolean is_summary_ready; + EBookBackendSummary *summary; }; +#define SUMMARY_FLUSH_TIMEOUT 5000 +static GStaticMutex global_env_lock = G_STATIC_MUTEX_INIT; +static struct { + int ref_count; + DB_ENV *env; +} global_env; + typedef void (*LDAPOpHandler)(LDAPOp *op, LDAPMessage *res); typedef void (*LDAPOpDtor)(LDAPOp *op); @@ -299,8 +318,6 @@ ldap_op_add (LDAPOp *op, EBookBackend *b op->handler = handler; op->dtor = dtor; - d(printf ("(ldap_op_add): active operations %d \n", bl->priv->active_ops + 1)); - g_static_rec_mutex_lock (&bl->priv->op_hash_mutex); if (g_hash_table_lookup (bl->priv->id_to_op, &op->id)) { g_warning ("conflicting ldap msgid's"); @@ -327,7 +344,7 @@ ldap_op_finished (LDAPOp *op) g_static_rec_mutex_lock (&bl->priv->op_hash_mutex); g_hash_table_remove (bl->priv->id_to_op, &op->id); - + /* should handle errors here */ g_mutex_lock (bl->priv->ldap_lock); if (bl->priv->ldap) @@ -343,8 +360,6 @@ ldap_op_finished (LDAPOp *op) g_source_remove (bl->priv->poll_timeout); bl->priv->poll_timeout = -1; } - - d(printf ("(ldap_op_finished): active operations %d \n", bl->priv->active_ops)); g_static_rec_mutex_unlock (&bl->priv->op_hash_mutex); } @@ -506,8 +521,8 @@ get_contact (EBookBackend *backend, printf("get contact\n"); switch (bl->priv->mode) { case GNOME_Evolution_Addressbook_MODE_LOCAL: - if (bl->priv->marked_for_offline && bl->priv->cache) { - EContact *contact = e_book_backend_cache_get_contact (bl->priv->cache, id); + if (bl->priv->marked_for_offline && bl->priv->file_db) { + EContact *contact = e_book_backend_db_cache_get_contact (bl->priv->file_db, id); gchar *vcard_str; if (!contact) { @@ -531,8 +546,8 @@ get_contact (EBookBackend *backend, case GNOME_Evolution_Addressbook_MODE_REMOTE : printf("Mode:Remote\n"); - if (bl->priv->marked_for_offline && bl->priv->cache) { - EContact *contact = e_book_backend_cache_get_contact (bl->priv->cache, id); + if (bl->priv->marked_for_offline && bl->priv->file_db) { + EContact *contact = e_book_backend_db_cache_get_contact (bl->priv->file_db, id); gchar *vcard_str ; if (!contact) { e_data_book_respond_get_contact (book, opid, GNOME_Evolution_Addressbook_OtherError, ""); @@ -706,12 +721,12 @@ get_contact_list (EBookBackend *backend, printf("get contact list\n"); switch (bl->priv->mode) { case GNOME_Evolution_Addressbook_MODE_LOCAL: - if (bl->priv->marked_for_offline && bl->priv->cache) { + if (bl->priv->marked_for_offline && bl->priv->file_db) { GList *contacts; GList *vcard_strings = NULL; GList *l; - contacts = e_book_backend_cache_get_contacts (bl->priv->cache, query); + contacts = e_book_backend_db_cache_get_contacts (bl->priv->file_db, query); for (l = contacts; l; l = g_list_next (l)) { EContact *contact = l->data; @@ -731,12 +746,12 @@ get_contact_list (EBookBackend *backend, case GNOME_Evolution_Addressbook_MODE_REMOTE: printf("Mode : Remote\n"); - if (bl->priv->marked_for_offline && bl->priv->cache) { + if (bl->priv->marked_for_offline && bl->priv->file_db) { GList *contacts; GList *vcard_strings = NULL; GList *l; - contacts = e_book_backend_cache_get_contacts (bl->priv->cache, query); + contacts = e_book_backend_db_cache_get_contacts (bl->priv->file_db, query); for (l = contacts; l ;l = g_list_next (l)) { EContact *contact = l->data; @@ -1326,9 +1341,6 @@ poll_ldap (EBookBackendGAL *bl) timeout.tv_sec = 0; timeout.tv_usec = LDAP_RESULT_TIMEOUT_MILLIS * 1000; - d(printf ("(poll_ldap): Active operations %d, ldap %p, poll timeout %d, timeout %ld \n", bl->priv->active_ops, ldap, - bl->priv->poll_timeout, timeout.tv_usec)); - g_mutex_lock (bl->priv->ldap_lock); rc = ldap_result (ldap, LDAP_RES_ANY, 0, &timeout, &res); g_mutex_unlock (bl->priv->ldap_lock); @@ -1379,8 +1391,9 @@ ldap_search_handler (LDAPOp *op, LDAPMes int msg_type; d(printf ("ldap_search_handler (%p)\n", view)); - + printf("%s(%d):%s: search handler \n", __FILE__, __LINE__, __PRETTY_FUNCTION__); if (!ldap) { + printf("%s(%d):%s: other error\n", __FILE__, __LINE__, __PRETTY_FUNCTION__); e_data_book_view_notify_complete (view, GNOME_Evolution_Addressbook_OtherError); ldap_op_finished (op); return; @@ -1418,6 +1431,7 @@ ldap_search_handler (LDAPOp *op, LDAPMes NULL, &ldap_error_msg, NULL, NULL, 0); g_mutex_unlock (bl->priv->ldap_lock); if (ldap_error != LDAP_SUCCESS) { + printf("%s(%d):%s: error result\n", __FILE__, __LINE__, __PRETTY_FUNCTION__); g_warning ("ldap_search_handler: %02X (%s), additional info: %s", ldap_error, ldap_err2string (ldap_error), ldap_error_msg); @@ -1432,7 +1446,7 @@ ldap_search_handler (LDAPOp *op, LDAPMes e_data_book_view_notify_complete (view, GNOME_Evolution_Addressbook_Success); else e_data_book_view_notify_complete (view, GNOME_Evolution_Addressbook_OtherError); - + printf("%s(%d):%s: o/p %d %d\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, ldap_error, LDAP_SUCCESS); ldap_op_finished (op); } else { @@ -1459,6 +1473,30 @@ ldap_search_dtor (LDAPOp *op) } static void +get_contacts_from_cache (EBookBackendGAL *ebg, + const char *query, + GPtrArray *ids, + EDataBookView *book_view) + +{ + int i; + + for (i = 0; i < ids->len; i ++) { + char *uid = g_ptr_array_index (ids, i); + + + EContact *contact = + e_book_backend_db_cache_get_contact (ebg->priv->file_db, uid); + if (contact) { + e_data_book_view_notify_update (book_view, contact); + g_object_unref (contact); + } + } + e_data_book_view_notify_complete (book_view, + GNOME_Evolution_Addressbook_Success); +} + +static void start_book_view (EBookBackend *backend, EDataBookView *view) { @@ -1474,12 +1512,12 @@ start_book_view (EBookBackend *backend, printf("start book view\n"); switch (bl->priv->mode) { case GNOME_Evolution_Addressbook_MODE_LOCAL: - if (!(bl->priv->marked_for_offline && bl->priv->cache)) { + if (!(bl->priv->marked_for_offline && bl->priv->file_db)) { e_data_book_view_notify_complete (view, GNOME_Evolution_Addressbook_RepositoryOffline); return; } - contacts = e_book_backend_cache_get_contacts (bl->priv->cache, + contacts = e_book_backend_db_cache_get_contacts (bl->priv->file_db, e_data_book_view_get_card_query (view)); for (l = contacts; l; l = g_list_next (l)) { @@ -1495,9 +1533,11 @@ start_book_view (EBookBackend *backend, case GNOME_Evolution_Addressbook_MODE_REMOTE: printf("Mode:Remote\n"); - if (bl->priv->marked_for_offline && bl->priv->cache) { + if (bl->priv->marked_for_offline && bl->priv->file_db) { + char *query = e_data_book_view_get_card_query (view); + GPtrArray *ids = NULL; printf("Marked for offline and cache present\n"); - + status = build_query (bl, e_data_book_view_get_card_query (view), &ldap_query); if (status != GNOME_Evolution_Addressbook_Success || !ldap_query) { @@ -1506,9 +1546,21 @@ start_book_view (EBookBackend *backend, g_free (ldap_query); return; } - contacts = e_book_backend_cache_get_contacts (bl->priv->cache, - e_data_book_view_get_card_query (view)); - + + if (bl->priv->is_summary_ready && + e_book_backend_summary_is_summary_query (bl->priv->summary, query)) { + printf("Summary ready and summary_query, searching from summary \n"); + ids = e_book_backend_summary_search (bl->priv->summary, query); + if (ids && ids->len > 0) { + get_contacts_from_cache (bl, query, ids, view); + g_ptr_array_free (ids, TRUE); + } + return; + } + + + contacts = e_book_backend_db_cache_get_contacts (bl->priv->file_db, + e_data_book_view_get_card_query (view)); for (l = contacts; l ;l = g_list_next (l)) { EContact *contact = l->data; e_data_book_view_notify_update (view, contact); @@ -1523,6 +1575,7 @@ start_book_view (EBookBackend *backend, else { printf("Not marked for offline or cache not there\n"); if (!bl->priv->ldap) { + printf("%s(%d):%s: no ldap :(\n", __FILE__, __LINE__, __PRETTY_FUNCTION__); e_data_book_view_notify_complete (view, GNOME_Evolution_Addressbook_InvalidQuery); return; @@ -1541,11 +1594,12 @@ start_book_view (EBookBackend *backend, status = build_query (bl, e_data_book_view_get_card_query (view), &ldap_query); - + printf("%s(%d):%s: %s\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, ldap_query); if (status != GNOME_Evolution_Addressbook_Success || !ldap_query) { e_data_book_view_notify_complete (view, status); if (ldap_query) g_free (ldap_query); + printf("%s(%d):%s: failure \n", __FILE__, __LINE__, __PRETTY_FUNCTION__); return; } @@ -1553,6 +1607,7 @@ start_book_view (EBookBackend *backend, book_view_notify_status (view, _("Searching...")); g_mutex_lock (bl->priv->ldap_lock); + printf("%s(%d):%s: starting \n", __FILE__, __LINE__, __PRETTY_FUNCTION__); ldap_err = ldap_search_ext (bl->priv->ldap, LDAP_ROOT_DSE, LDAP_SCOPE_SUBTREE, ldap_query, @@ -1563,15 +1618,18 @@ start_book_view (EBookBackend *backend, view_limit, &search_msgid); g_mutex_unlock (bl->priv->ldap_lock); + printf("%s(%d):%s: %d\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, ldap_err); } while (gal_reconnect (bl, view, ldap_err)); g_free (ldap_query); if (ldap_err != LDAP_SUCCESS) { + printf("%s(%d):%s: error\n", __FILE__, __LINE__, __PRETTY_FUNCTION__); book_view_notify_status (view, ldap_err2string(ldap_err)); return; } else if (search_msgid == -1) { + printf("%s(%d):%s: error\n", __FILE__, __LINE__, __PRETTY_FUNCTION__); book_view_notify_status (view, _("Error performing search")); return; @@ -1580,7 +1638,7 @@ start_book_view (EBookBackend *backend, LDAPSearchOp *op = g_new0 (LDAPSearchOp, 1); d(printf ("adding search_op (%p, %d)\n", view, search_msgid)); - + printf("%s(%d):%s: adding search \n", __FILE__, __LINE__, __PRETTY_FUNCTION__); op->view = view; bonobo_object_ref (view); @@ -1617,68 +1675,6 @@ get_changes (EBookBackend *backend, /* FIXME: implement */ } -/* -static void -generate_cache_handler (LDAPOp *op, LDAPMessage *res) -{ - LDAPGetContactListOp *contact_list_op = (LDAPGetContactListOp *) op; - EBookBackendGAL *bl = E_BOOK_BACKEND_GAL (op->backend); - LDAP *ldap = bl->priv->ldap; - LDAPMessage *e; - gint msg_type; - - if (!ldap) { - ldap_op_finished (op); - return; - } - - msg_type = ldap_msgtype (res); - if (msg_type == LDAP_RES_SEARCH_ENTRY) { - e = ldap_first_entry(ldap, res); - - while (e != NULL) { - EContact *contact = build_contact_from_entry (bl, e, NULL); - - contact_list_op->contacts = g_list_prepend (contact_list_op->contacts, contact); - e = ldap_next_entry(ldap, e); - } - } else if (msg_type == LDAP_RES_SEARCH_RESULT) { - GList *l; - - e_file_cache_clean (E_FILE_CACHE (bl->priv->cache)); - e_file_cache_freeze_changes (E_FILE_CACHE (bl->priv->cache)); - - for (l = contact_list_op->contacts; l; l = g_list_next (l)) { - EContact *contact = l->data; - e_book_backend_cache_add_contact (bl->priv->cache, contact); - } - e_book_backend_cache_set_populated(bl->priv->cache); - time_t t1 = time (NULL); - char t[15] ; - g_sprintf (t," %d", (int)t1); - e_book_backend_cache_set_time (bl->priv->cache, t); - e_file_cache_thaw_changes (E_FILE_CACHE (bl->priv->cache)); - - ldap_op_finished (op); - } - -} - -static void -generate_cache_dtor (LDAPOp *op) -{ - LDAPGetContactListOp *contact_list_op = (LDAPGetContactListOp *) op; - GList *l; - - for (l = contact_list_op->contacts; l; l = g_list_next (l)) { - g_object_unref (l->data); - } - - g_list_free (contact_list_op->contacts); - g_free (contact_list_op); -} -*/ - static int pagedResults = 1; static ber_int_t pageSize = 1000; static ber_int_t entriesLeft = 0; @@ -1766,7 +1762,6 @@ parse_page_control( } tag = ber_scanf( ber, "{im}", &entriesLeft, &servercookie ); - printf ("Entries Left %d\n", entriesLeft); ber_dupbv( cookie, &servercookie ); (void) ber_free( ber, 1 ); @@ -1787,10 +1782,9 @@ parse_page_control( morePagedResults = 0; } if (cookie->bv_len>0) { - printf("Cookie there\n"); + printf("\n"); } else { - printf ("Coooooooooooookie length zero\n"); morePagedResults = 0; } @@ -1816,8 +1810,6 @@ static int dosearch( ber_int_t msgid; static int count = 0; - printf ("do search \n"); - rc = ldap_search_ext( ld, base, scope, value, attrs, attrsonly, sctrls, cctrls, timeout, -1 /*LDAP_NO_LIMIT*/, &msgid ); @@ -1839,13 +1831,12 @@ static int dosearch( case LDAP_RES_SEARCH_ENTRY: count ++; EContact *contact = build_contact_from_entry (bl, msg, NULL); - e_book_backend_cache_add_contact (bl->priv->cache, contact); + e_book_backend_db_cache_add_contact (bl->priv->file_db, contact); + e_book_backend_summary_add_contact (bl->priv->summary, contact); g_object_unref (contact); - printf ("Count :%d\n", count); break; case LDAP_RES_SEARCH_RESULT: - printf("LDAP_RES_SEARCH_RESULT..................\n"); if ( pageSize != 0 ) { rc = parse_page_control( ld, msg, &cookie ); } @@ -1880,16 +1871,13 @@ generate_cache (EBookBackendGAL *book_ba priv = book_backend_gal->priv; + npagedresponses = npagedentries = npagedreferences = npagedextended = npagedpartial = 0; build_query (book_backend_gal, "(beginswith \"file_as\" \"\")", &ldap_query); - /*Clean the file cache before populating it again*/ - e_file_cache_freeze_changes (E_FILE_CACHE (priv->cache)); - e_file_cache_clean (E_FILE_CACHE (priv->cache)); - getNextPage: @@ -1924,41 +1912,25 @@ getNextPage: /* loop to get the next set of entries */ - printf("morePagedResults :%d\n", morePagedResults); if ( (pageSize !=0 ) && (morePagedResults != 0)) { - printf ("start next iteration\n"); + printf ("Start next iteration\n"); goto getNextPage; } + else + printf ("All the entries fetched and finished building the cache\n"); /* Set the cache to populated and thaw the changes */ - e_book_backend_cache_set_populated (priv->cache); + e_book_backend_db_cache_set_populated (priv->file_db); time_t t1 = time (NULL); char t[15] ; g_sprintf (t," %d", (int)t1); - e_book_backend_cache_set_time (priv->cache, t); - e_file_cache_thaw_changes (E_FILE_CACHE (priv->cache)); + e_book_backend_db_cache_set_time (priv->file_db, t); + priv->is_summary_ready = TRUE; + book_backend_gal->priv->file_db->sync (book_backend_gal->priv->file_db, 0); -// do { -// g_mutex_lock (priv->ldap_lock); -// ldap_error = ldap_search_ext (priv->ldap, LDAP_ROOT_DSE, -// LDAP_SCOPE_SUBTREE, -// ldap_query, -// NULL, 0, NULL, NULL, -// NULL, /* XXX timeout */ -// LDAP_NO_LIMIT, &contact_list_msgid); -// g_mutex_unlock (priv->ldap_lock); -// } while (gal_reconnect (book_backend_gal, NULL, ldap_error)); - g_free (ldap_query); -// if (ldap_error == LDAP_SUCCESS) { -// ldap_op_add ((LDAPOp*) contact_list_op, (EBookBackend *) book_backend_gal, NULL /* book */, -// NULL /* book_view */, 0 /* opid */, contact_list_msgid, -// generate_cache_handler, generate_cache_dtor); -// } else { -// generate_cache_dtor ((LDAPOp *) contact_list_op); -// } } static void @@ -1966,13 +1938,92 @@ authenticate_user (EBookBackend *backend EDataBook *book, guint32 opid, const char *user, - const char *passwd, + const char *password, const char *auth_method) { + EBookBackendGAL *be = E_BOOK_BACKEND_GAL (backend); + EBookBackendGALPrivate *bepriv = be->priv; + ExchangeAccountResult result; + ExchangeAccount *account; + GNOME_Evolution_Addressbook_CallStatus res; + GConfClient *gc = gconf_client_get_default(); + int interval = gconf_client_get_int (gc, "/apps/evolution/addressbook/gal_cache_interval", NULL); + + /* We should not be here */ +/* e_data_book_respond_authenticate_user (book, */ +/* opid, */ +/* GNOME_Evolution_Addressbook_UnsupportedAuthenticationMethod); */ +/* return; */ + + d(printf("authenticate_user(%p, %p, %s, %s, %s)\n", backend, book, user, password, auth_method)); + + switch (bepriv->mode) { + + case GNOME_Evolution_Addressbook_MODE_LOCAL: + e_book_backend_notify_writable (E_BOOK_BACKEND (backend), FALSE); + e_book_backend_notify_connection_status (E_BOOK_BACKEND (backend), FALSE); + e_data_book_respond_authenticate_user (book, opid, GNOME_Evolution_Addressbook_Success); + return; + + case GNOME_Evolution_Addressbook_MODE_REMOTE: + + account = exchange_component_get_account_for_uri (global_exchange_component, NULL); + /* FIXME : Check for failures */ + if (!exchange_account_get_context (account)) { + exchange_account_set_online (account); + if(!exchange_account_connect (account, password, &result)) { + printf("%s(%d):%s: failed\n", __FILE__, __LINE__, __PRETTY_FUNCTION__); + e_data_book_respond_authenticate_user (book, opid, GNOME_Evolution_Addressbook_AuthenticationFailed); + return; + } + } + + res = gal_connect (be); + if (res != GNOME_Evolution_Addressbook_Success) { + e_data_book_respond_authenticate_user (book, opid, res); + return; + } + + if (be->priv->marked_for_offline) { + if (e_book_backend_db_cache_is_populated (be->priv->file_db) ) { + printf("Cache is populated, check if refresh is required \n"); + time_t t1, t2; + int diff; + + char *t = e_book_backend_db_cache_get_time (be->priv->file_db); + if (t && *t) + t1 = atoi (t); + else + t1=0; + t2 = time (NULL); + diff = interval * 24 * 60 *60; + /* We have a day specified, then we cache it. */ + if (!diff || t2 - t1 > diff) { + printf ("Cache older than specified period, refreshing \n"); + generate_cache (be); + } + else + be->priv->is_summary_ready= TRUE; + } + else { + printf("Cache not there, generate cache\n"); + generate_cache(be); + } + } + + e_data_book_respond_authenticate_user (book, opid, GNOME_Evolution_Addressbook_Success); + return; + + default: + break; + } + + /* We should not be here */ e_data_book_respond_authenticate_user (book, opid, GNOME_Evolution_Addressbook_UnsupportedAuthenticationMethod); + return; } static void @@ -2030,7 +2081,7 @@ set_mode (EBookBackend *backend, int mod gal_connect (be); e_book_backend_notify_auth_required (backend); - if (bepriv->marked_for_offline && bepriv->cache) + if (bepriv->marked_for_offline && bepriv->file_db) generate_cache (be); } } @@ -2071,6 +2122,7 @@ get_supported_auth_methods (EBookBackend guint32 opid) { + printf("%s(%d):%s: NONE\n", __FILE__, __LINE__, __PRETTY_FUNCTION__); e_data_book_respond_get_supported_auth_methods (book, opid, GNOME_Evolution_Addressbook_Success, @@ -2084,11 +2136,15 @@ load_source (EBookBackend *backend, { EBookBackendGAL *bl = E_BOOK_BACKEND_GAL (backend); GConfClient *gc = gconf_client_get_default(); - GNOME_Evolution_Addressbook_CallStatus result; const char *host; + char **tokens; const char *offline; char *uri; - int interval = gconf_client_get_int (gc, "/apps/evolution/addressbook/gal_cache_interval", NULL); + char *book_name; + char *dirname, *filename; + int i, db_error; + DB *db; + DB_ENV *env; g_object_unref (gc); g_return_val_if_fail (bl->priv->connected == FALSE, GNOME_Evolution_Addressbook_OtherError); @@ -2106,15 +2162,24 @@ load_source (EBookBackend *backend, if (strncmp (uri, "gal://", host - uri)) return GNOME_Evolution_Addressbook_OtherError; - bl->priv->gal_uri = uri; - - if (bl->priv->cache) { - g_object_unref (bl->priv->cache); - bl->priv->cache = NULL; + bl->priv->gal_uri = g_strdup (uri); + tokens = g_strsplit (uri, ";", 2); + g_free (uri); + if (tokens[0]) + uri = g_strdup (tokens [0]); + book_name = g_strdup (tokens[1]); + if (book_name == NULL) + return GNOME_Evolution_Addressbook_OtherError; + g_strfreev (tokens); + + for (i=0; i< strlen (uri); i++) { + switch (uri[i]) { + case ':' : + case '/' : + uri[i] = '_'; + } } - bl->priv->cache = e_book_backend_cache_new (uri); - if (bl->priv->mode == GNOME_Evolution_Addressbook_MODE_LOCAL) { /* Offline */ @@ -2127,38 +2192,127 @@ load_source (EBookBackend *backend, return GNOME_Evolution_Addressbook_Success; } + if (bl->priv->marked_for_offline) { - /* Online */ + bl->priv->summary_file_name = g_build_filename (g_get_home_dir(), ".evolution/cache/addressbook" , uri, book_name, NULL); + bl->priv->summary_file_name = g_build_filename (bl->priv->summary_file_name, "cache.summary", NULL); + bl->priv->summary = e_book_backend_summary_new (bl->priv->summary_file_name, + SUMMARY_FLUSH_TIMEOUT); + e_book_backend_summary_load (bl->priv->summary); + + dirname = g_build_filename (g_get_home_dir(), ".evolution/cache/addressbook", uri, book_name, NULL); + filename = g_build_filename (dirname, "cache.db", NULL); - result = gal_connect (bl); - if (result != GNOME_Evolution_Addressbook_Success) - return result; + 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; + } - if (bl->priv->marked_for_offline) { - if (e_book_backend_cache_is_populated (bl->priv->cache) ) { - printf("Cache is populated, check if refresh is required \n"); - time_t t1, t2; - int diff; - - char *t = e_book_backend_cache_get_time (bl->priv->cache); - t1 = (t && *t) ? atoi (t): 0; - t2 = time (NULL); - diff = interval * 24 * 60 *60; - printf("Interval:%d, diff:%d\n", interval, diff); - printf("t2:%d, t1:%d\n", t2 , t1); - /* We have a day specified, then we cache it. */ - if (!diff || t2 - t1 > diff) { - printf ("Cache older than 1 day, refreshing \n"); - generate_cache (bl); - } + g_static_mutex_lock (&global_env_lock); + if (global_env.ref_count > 0) { + env = global_env.env; + global_env.ref_count ++; } else { - printf("Cache not there, generate cache\n"); - generate_cache(bl); + 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); + + bl->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); + } + + bl->priv->file_db = db; + if (db_error != 0) { + int rv; + + /* the database 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); + } + } + + bl->priv->file_db = db; + + if (db_error != 0 || bl->priv->file_db == NULL) { + + g_free (filename); + g_free (dirname); + return GNOME_Evolution_Addressbook_OtherError; } + + e_book_backend_db_cache_set_filename (bl->priv->file_db, filename); + g_free (filename); + g_free (dirname); + g_free (uri); } - return result; + /* Online */ + e_book_backend_set_is_writable (E_BOOK_BACKEND(backend), FALSE); + e_book_backend_set_is_loaded (E_BOOK_BACKEND (backend), TRUE); + e_book_backend_notify_writable (backend, FALSE); + e_book_backend_notify_connection_status (E_BOOK_BACKEND (backend), TRUE); + + return GNOME_Evolution_Addressbook_Success; + + +// return result; } static void @@ -2214,15 +2368,10 @@ dispose (GObject *object) { EBookBackendGAL *bl = E_BOOK_BACKEND_GAL (object); - d(printf ("ldap Dispose\n")); - if (bl->priv) { g_static_rec_mutex_lock (&bl->priv->op_hash_mutex); - g_hash_table_foreach_remove (bl->priv->id_to_op, (GHRFunc)call_dtor, NULL); g_hash_table_destroy (bl->priv->id_to_op); - bl->priv->active_ops = 0; - g_static_rec_mutex_unlock (&bl->priv->op_hash_mutex); g_static_rec_mutex_free (&bl->priv->op_hash_mutex); @@ -2232,20 +2381,37 @@ dispose (GObject *object) } g_mutex_lock (bl->priv->ldap_lock); - if (bl->priv->ldap) { + if (bl->priv->ldap) ldap_unbind (bl->priv->ldap); - bl->priv->ldap = NULL; - } g_mutex_unlock (bl->priv->ldap_lock); if (bl->priv->gc) g_object_unref (bl->priv->gc); - if (bl->priv->cache) - g_object_unref (bl->priv->cache); if (bl->priv->ldap_lock) g_mutex_free (bl->priv->ldap_lock); + if (bl->priv->summary_file_name) { + g_free (bl->priv->summary_file_name); + bl->priv->summary_file_name = NULL; + } + + if (bl->priv->summary) { + e_book_backend_summary_save (bl->priv->summary); + g_object_unref (bl->priv->summary); + bl->priv->summary = NULL; + } + + if (bl->priv->file_db) + bl->priv->file_db->close (bl->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); g_free (bl->priv->gal_uri); g_free (bl->priv); Index: addressbook/Makefile.am =================================================================== RCS file: /cvs/gnome/evolution-exchange/addressbook/Makefile.am,v retrieving revision 1.9 diff -u -p -r1.9 Makefile.am --- addressbook/Makefile.am 1 Dec 2006 10:51:35 -0000 1.9 +++ addressbook/Makefile.am 15 Dec 2006 10:49:33 -0000 @@ -4,6 +4,7 @@ INCLUDES = \ $(LIBEXCHANGE_CFLAGS) \ -I$(top_srcdir) \ -I$(top_srcdir)/storage \ + "-I /usr/include" \ $(LDAP_CFLAGS) # GConf schemas @@ -23,6 +24,7 @@ install-data-local: fi noinst_LTLIBRARIES = libexchangeaddressbook.la +DB_LIBS=-L/usr/lib -ldb libexchangeaddressbook_la_SOURCES = \ e-book-backend-exchange.c \ @@ -31,8 +33,16 @@ libexchangeaddressbook_la_SOURCES = \ e-book-backend-exchange-factory.h \ e-book-backend-gal.c \ e-book-backend-gal.h \ + e-book-backend-db-cache.c \ + e-book-backend-db-cache.h \ e-book-backend-gal-factory.c \ e-book-backend-gal-factory.h + +libexchangeaddressbook_la_LIBADD = \ + $(DB_LIBS) + +libexchangeaddressbook_la_LDFLAGS = \ + -module -avoid-version $(NO_UNDEFINED) EXTRA_DIST = \ $(schema_in_files) --- /dev/null 2006-06-16 18:37:58.000000000 +0530 +++ addressbook/e-book-backend-db-cache.c 2006-12-12 15:58:52.000000000 +0530 @@ -0,0 +1,454 @@ +/* -*- 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 <libedata-book/e-book-backend.h> +#include <libedata-book/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; + } +} + +void +e_book_backend_db_cache_set_time(DB *db, const char *t) +{ + DBT uid_dbt, vcard_dbt ; + int db_error ; + + string_to_dbt ("last_update_time", &uid_dbt); + string_to_dbt (t, &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); + } +} + +char * +e_book_backend_db_cache_get_time (DB *db) +{ + DBT uid_dbt, vcard_dbt; + int db_error; + char *t; + + string_to_dbt ("last_update_time", &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 { + t = g_strdup (vcard_dbt.data); + g_free (vcard_dbt.data); + return t; + } +} + +/** + * 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-06-16 18:37:58.000000000 +0530 +++ addressbook/e-book-backend-db-cache.h 2006-12-12 15:42:09.000000000 +0530 @@ -0,0 +1,51 @@ +/* -*- 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); +char *e_book_backend_db_cache_get_time(DB *db); +void e_book_backend_db_cache_set_time(DB *db, const char *time); +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 +
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor