Hi,

I implemented asynchronous ECal opening in KCal-EDS. I would
appreciate if you could review the patch attached.

***
    EDSStorage: Make ECal calendar opening asynchronous

    Use e_cal_open_async() instead of e_cal_open() to open the ECal
    calendar asynchronously and avoid blocking on
    EStorage::localStorage() or EStorage::defaultStorage() calls.

    If startLoading() is called while the ECal is still being opened
    asynchronously, the loading will be delayed until the ECal is open.

    This change does not change the public API in any way and does not
    require any change in clients.
***

Kr,

-- 
Dr. Christophe Dumez
Linux Software Engineer
Intel Finland Oy - Open Source Technology Center
From 36dd475ce3f7d0cb217e3476fbbff5ca725f7b40 Mon Sep 17 00:00:00 2001
From: Christophe Dumez <[email protected]>
Date: Fri, 17 Jun 2011 16:13:04 +0300
Subject: [PATCH] EDSStorage: Make ECal calendar opening asynchronous

Use e_cal_open_async() instead of e_cal_open() to open the ECal
calendar asynchronously and avoid blocking on
EStorage::localStorage() or EStorage::defaultStorage() calls.

If startLoading() is called while the ECal is still being opened
asynchronously, the loading will be delayed until the ECal is open.

This change does not change the public API in any way and does not
require any change in clients.
---
 src/eds-storage.cpp |   85 ++++++++++++++++++++++++++++++--------------------
 src/eds-storage.h   |   17 ++++++++++
 2 files changed, 68 insertions(+), 34 deletions(-)

diff --git a/src/eds-storage.cpp b/src/eds-storage.cpp
index 6b1f6a7..5182f8a 100644
--- a/src/eds-storage.cpp
+++ b/src/eds-storage.cpp
@@ -90,7 +90,7 @@ namespace eKCalImpl {
     }
 
     EDSStorage::EDSStorage() :
-        m_icalFormat(&m_icalFormatMain)
+        m_ecalStatus(NOT_OPENED), m_loadingPending(false), m_icalFormat(&m_icalFormatMain)
     {
       g_type_init();
     }
@@ -126,22 +126,9 @@ namespace eKCalImpl {
             return false;
         }
 
-        // TODO (?): define a non-blocking way of creating EStorage,
-        // use e_cal_open_async() here. Probably not that relevant
-        // for local calendars.
-        GErrorCXX gerror;
-        if (!e_cal_open(m_database.get(),
-                        false, // open even if it has to be created
-                        gerror)) {
-            EKCAL_CRITICAL() << "e_cal_open failed" << gerror;
-            return false;
-        }
-
-        if (!e_cal_get_static_capability(m_database.get(),
-                                         CAL_STATIC_CAPABILITY_REMOVE_ONLY_THIS)) {
-            EKCAL_CRITICAL() << "system storage does not support CAL_STATIC_CAPABILITY_REMOVE_ONLY_THIS, needed for KCal-EDS";
-            return false;
-        }
+        m_ecalStatus = OPENING;
+        g_signal_connect(m_database.get(), "cal_opened_ex", G_CALLBACK(calendarOpened), this);
+        e_cal_open_async(m_database.get(), false);
 
         return true;
     }
@@ -243,28 +230,45 @@ namespace eKCalImpl {
         return false;
       }
 
-      // TODO (?): define a non-blocking way of creating EStorage,
-      // use e_cal_open_async() here. Probably not that relevant
-      // for local calendars.
-      GErrorCXX gerror;
-      EKCAL_DEBUG() << "Calling e_cal_open() on database" << EDS_LOCAL_STORAGE_PREFIX+id
+      EKCAL_DEBUG() << "Calling e_cal_open_async() on database" << EDS_LOCAL_STORAGE_PREFIX+id
                        << "with create boolean at" << create;
-      if (!e_cal_open(m_database.get(),
-                      !create,
-                      gerror)) {
-          EKCAL_CRITICAL() << "e_cal_open failed" << gerror;
-          return false;
-      }
-
-      if (!e_cal_get_static_capability(m_database.get(),
-                                       CAL_STATIC_CAPABILITY_REMOVE_ONLY_THIS)) {
-          EKCAL_CRITICAL() << "local storage does not support CAL_STATIC_CAPABILITY_REMOVE_ONLY_THIS, needed for KCal-EDS";
-          return false;
-      }
+      m_ecalStatus = OPENING;
+      g_signal_connect(m_database.get(), "cal_opened_ex", G_CALLBACK(calendarOpened), this);
+      e_cal_open_async(m_database.get(), !create);
 
       return true;
     }
 
