summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Ohly <patrick.ohly@intel.com>2013-04-02 07:36:21 -0700
committerPatrick Ohly <patrick.ohly@intel.com>2013-05-06 16:28:12 +0200
commite3f0a297f7a6799b8f4481b5142e78981ecef4a0 (patch)
treec724f26a7230a9a6fc29263595eb4dd86eacf650
parent065fdcd34382a8bd4537a0f70c9a8b90c67d1bef (diff)
EDS Client: handle "busy" error
In EDS 3.6.4, opening fails a lot more often with E_CLIENT_ERROR_BUSY. We must retry until we succeed. Seen in particular with testpim.py testFilterStartup. Clients are expected to try the open call again. EDS >= 3.8 does that automatically.
-rw-r--r--src/backends/evolution/EvolutionSyncSource.cpp26
-rw-r--r--src/dbus/server/pim/edsf-view.cpp57
2 files changed, 57 insertions, 26 deletions
diff --git a/src/backends/evolution/EvolutionSyncSource.cpp b/src/backends/evolution/EvolutionSyncSource.cpp
index c22d3e93..d94a4448 100644
--- a/src/backends/evolution/EvolutionSyncSource.cpp
+++ b/src/backends/evolution/EvolutionSyncSource.cpp
@@ -89,19 +89,25 @@ EClientCXX EvolutionSyncSource::openESource(const char *extension,
(void *)"Evolution Data Server has died unexpectedly.");
- // Always allow EDS to create the database. "only-if-exists =
- // true" does not make sense.
- if (!e_client_open_sync(client, false, NULL, gerror)) {
- if (created) {
- // Opening newly created address books often failed in old
- // EDS releases - try again.
- gerror.clear();
- sleep(5);
- if (!e_client_open_sync(client, false, NULL, gerror)) {
+ while (true) {
+ // Always allow EDS to create the database. "only-if-exists =
+ // true" does not make sense.
+ if (!e_client_open_sync(client, false, NULL, gerror)) {
+ if (gerror && g_error_matches(gerror, E_CLIENT_ERROR, E_CLIENT_ERROR_BUSY)) {
+ gerror.clear();
+ sleep(1);
+ } else if (created) {
+ // Opening newly created address books often failed in
+ // old EDS releases - try again. Probably covered by
+ // more recently added E_CLIENT_ERROR_BUSY check above.
+ gerror.clear();
+ sleep(5);
+ } else {
throwError("opening database", gerror);
}
} else {
- throwError("opening database", gerror);
+ // Success!
+ break;
}
}
diff --git a/src/dbus/server/pim/edsf-view.cpp b/src/dbus/server/pim/edsf-view.cpp
index eb869a7c..16972f33 100644
--- a/src/dbus/server/pim/edsf-view.cpp
+++ b/src/dbus/server/pim/edsf-view.cpp
@@ -49,6 +49,8 @@ boost::shared_ptr<EDSFView> EDSFView::create(const ESourceRegistryCXX &registry,
void EDSFView::doStart()
{
+ // This function may get entered again, see retry code in opened() below.
+
ESourceCXX source(e_source_registry_ref_source(m_registry, m_uuid.c_str()), false);
if (!source) {
SE_LOG_DEBUG(NULL, NULL, "edsf %s: address book not found", m_uuid.c_str());
@@ -56,23 +58,36 @@ void EDSFView::doStart()
}
m_store = EdsfPersonaStoreCXX::steal(edsf_persona_store_new_with_source_registry(m_registry, source));
GErrorCXX gerror;
- m_ebook = EBookClientCXX::steal(
-#ifdef HAVE_E_BOOK_CLIENT_NEW_DIRECT
- getenv("SYNCEVOLUTION_NO_PIM_EDS_DIRECT") ?
- e_book_client_new(source, gerror) :
- e_book_client_new_direct(m_registry, source, gerror)
-#elif defined(HAVE_E_BOOK_CLIENT_CONNECT_DIRECT_SYNC)
- getenv("SYNCEVOLUTION_NO_PIM_EDS_DIRECT") ?
- e_book_client_new(source, gerror) :
- E_BOOK_CLIENT(e_book_client_connect_direct_sync(m_registry, source, NULL, gerror))
-#else
- e_book_client_new(source, gerror)
+#ifdef HAVE_E_BOOK_CLIENT_CONNECT_DIRECT_SYNC
+ // TODO: use asynchronous version, once there is one in EDS
+ if (!getenv("SYNCEVOLUTION_NO_PIM_EDS_DIRECT")) {
+ while (!m_ebook) {
+ SE_LOG_DEBUG(NULL, NULL, "edsf %s: synchronously connecting direct", m_uuid.c_str());
+ m_ebook = EBookClientCXX::steal(E_BOOK_CLIENT(e_book_client_connect_direct_sync(m_registry, source, NULL, gerror)));
+ if (!m_ebook) {
+ SE_LOG_DEBUG(NULL, NULL, "edsf %s: no DRA client for address book: %s", m_uuid.c_str(), gerror ? gerror->message : "???");
+ if (gerror && g_error_matches(gerror, E_CLIENT_ERROR, E_CLIENT_ERROR_BUSY)) {
+ SE_LOG_DEBUG(NULL, NULL, "edsf %s: try again", m_uuid.c_str());
+ gerror.clear();
+ } else {
+ return;
+ }
+ }
+ }
+ // Already opened by call above, proceed immediately.
+ opened(true, NULL);
+ return;
+ }
#endif
- );
+
+ SE_LOG_DEBUG(NULL, NULL, "edsf %s: new client", m_uuid.c_str());
+ m_ebook = EBookClientCXX::steal(e_book_client_new(source, gerror));
if (!m_ebook) {
- SE_LOG_DEBUG(NULL, NULL, "edfs %s: no client for address book: %s", m_uuid.c_str(), gerror->message);
+ SE_LOG_DEBUG(NULL, NULL, "edsf %s: no normal client for address book: %s", m_uuid.c_str(), gerror ? gerror->message : "???");
return;
}
+
+ SE_LOG_DEBUG(NULL, NULL, "edsf %s: asynchronous open", m_uuid.c_str());
SYNCEVO_GLIB_CALL_ASYNC(e_client_open,
boost::bind(&EDSFView::opened,
m_self,
@@ -87,9 +102,14 @@ void EDSFView::opened(gboolean success, const GError *gerror) throw()
{
try {
if (!success) {
- SE_LOG_DEBUG(NULL, NULL, "edfs %s: opening failed: %s", m_uuid.c_str(), gerror->message);
- return;
+ SE_LOG_DEBUG(NULL, NULL, "edsf %s: opening failed: %s", m_uuid.c_str(), gerror ? gerror->message : "???");
+ if (gerror && g_error_matches(gerror, E_CLIENT_ERROR, E_CLIENT_ERROR_BUSY)) {
+ SE_LOG_DEBUG(NULL, NULL, "edsf %s: try again", m_uuid.c_str());
+ doStart();
+ return;
+ }
}
+ SE_LOG_DEBUG(NULL, NULL, "edsf %s: opened successfully, reading contacts asynchronously: %s", m_uuid.c_str(), m_query.c_str());
SYNCEVO_GLIB_CALL_ASYNC(e_book_client_get_contacts,
boost::bind(&EDSFView::read,
m_self,
@@ -107,9 +127,14 @@ void EDSFView::opened(gboolean success, const GError *gerror) throw()
void EDSFView::read(gboolean success, GSList *contactslist, const GError *gerror) throw()
{
try {
+ SE_LOG_DEBUG(NULL, NULL, "edsf %s: reading contacts completed: %s",
+ m_uuid.c_str(),
+ success ? "success" :
+ gerror ? gerror->message :
+ "failed without error");
GListCXX<EContact, GSList, GObjectDestructor> contacts(contactslist);
if (!success) {
- SE_LOG_DEBUG(NULL, NULL, "edfs %s: reading failed: %s", m_uuid.c_str(), gerror->message);
+ SE_LOG_DEBUG(NULL, NULL, "edsf %s: reading failed: %s", m_uuid.c_str(), gerror->message);
return;
}