Index: calendar/ChangeLog
===================================================================
--- calendar/ChangeLog	(revision 9511)
+++ calendar/ChangeLog	(working copy)
@@ -1,3 +1,21 @@
+2008-09-11  Milan Crha  <mcrha@redhat.com>
+
+	** Fix for bug #501298
+
+	* backends/contacts/e-cal-backend-contacts.c:
+	(struct _ECalBackendContactsPrivate), (init_sources_cb),
+	(e_cal_backend_contacts_open), (e_cal_backend_contacts_finalize),
+	(e_cal_backend_contacts_init): Make _open function quick as much
+	as possible, to not block the sync_backend lock for long, thus other
+	threads can work with it too.
+	* backends/contacts/e-cal-backend-contacts.c: (book_record_new),
+	(add_source): Do not search a book when it wasn't opened correctly.
+	* backends/contacts/e-cal-backend-contacts.c: (contact_record_new),
+	(contact_record_free), (contact_record_cb_new): Do not ref/unref
+	backend in a structure which backend holds itself.
+	* libecal/e-cal.c: (cal_read_only_cb):
+	There is no operation for this, thus do not steal other operation.
+
 2008-09-05  Andre Klapper  <a9016009@gmx.de>
 
 	* libedata-cal/e-cal-backend-util.c: 
Index: calendar/backends/contacts/e-cal-backend-contacts.c
===================================================================
--- calendar/backends/contacts/e-cal-backend-contacts.c	(revision 9511)
+++ calendar/backends/contacts/e-cal-backend-contacts.c	(working copy)
@@ -32,6 +32,7 @@
 
 #include <glib/gi18n-lib.h>
 #include "libedataserver/e-xml-hash-utils.h"
+#include "libedataserver/e-flag.h"
 #include <libecal/e-cal-recur.h>
 #include <libecal/e-cal-util.h>
 #include <libedata-cal/e-cal-backend-util.h>