+    void EDSStorage::calendarOpened(ECal *ecal, const GError *error, EDSStorage *that)
+    {
+      Q_UNUSED(ecal);
+      EKCAL_DEBUG() << Q_FUNC_INFO << "Success:" << (error == NULL);
+      if (error != NULL) {
+        that->setEcalStatus(ECAL_FAILURE);
+        if (that->calendarLoadingPending()) {
+            // No point trying to load, the calendar could not be opened
+            that->loadingComplete(false, QString::fromUtf8(error->message));
+        }
+      } else {
+        // Opened successfully, now check its capabilities...
+        if (e_cal_get_static_capability(ecal,
+                                        CAL_STATIC_CAPABILITY_REMOVE_ONLY_THIS)) {
+           that->setEcalStatus(OPENED);
+           if (that->calendarLoadingPending()) {
+               // Call startLoading() again now that ECal is ready
+               that->startLoading();
+           }
+        } else {
+            EKCAL_CRITICAL() << "local storage does not support CAL_STATIC_CAPABILITY_REMOVE_ONLY_THIS, needed for KCal-EDS";
+            that->setEcalStatus(ECAL_FAILURE);
+            if (that->calendarLoadingPending()) {
+                // No point trying to load, the calendar could not be opened
+                that->loadingComplete(false, tr("Local storage does not support %1").arg("CAL_STATIC_CAPABILITY_REMOVE_ONLY_THIS"));
+            }
+        }
+      }
+    }
+
     void EDSStorage::registerObserver(StorageObserver *observer)
     {
         if (!m_observers.contains(observer))
@@ -286,6 +290,18 @@ namespace eKCalImpl {
 
     void EDSStorage::startLoading()
     {
+        // Make sure the calendar is open
+        if (m_ecalStatus == ECAL_FAILURE) {
+          loadingComplete(false, tr("ECal could not be opened"));
+          return;
+        }
+        if (m_ecalStatus != OPENED) {
+          EKCAL_DEBUG() << "The calendar is not done opening yet, delaying the loading...";
+          m_loadingPending = true;
+          return;
+        }
+        m_loadingPending = false;
+
         // clean up before populating anew;
         // resolves to deleteAllEvents/Todos/Journals
         (m_calendar.data()->*m_calendarDeleteAll)();
@@ -440,6 +456,7 @@ namespace eKCalImpl {
             }
         }
     }
+
     void EDSStorage::objectsModified(ECalView *ecalview,
                                      GList *icomps,
                                      EDSStorage *that)
diff --git a/src/eds-storage.h b/src/eds-storage.h
index 841bcf6..c03936f 100644
--- a/src/eds-storage.h
+++ b/src/eds-storage.h
@@ -86,6 +86,7 @@ namespace eKCalImpl {
         virtual void startLoading();
         virtual void stopLoading();
         virtual void save();
+
     private:
         /** for some operations we need to know the type of items */
         KCalCore::IncidenceBase::IncidenceType m_type;
@@ -97,6 +98,19 @@ namespace eKCalImpl {
 
         /** Evolution calendar */
         ECalCXX m_database;
+
+        enum ECalStatus { NOT_OPENED, OPENED, ECAL_FAILURE, OPENING };
+        /** Status of the ECal calendar */
+        ECalStatus m_ecalStatus;
+        /** Return the status of the ECal calendar */
+        inline ECalStatus ecalStatus() const { return m_ecalStatus; }
+        /** Set the status of the ECal calendar */
+        inline void setEcalStatus(ECalStatus status) { m_ecalStatus = status; }
+        /** Is the storage supposed to be loaded once the calendar is opened */
+        bool m_loadingPending;
+        /** Indicate if the storage supposed to be loaded once the calendar is opened */
+        inline bool calendarLoadingPending() const { return m_loadingPending; }
+
         /**
          * initial loading and updating, created in startLoading(),
          * destroyed in stopLoading()
@@ -163,6 +177,9 @@ namespace eKCalImpl {
         typedef QMap<QString, UIDChanges> Changes;
         Changes m_changes;
         
+        /* ECal callbacks */
+        static void calendarOpened(ECal *ecal, const GError *error, EDSStorage *that);
+
         /* ECalView callbacks */
         static void objectsAdded(ECalView *ecalview,
                                  GList *icomps,
-- 
1.7.4.4

_______________________________________________
MeeGo-dev mailing list
[email protected]
http://lists.meego.com/listinfo/meego-dev
http://wiki.meego.com/Mailing_list_guidelines

Reply via email to