From 8ae2141438451c3107c5e3184655a6bf8e25ebd8 Mon Sep 17 00:00:00 2001 From: Chris Toshok Date: Sat, 13 Mar 2004 22:40:45 +0000 Subject: add prototype for e_data_book_view_get_mutex. 2004-03-12 Chris Toshok * libedata-book/e-data-book-view.h: add prototype for e_data_book_view_get_mutex. * libedata-book/e-data-book-view.c (e_data_book_view_get_mutex): new function, return the book view's mutex. (e_data_book_view_dispose): free priv->mutex. (e_data_book_view_init): init priv->mutex. * backends/file/e-book-backend-file.c (closure_destroy): GDestroyNotify to clear up the search closure. (init_closure): initialize the object data we use to store search information (just a "stopped" flag at the moment) (get_closure): return the object data. (e_book_backend_file_start_book_view): add code to deal with the race between start and stop, locking the book_view's mutex around the initial get/set of the closure. also, switch from using g_object_ref to bonobo_object_ref on the book_view, and don't do any freeing of the search closure here. it's handled automatically for us by virtue of the GDestroyNotify. (e_book_backend_file_stop_book_view): flesh this out to fix the race between start/stop. --- addressbook/ChangeLog | 24 ++++++ addressbook/backends/file/e-book-backend-file.c | 102 +++++++++++++++++------- addressbook/libedata-book/e-data-book-view.c | 18 +++++ addressbook/libedata-book/e-data-book-view.h | 23 +++--- 4 files changed, 129 insertions(+), 38 deletions(-) (limited to 'addressbook') diff --git a/addressbook/ChangeLog b/addressbook/ChangeLog index f3e274c09..e26064f1e 100644 --- a/addressbook/ChangeLog +++ b/addressbook/ChangeLog @@ -1,3 +1,27 @@ +2004-03-12 Chris Toshok + + * libedata-book/e-data-book-view.h: add prototype for + e_data_book_view_get_mutex. + + * libedata-book/e-data-book-view.c (e_data_book_view_get_mutex): + new function, return the book view's mutex. + (e_data_book_view_dispose): free priv->mutex. + (e_data_book_view_init): init priv->mutex. + + * backends/file/e-book-backend-file.c (closure_destroy): + GDestroyNotify to clear up the search closure. + (init_closure): initialize the object data we use to store search + information (just a "stopped" flag at the moment) + (get_closure): return the object data. + (e_book_backend_file_start_book_view): add code to deal with the + race between start and stop, locking the book_view's mutex around + the initial get/set of the closure. also, switch from using + g_object_ref to bonobo_object_ref on the book_view, and don't do + any freeing of the search closure here. it's handled + automatically for us by virtue of the GDestroyNotify. + (e_book_backend_file_stop_book_view): flesh this out to fix the + race between start/stop. + 2004-03-12 Chris Toshok * libebook/e-contact.c (e_contact_set_property): in the CATEGORIES diff --git a/addressbook/backends/file/e-book-backend-file.c b/addressbook/backends/file/e-book-backend-file.c index 189fbd129..b3ae524e4 100644 --- a/addressbook/backends/file/e-book-backend-file.c +++ b/addressbook/backends/file/e-book-backend-file.c @@ -32,6 +32,8 @@ #include #include "e-book-backend-file.h" +#define d(x) + #define CHANGES_DB_SUFFIX ".changes.db" #define E_BOOK_BACKEND_FILE_VERSION_NAME "PAS-DB-VERSION" @@ -306,7 +308,7 @@ e_book_backend_file_get_contact_list (EBookBackendSync *backend, const char *search = query; GList *contact_list = NULL; - printf ("e_book_backend_file_get_contact_list (%s)\n", search); + d(printf ("e_book_backend_file_get_contact_list (%s)\n", search)); search_needed = TRUE; @@ -356,11 +358,39 @@ typedef struct { gboolean stopped; } FileBackendSearchClosure; +static void +closure_destroy (FileBackendSearchClosure *closure) +{ + d(printf ("destroying search closure\n")); + g_mutex_free (closure->mutex); + g_free (closure); +} + +static FileBackendSearchClosure* +init_closure (EDataBookView *book_view) +{ + FileBackendSearchClosure *closure = g_new (FileBackendSearchClosure, 1); + + closure->mutex = g_mutex_new(); + closure->stopped = FALSE; + + g_object_set_data_full (G_OBJECT (book_view), "EBookBackendFile.BookView::closure", + closure, (GDestroyNotify)closure_destroy); + + return closure; +} + +static FileBackendSearchClosure* +get_closure (EDataBookView *book_view) +{ + return g_object_get_data (G_OBJECT (book_view), "EBookBackendFile.BookView::closure"); +} + static void e_book_backend_file_start_book_view (EBookBackend *backend, EDataBookView *book_view) { - FileBackendSearchClosure *closure = g_new0 (FileBackendSearchClosure, 1); + FileBackendSearchClosure *closure; EBookBackendFile *bf = E_BOOK_BACKEND_FILE (backend); const char *query; DB *db; @@ -368,19 +398,36 @@ e_book_backend_file_start_book_view (EBookBackend *backend, int db_error; gboolean stopped = FALSE; - printf ("starting initial population of book view\n"); + d(printf ("starting initial population of book view\n")); + + g_mutex_lock (e_data_book_view_get_mutex (book_view)); + + closure = get_closure (book_view); + if (closure) { + /* the only way op can be set here is if we raced with + stop_book_view and lost. make sure by checking + op->stopped. */ + if (!closure->stopped) { + g_warning ("lost race with stop_book_view, but op->stopped != TRUE"); + } + g_object_set_data (G_OBJECT (book_view), "EBookBackendFile.BookView::closure", NULL); + g_mutex_unlock (e_data_book_view_get_mutex (book_view)); + return; + } + else { + closure = init_closure (book_view); + closure->stopped = FALSE; + } /* ref the book view because it'll be removed and unrefed when/if it's stopped */ - g_object_ref (book_view); + bonobo_object_ref (book_view); + g_mutex_unlock (e_data_book_view_get_mutex (book_view)); + db = bf->priv->file_db; query = e_data_book_view_get_card_query (book_view); - closure->mutex = g_mutex_new(); - closure->stopped = FALSE; - g_object_set_data (G_OBJECT (book_view), "EBookBackendFile.BookView::closure", closure); - if ( ! strcmp (query, "(contains \"x-evolution-any-field\" \"\")")) e_data_book_view_notify_status_message (book_view, _("Loading...")); else @@ -398,11 +445,8 @@ e_book_backend_file_start_book_view (EBookBackend *backend, stopped = closure->stopped; g_mutex_unlock (closure->mutex); - if (stopped) { - g_mutex_free (closure->mutex); - g_free (closure); + if (stopped) break; - } string_to_dbt (id, &id_dbt); memset (&vcard_dbt, 0, sizeof (vcard_dbt)); @@ -460,31 +504,35 @@ e_book_backend_file_start_book_view (EBookBackend *backend, if (!stopped) e_data_book_view_notify_complete (book_view, GNOME_Evolution_Addressbook_Success); - g_mutex_free (closure->mutex); - g_free (closure); - - g_object_set_data (G_OBJECT (book_view), "EBookBackendFile.BookView::closure", NULL); - /* unref the */ - g_object_unref (book_view); + bonobo_object_unref (book_view); - printf ("finished initial population of book view\n"); + d(printf ("finished initial population of book view\n")); } static void e_book_backend_file_stop_book_view (EBookBackend *backend, EDataBookView *book_view) { - FileBackendSearchClosure *closure = g_object_get_data (G_OBJECT (book_view), "EBookBackendFile.BookView::closure"); - if (!closure) { - printf ("book view is already done populating\n"); - return; + FileBackendSearchClosure *closure; + + g_mutex_lock (e_data_book_view_get_mutex (book_view)); + + closure = get_closure (book_view); + + if (closure) { + d(printf ("stopping running query!\n")); + g_mutex_lock (closure->mutex); + closure->stopped = TRUE; + g_mutex_unlock (closure->mutex); + } + else { + d(printf ("either the query is already finished or hasn't started yet (we won the race)\n")); + closure = init_closure (book_view); + closure->stopped = TRUE; } - printf ("stopping book view!\n"); - g_mutex_lock (closure->mutex); - closure->stopped = TRUE; - g_mutex_unlock (closure->mutex); + g_mutex_unlock (e_data_book_view_get_mutex (book_view)); } typedef struct { diff --git a/addressbook/libedata-book/e-data-book-view.c b/addressbook/libedata-book/e-data-book-view.c index 584110a96..a7fff0da1 100644 --- a/addressbook/libedata-book/e-data-book-view.c +++ b/addressbook/libedata-book/e-data-book-view.c @@ -16,6 +16,8 @@ #include "e-book-backend-sexp.h" #include "e-data-book-view.h" +#define d(x) + static BonoboObjectClass *e_data_book_view_parent_class; struct _EDataBookViewPrivate { @@ -24,6 +26,8 @@ struct _EDataBookViewPrivate { #define INITIAL_THRESHOLD 20 #define THRESHOLD_MAX 3000 + GMutex *mutex; + GMutex *pending_mutex; CORBA_sequence_GNOME_Evolution_Addressbook_VCard adds; @@ -373,6 +377,7 @@ impl_GNOME_Evolution_Addressbook_BookView_dispose (PortableServer_Servant servan { EDataBookView *view = E_DATA_BOOK_VIEW (bonobo_object (servant)); + d(printf("in impl_GNOME_Evolution_Addressbook_BookView_dispose\n")); ORBit_small_unlisten_for_broken (e_data_book_view_get_listener (view), G_CALLBACK (view_listener_died_cb)); bonobo_object_unref (view); @@ -408,6 +413,14 @@ e_data_book_view_get_backend (EDataBookView *book_view) return book_view->priv->backend; } +GMutex* +e_data_book_view_get_mutex (EDataBookView *book_view) +{ + g_return_val_if_fail (E_IS_DATA_BOOK_VIEW (book_view), NULL); + + return book_view->priv->mutex; +} + GNOME_Evolution_Addressbook_BookViewListener e_data_book_view_get_listener (EDataBookView *book_view) { @@ -441,6 +454,7 @@ e_data_book_view_dispose (GObject *object) { EDataBookView *book_view = E_DATA_BOOK_VIEW (object); + d(printf ("disposing of EDataBookView\n")); if (book_view->priv) { bonobo_object_release_unref (book_view->priv->listener, NULL); @@ -457,6 +471,9 @@ e_data_book_view_dispose (GObject *object) g_mutex_free (book_view->priv->pending_mutex); book_view->priv->pending_mutex = NULL; + g_mutex_free (book_view->priv->mutex); + book_view->priv->mutex = NULL; + g_free (book_view->priv); book_view->priv = NULL; } @@ -489,6 +506,7 @@ e_data_book_view_init (EDataBookView *book_view) book_view->priv = g_new0 (EDataBookViewPrivate, 1); book_view->priv->pending_mutex = g_mutex_new(); + book_view->priv->mutex = g_mutex_new(); book_view->priv->next_threshold = INITIAL_THRESHOLD; book_view->priv->threshold_max = THRESHOLD_MAX; diff --git a/addressbook/libedata-book/e-data-book-view.h b/addressbook/libedata-book/e-data-book-view.h index 6eb4411a9..4b13061a7 100644 --- a/addressbook/libedata-book/e-data-book-view.h +++ b/addressbook/libedata-book/e-data-book-view.h @@ -40,24 +40,25 @@ struct _EDataBookViewClass { }; -EDataBookView *e_data_book_view_new (EBookBackend *backend, - GNOME_Evolution_Addressbook_BookViewListener listener, - const char *card_query, - EBookBackendSExp *card_sexp); +EDataBookView *e_data_book_view_new (EBookBackend *backend, + GNOME_Evolution_Addressbook_BookViewListener listener, + const char *card_query, + EBookBackendSExp *card_sexp); -const char* e_data_book_view_get_card_query (EDataBookView *book_view); -EBookBackendSExp* e_data_book_view_get_card_sexp (EDataBookView *book_view); -EBookBackend* e_data_book_view_get_backend (EDataBookView *book_view); +const char* e_data_book_view_get_card_query (EDataBookView *book_view); +EBookBackendSExp* e_data_book_view_get_card_sexp (EDataBookView *book_view); +EBookBackend* e_data_book_view_get_backend (EDataBookView *book_view); GNOME_Evolution_Addressbook_BookViewListener e_data_book_view_get_listener (EDataBookView *book_view); +GMutex* e_data_book_view_get_mutex (EDataBookView *book_view); void e_data_book_view_notify_update (EDataBookView *book_view, - EContact *contact); + EContact *contact); void e_data_book_view_notify_remove (EDataBookView *book_view, - const char *id); + const char *id); void e_data_book_view_notify_complete (EDataBookView *book_view, - GNOME_Evolution_Addressbook_CallStatus); + GNOME_Evolution_Addressbook_CallStatus); void e_data_book_view_notify_status_message (EDataBookView *book_view, - const char *message); + const char *message); GType e_data_book_view_get_type (void); -- cgit v1.2.1