@@ -55,6 +56,8 @@ struct _ECalBackendContactsPrivate {
 
 	GHashTable *zones;
 	icaltimezone *default_zone;
+
+	EFlag   *init_done_flag; /* is set, when the init thread gone */
 };
 
 typedef struct _BookRecord {
@@ -91,9 +94,17 @@ book_record_new (ECalBackendContacts *cb
         EBookQuery *query;
         EBookView  *book_view;
         BookRecord *br;
+	GError     *error = NULL;
 
 	book = e_book_new (source, NULL);
-        e_book_open (book, TRUE, NULL);
+        if (!book || !e_book_open (book, TRUE, &error) || error) {
+		g_object_unref (book);
+		if (error) {
+			g_warning ("%s: Failed to open book, error: %s", G_STRFUNC, error->message);
+			g_error_free (error);
+		}
+		return NULL;
+	}
 
         /* Create book view */
         fields = g_list_append (fields, (char*)e_contact_field_name (E_CONTACT_FILE_AS));
@@ -142,7 +153,7 @@ contact_record_new (ECalBackendContacts 
         ContactRecord *cr = g_new0 (ContactRecord, 1);
 	char *comp_str;
 
-        cr->cbc = g_object_ref (cbc);
+        cr->cbc = cbc;
         cr->contact = contact;
         cr->comp_birthday = create_birthday (cbc, contact);
         cr->comp_anniversary = create_anniversary (cbc, contact);
@@ -198,7 +209,6 @@ contact_record_free (ContactRecord *cr)
 		g_object_unref (G_OBJECT (cr->comp_anniversary));
 	}
 
-	g_object_unref (cr->cbc);
         g_free (cr);
 }
 
@@ -214,7 +224,7 @@ contact_record_cb_new (ECalBackendContac
 {
         ContactRecordCB *cb_data = g_new (ContactRecordCB, 1);
 
-        cb_data->cbc = g_object_ref (cbc);
+        cb_data->cbc = cbc;
         cb_data->sexp = sexp;
         cb_data->result = NULL;
 
@@ -254,6 +264,9 @@ add_source (ECalBackendContacts *cbc, ES
         BookRecord *br = book_record_new (cbc, source);
         const char *uid = e_source_peek_uid (source);
 
+	if (!br)
+		return;
+
         g_hash_table_insert (cbc->priv->addressbooks, g_strdup (uid), br);
 }
 
@@ -721,6 +734,32 @@ e_cal_backend_contacts_is_read_only (ECa
 	return GNOME_Evolution_Calendar_Success;
 }
 
+static gpointer
+init_sources_cb (ECalBackendContacts *cbc)
+{
+        ECalBackendContactsPrivate *priv;
+        GSList *i;
+
+	g_return_val_if_fail (cbc != NULL, FALSE);
+
+	priv = cbc->priv;
+
+	/* Create address books for existing sources */
+        for (i = e_source_list_peek_groups (priv->addressbook_sources); i; i = i->next) {
+                ESourceGroup *source_group = E_SOURCE_GROUP (i->data);
+
+                source_group_added_cb (priv->addressbook_sources, source_group, cbc);
+        }
+
+        /* Listen for source list changes */
+        g_signal_connect (priv->addressbook_sources, "group_added", G_CALLBACK (source_group_added_cb), cbc);
+        g_signal_connect (priv->addressbook_sources, "group_removed", G_CALLBACK (source_group_removed_cb), cbc);
+
+	e_flag_set (priv->init_done_flag);
+
+	return NULL;
+}
+
 static ECalBackendSyncStatus
 e_cal_backend_contacts_open (ECalBackendSync *backend, EDataCal *cal,
 			     gboolean only_if_exists,
@@ -728,8 +767,7 @@ e_cal_backend_contacts_open (ECalBackend
 {
         ECalBackendContacts *cbc = E_CAL_BACKEND_CONTACTS (backend);
         ECalBackendContactsPrivate *priv = cbc->priv;
-
-        GSList *i;
+	GError *error = NULL;
 
         if (priv->addressbook_loaded)
                 return GNOME_Evolution_Calendar_Success;
@@ -743,18 +781,18 @@ e_cal_backend_contacts_open (ECalBackend
 		g_hash_table_insert (priv->zones, g_strdup (icaltimezone_get_tzid (zone)), zone);
 	}
 
-	/* Create address books for existing sources */
-        for (i = e_source_list_peek_groups (priv->addressbook_sources); i; i = i->next) {
-                ESourceGroup *source_group = E_SOURCE_GROUP (i->data);
-
-                source_group_added_cb (priv->addressbook_sources, source_group, cbc);
-        }
+	/* initialize addressbook sources in new thread to make this function quick as much as possible */
+	if (!g_thread_create ((GThreadFunc)init_sources_cb, cbc, FALSE, &error)) {
+		e_flag_set (priv->init_done_flag);
+		g_warning ("%s: Cannot create thread to initialize sources! (%s)", G_STRFUNC, error ? error->message : "Unknown error");
+		if (error)
+			g_error_free (error);
 
-        /* Listen for source list changes */
-        g_signal_connect (priv->addressbook_sources, "group_added", G_CALLBACK (source_group_added_cb), cbc);
-        g_signal_connect (priv->addressbook_sources, "group_removed", G_CALLBACK (source_group_removed_cb), cbc);
+		return GNOME_Evolution_Calendar_OtherError;
+	}
 
         priv->addressbook_loaded = TRUE;
+
         return GNOME_Evolution_Calendar_Success;
 }
 
@@ -948,6 +986,12 @@ e_cal_backend_contacts_finalize (GObject
 	cbc = E_CAL_BACKEND_CONTACTS (object);
 	priv = cbc->priv;
 
+	if (priv->init_done_flag) {
+		e_flag_wait (priv->init_done_flag);
+		e_flag_free (priv->init_done_flag);
+		priv->init_done_flag = NULL;
+	}
+
 	if (priv->default_zone && priv->default_zone != icaltimezone_get_utc_timezone ()) {
 		icaltimezone_free (priv->default_zone, 1);
 	}
@@ -982,6 +1026,7 @@ e_cal_backend_contacts_init (ECalBackend
 
 	priv->zones = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, free_zone);
 	priv->default_zone = icaltimezone_get_utc_timezone ();
+	priv->init_done_flag = e_flag_new ();
 
 	cbc->priv = priv;
 
Index: calendar/libecal/e-cal.c
===================================================================
--- calendar/libecal/e-cal.c	(revision 9511)
+++ calendar/libecal/e-cal.c	(working copy)
@@ -435,19 +435,10 @@ static void
 cal_read_only_cb (ECalListener *listener, ECalendarStatus status, gboolean read_only, gpointer data)
 {
 	ECal *ecal = data;
-	ECalendarOp *op;
-
-	op = e_calendar_get_op (ecal);
 
-	if (op == NULL || !op->bool) {
-		ecal->priv->read_only = read_only;
-		return;
-	}
-
-	op->status = status;
-	op->bool = read_only;
-
-	e_flag_set (op->done);
+	/* readonly information comes asynchronously,
+	   without operation, so no check here for that */
+	ecal->priv->read_only = read_only;
 }
 
 static void
