7e0e61d87c
git-svn-id: https://zeitsenke.de/svn/SyncEvolution/trunk@314 15ad00c4-1369-45f4-8270-35d70d36bdcd
532 lines
18 KiB
Diff
532 lines
18 KiB
Diff
This patch demonstrates how switching from the current, synchronous
|
|
to the corresponding asynchronous API could work. This helps to
|
|
avoid some timeouts with EDS-DBus, but not all: the e_book_async_get_changes()
|
|
call still times out.
|
|
|
|
Index: src/EvolutionContactSource.cpp
|
|
===================================================================
|
|
RCS file: /cvsroot/sync4jevolution/sync4jevolution/src/EvolutionContactSource.cpp,v
|
|
retrieving revision 1.50
|
|
diff -c -r1.50 EvolutionContactSource.cpp
|
|
*** src/EvolutionContactSource.cpp 3 Jan 2007 20:58:41 -0000 1.50
|
|
--- src/EvolutionContactSource.cpp 22 Feb 2007 19:27:50 -0000
|
|
***************
|
|
*** 27,32 ****
|
|
--- 27,33 ----
|
|
#ifdef ENABLE_EBOOK
|
|
|
|
#include "EvolutionContactSource.h"
|
|
+ #include <libebook/e-book-view.h>
|
|
|
|
#include <common/base/Log.h>
|
|
#include "vocl/VConverter.h"
|
|
***************
|
|
*** 154,159 ****
|
|
--- 155,207 ----
|
|
}
|
|
}
|
|
|
|
+ void EvolutionContactSource::addContacts(void *custom, GList *nextItem)
|
|
+ {
|
|
+ EvolutionContactSource *source = (EvolutionContactSource *)custom;
|
|
+
|
|
+ while (nextItem) {
|
|
+ const char *uid = (const char *)e_contact_get_const(E_CONTACT(nextItem->data),
|
|
+ E_CONTACT_UID);
|
|
+ source->m_allItems.addItem(uid);
|
|
+ nextItem = nextItem->next;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ void EvolutionContactSource::addChanges(EBook *book,
|
|
+ EBookStatus status,
|
|
+ GList *nextItem,
|
|
+ gpointer custom)
|
|
+ {
|
|
+ EvolutionContactSource *source = (EvolutionContactSource *)custom;
|
|
+ source->m_status = status;
|
|
+
|
|
+ while (nextItem) {
|
|
+ EBookChange *ebc = (EBookChange *)nextItem->data;
|
|
+
|
|
+ if (ebc->contact) {
|
|
+ const char *uid = (const char *)e_contact_get_const( ebc->contact, E_CONTACT_UID );
|
|
+
|
|
+ if (uid) {
|
|
+ switch (ebc->change_type) {
|
|
+ case E_BOOK_CHANGE_CARD_ADDED:
|
|
+ source->m_newItems.addItem(uid);
|
|
+ break;
|
|
+ case E_BOOK_CHANGE_CARD_MODIFIED:
|
|
+ source->m_updatedItems.addItem(uid);
|
|
+ break;
|
|
+ case E_BOOK_CHANGE_CARD_DELETED:
|
|
+ source->m_deletedItems.addItem(uid);
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ nextItem = nextItem->next;
|
|
+ }
|
|
+
|
|
+ source->m_loop.quit();
|
|
+ }
|
|
+
|
|
+
|
|
void EvolutionContactSource::beginSyncThrow(bool needAll,
|
|
bool needPartial,
|
|
bool deleteLocal)
|
|
***************
|
|
*** 161,234 ****
|
|
GError *gerror = NULL;
|
|
|
|
if (deleteLocal) {
|
|
! eptr<EBookQuery> allItemsQuery( e_book_query_any_field_contains(""), "query" );
|
|
! GList *nextItem;
|
|
! if (!e_book_get_contacts( m_addressbook, allItemsQuery, &nextItem, &gerror )) {
|
|
! throwError( "reading all items", gerror );
|
|
! }
|
|
! while (nextItem) {
|
|
! const char *uid = (const char *)e_contact_get_const(E_CONTACT(nextItem->data),
|
|
! E_CONTACT_UID);
|
|
! if (!e_book_remove_contact( m_addressbook, uid, &gerror ) ) {
|
|
! throwError( string( "deleting contact " ) + uid,
|
|
gerror );
|
|
}
|
|
- nextItem = nextItem->next;
|
|
}
|
|
}
|
|
|
|
if (needAll) {
|
|
! eptr<EBookQuery> allItemsQuery( e_book_query_any_field_contains(""), "query" );
|
|
! GList *nextItem;
|
|
! if (!e_book_get_contacts( m_addressbook, allItemsQuery, &nextItem, &gerror )) {
|
|
! throwError( "reading all items", gerror );
|
|
! }
|
|
! while (nextItem) {
|
|
! const char *uid = (const char *)e_contact_get_const(E_CONTACT(nextItem->data),
|
|
! E_CONTACT_UID);
|
|
! m_allItems.addItem(uid);
|
|
! nextItem = nextItem->next;
|
|
! }
|
|
}
|
|
|
|
if (needPartial) {
|
|
GList *nextItem;
|
|
if (!e_book_get_changes( m_addressbook, (char *)m_changeId.c_str(), &nextItem, &gerror )) {
|
|
throwError( "reading changes", gerror );
|
|
}
|
|
! while (nextItem) {
|
|
! EBookChange *ebc = (EBookChange *)nextItem->data;
|
|
!
|
|
! if (ebc->contact) {
|
|
! const char *uid = (const char *)e_contact_get_const( ebc->contact, E_CONTACT_UID );
|
|
!
|
|
! if (uid) {
|
|
! switch (ebc->change_type) {
|
|
! case E_BOOK_CHANGE_CARD_ADDED:
|
|
! m_newItems.addItem(uid);
|
|
! break;
|
|
! case E_BOOK_CHANGE_CARD_MODIFIED:
|
|
! m_updatedItems.addItem(uid);
|
|
! break;
|
|
! case E_BOOK_CHANGE_CARD_DELETED:
|
|
! m_deletedItems.addItem(uid);
|
|
! break;
|
|
! }
|
|
! }
|
|
! }
|
|
! nextItem = nextItem->next;
|
|
}
|
|
}
|
|
}
|
|
|
|
void EvolutionContactSource::endSyncThrow()
|
|
{
|
|
if (m_isModified) {
|
|
- GError *gerror = NULL;
|
|
- GList *nextItem;
|
|
// move change_id forward so that our own changes are not listed the next time
|
|
! if (!e_book_get_changes( m_addressbook, (char *)m_changeId.c_str(), &nextItem, &gerror )) {
|
|
! throwError( "reading changes", gerror );
|
|
}
|
|
}
|
|
resetItems();
|
|
--- 209,264 ----
|
|
GError *gerror = NULL;
|
|
|
|
if (deleteLocal) {
|
|
! m_allItems.clear();
|
|
! listAllContacts(addContacts, this);
|
|
!
|
|
! EvolutionSyncSource::itemList::const_iterator it;
|
|
! for (it = m_allItems.begin();
|
|
! it != m_allItems.end();
|
|
! ++it) {
|
|
! if (!e_book_remove_contact( m_addressbook, it->c_str(), &gerror ) ) {
|
|
! throwError( string( "deleting contact " ) + *it,
|
|
gerror );
|
|
}
|
|
}
|
|
+ m_allItems.clear();
|
|
}
|
|
|
|
if (needAll) {
|
|
! listAllContacts(addContacts, this);
|
|
}
|
|
|
|
if (needPartial) {
|
|
+ #if 0
|
|
+ // times out on N770
|
|
+ GError *gerror = NULL;
|
|
GList *nextItem;
|
|
if (!e_book_get_changes( m_addressbook, (char *)m_changeId.c_str(), &nextItem, &gerror )) {
|
|
throwError( "reading changes", gerror );
|
|
}
|
|
! addChanges(m_addressbook, E_BOOK_ERROR_OK, nextItem, (gpointer)this);
|
|
! #else
|
|
! if (e_book_async_get_changes(m_addressbook, (char *)m_changeId.c_str(), addChanges, this)) {
|
|
! throwError( "reading changes", gerror );
|
|
}
|
|
+ m_loop.run();
|
|
+ if (m_status != E_BOOK_ERROR_OK) {
|
|
+ throw runtime_error("reading changes stopped with an error");
|
|
+ }
|
|
+ #endif
|
|
}
|
|
}
|
|
|
|
void EvolutionContactSource::endSyncThrow()
|
|
{
|
|
if (m_isModified) {
|
|
// move change_id forward so that our own changes are not listed the next time
|
|
! if (e_book_async_get_changes(m_addressbook, (char *)m_changeId.c_str(), addChanges, this)) {
|
|
! throw runtime_error("reading changes");
|
|
! }
|
|
! m_loop.run();
|
|
! if (m_status != E_BOOK_ERROR_OK) {
|
|
! throw runtime_error("reading changes stopped with an error");
|
|
}
|
|
}
|
|
resetItems();
|
|
***************
|
|
*** 241,263 ****
|
|
m_addressbook = NULL;
|
|
}
|
|
|
|
! void EvolutionContactSource::exportData(ostream &out)
|
|
{
|
|
! eptr<EBookQuery> allItemsQuery( e_book_query_any_field_contains(""), "query" );
|
|
! GList *nextItem;
|
|
! GError *gerror = NULL;
|
|
! if (!e_book_get_contacts( m_addressbook, allItemsQuery, &nextItem, &gerror )) {
|
|
! throwError( "reading all items", gerror );
|
|
! }
|
|
while (nextItem) {
|
|
eptr<char> vcardstr(e_vcard_to_string(&E_CONTACT(nextItem->data)->parent,
|
|
EVC_FORMAT_VCARD_30));
|
|
|
|
! out << (const char *)vcardstr << "\r\n\r\n";
|
|
nextItem = nextItem->next;
|
|
}
|
|
}
|
|
|
|
SyncItem *EvolutionContactSource::createItem( const string &uid, SyncState state )
|
|
{
|
|
logItem( uid, "extracting from EV" );
|
|
--- 271,296 ----
|
|
m_addressbook = NULL;
|
|
}
|
|
|
|
!
|
|
! static void dumpContacts(void *custom, GList *nextItem)
|
|
{
|
|
! ostream *out = (ostream *)custom;
|
|
!
|
|
while (nextItem) {
|
|
eptr<char> vcardstr(e_vcard_to_string(&E_CONTACT(nextItem->data)->parent,
|
|
EVC_FORMAT_VCARD_30));
|
|
|
|
! *out << (const char *)vcardstr << "\r\n\r\n";
|
|
!
|
|
nextItem = nextItem->next;
|
|
}
|
|
}
|
|
|
|
+ void EvolutionContactSource::exportData(ostream &out)
|
|
+ {
|
|
+ listAllContacts(dumpContacts, (void *)&out);
|
|
+ }
|
|
+
|
|
SyncItem *EvolutionContactSource::createItem( const string &uid, SyncState state )
|
|
{
|
|
logItem( uid, "extracting from EV" );
|
|
***************
|
|
*** 773,776 ****
|
|
--- 806,876 ----
|
|
}
|
|
}
|
|
|
|
+ class EvolutionContactListAll {
|
|
+ public:
|
|
+ EvolutionContactListAll(void (*processList)(void *custom, GList *list), void *custom, EvolutionContactSource &source):
|
|
+ m_processList(processList),
|
|
+ m_custom(custom),
|
|
+ m_source(source),
|
|
+ m_status(E_BOOK_VIEW_STATUS_OK)
|
|
+ {}
|
|
+
|
|
+ static void contactsAdded(EBookView *ebookview,
|
|
+ gpointer arg1,
|
|
+ gpointer user_data) {
|
|
+ EvolutionContactListAll *listAll = (EvolutionContactListAll *)user_data;
|
|
+ listAll->m_processList(listAll->m_custom, (GList *)arg1);
|
|
+ }
|
|
+
|
|
+ static void sequenceDone(EBookView *ebookview,
|
|
+ gint arg1,
|
|
+ gpointer user_data) {
|
|
+ EvolutionContactListAll *listAll = (EvolutionContactListAll *)user_data;
|
|
+ listAll->m_status = (EBookViewStatus)arg1;
|
|
+ listAll->m_source.m_loop.quit();
|
|
+ }
|
|
+
|
|
+ /** throw an error exception if an error occurred */
|
|
+ void checkStatus() {
|
|
+ if (m_status != E_BOOK_VIEW_STATUS_OK) {
|
|
+ throw runtime_error("iterating over all contacts failed");
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private:
|
|
+ void (*m_processList)(void *custom, GList *list);
|
|
+ void *m_custom;
|
|
+ EvolutionContactSource &m_source;
|
|
+ EBookViewStatus m_status;
|
|
+ };
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+ void EvolutionContactSource::listAllContacts(void (*processList)(void *custom, GList *list), void *custom)
|
|
+ {
|
|
+ eptr<EBookQuery> allItemsQuery( e_book_query_any_field_contains(""), "query" );
|
|
+ GError *gerror = NULL;
|
|
+ EBookView *viewptr;
|
|
+
|
|
+ if (e_book_get_book_view(m_addressbook, allItemsQuery, NULL, -1, &viewptr, &gerror)) {
|
|
+ eptr<EBookView, GObject> view(viewptr);
|
|
+ EvolutionContactListAll listAll(processList, custom, *this);
|
|
+
|
|
+ g_signal_connect(viewptr, "contacts-added", G_CALLBACK(listAll.contactsAdded), &listAll);
|
|
+ g_signal_connect(viewptr, "sequence-complete", G_CALLBACK(listAll.sequenceDone), &listAll);
|
|
+ e_book_view_start(view);
|
|
+ m_loop.run();
|
|
+ e_book_view_stop(view);
|
|
+ // workaround for http://bugzilla.gnome.org/show_bug.cgi?id=399011
|
|
+ // Without the sleep() EDS often (but not always) crashes in e_book_backend_get_book_views()
|
|
+ // during one of the following calls.
|
|
+ sleep(1);
|
|
+ listAll.checkStatus();
|
|
+ } else {
|
|
+ throwError( "getting view on addressbook", gerror );
|
|
+ }
|
|
+ }
|
|
+
|
|
#endif /* ENABLE_EBOOK */
|
|
Index: src/EvolutionContactSource.h
|
|
===================================================================
|
|
RCS file: /cvsroot/sync4jevolution/sync4jevolution/src/EvolutionContactSource.h,v
|
|
retrieving revision 1.22
|
|
diff -c -r1.22 EvolutionContactSource.h
|
|
*** src/EvolutionContactSource.h 10 Dec 2006 17:35:18 -0000 1.22
|
|
--- src/EvolutionContactSource.h 22 Feb 2007 19:27:50 -0000
|
|
***************
|
|
*** 32,37 ****
|
|
--- 32,49 ----
|
|
#include <set>
|
|
|
|
/**
|
|
+ * callback used by EvolutionContactSource::listAll() and
|
|
+ */
|
|
+ class EvolutionCallback
|
|
+ {
|
|
+ public:
|
|
+ /**
|
|
+ * Called to iterate over data. Content of list depends on context.
|
|
+ */
|
|
+ virtual void processList(GList *list) = 0;
|
|
+ };
|
|
+
|
|
+ /**
|
|
* Implements access to Evolution address books.
|
|
*/
|
|
class EvolutionContactSource : public EvolutionSyncSource
|
|
***************
|
|
*** 81,87 ****
|
|
// implementation of SyncSource
|
|
//
|
|
virtual ArrayElement *clone() { return new EvolutionContactSource(*this); }
|
|
!
|
|
protected:
|
|
//
|
|
// implementation of EvolutionSyncSource callbacks
|
|
--- 93,102 ----
|
|
// implementation of SyncSource
|
|
//
|
|
virtual ArrayElement *clone() { return new EvolutionContactSource(*this); }
|
|
!
|
|
! /** start and stop event processing on this source */
|
|
! EvolutionAsync m_loop;
|
|
!
|
|
protected:
|
|
//
|
|
// implementation of EvolutionSyncSource callbacks
|
|
***************
|
|
*** 142,149 ****
|
|
--- 157,191 ----
|
|
insert("CALURI");
|
|
}
|
|
} m_uniqueProperties;
|
|
+
|
|
+ /**
|
|
+ * extracts all contacts
|
|
+ *
|
|
+ * @param processList is fed the contacts, possibly in multiple chunks
|
|
+ * @param custom pointer passed through to processList
|
|
+ */
|
|
+ void listAllContacts(void (*processList)(void *custom, GList *list), void *custom);
|
|
+
|
|
+ /**
|
|
+ * callback for listAllContacts() which adds all contacts to m_allItems
|
|
+ */
|
|
+ static void addContacts(void *custom, GList *nextItem);
|
|
+
|
|
+ /**
|
|
+ * EBookListCallback for beginSyncThrow()'s e_book_async_get_changes ()
|
|
+ */
|
|
+ static void addChanges(EBook *book,
|
|
+ EBookStatus status,
|
|
+ GList *nextItem,
|
|
+ gpointer custom);
|
|
+ /**
|
|
+ * status passed to addChanges()
|
|
+ */
|
|
+ EBookStatus m_status;
|
|
};
|
|
|
|
+
|
|
+
|
|
#endif // ENABLE_EBOOK
|
|
|
|
#endif // INCL_EVOLUTIONCONTACTSOURCE
|
|
Index: src/EvolutionSmartPtr.h
|
|
===================================================================
|
|
RCS file: /cvsroot/sync4jevolution/sync4jevolution/src/EvolutionSmartPtr.h,v
|
|
retrieving revision 1.8
|
|
diff -c -r1.8 EvolutionSmartPtr.h
|
|
*** src/EvolutionSmartPtr.h 10 Dec 2006 17:35:19 -0000 1.8
|
|
--- src/EvolutionSmartPtr.h 22 Feb 2007 19:27:50 -0000
|
|
***************
|
|
*** 34,39 ****
|
|
--- 34,40 ----
|
|
|
|
void inline unref( char *pointer ) { free( pointer ); }
|
|
void inline unref( GObject *pointer ) { g_object_unref( pointer ); }
|
|
+ void inline unref( GMainLoop *pointer ) { g_main_loop_unref( pointer ); }
|
|
#ifdef ENABLE_EBOOK
|
|
void inline unref( EBookQuery *pointer ) { e_book_query_unref( pointer ); }
|
|
#endif
|
|
Index: src/EvolutionSyncClient.cpp
|
|
===================================================================
|
|
RCS file: /cvsroot/sync4jevolution/sync4jevolution/src/EvolutionSyncClient.cpp,v
|
|
retrieving revision 1.24
|
|
diff -c -r1.24 EvolutionSyncClient.cpp
|
|
*** src/EvolutionSyncClient.cpp 17 Dec 2006 16:33:45 -0000 1.24
|
|
--- src/EvolutionSyncClient.cpp 22 Feb 2007 19:27:50 -0000
|
|
***************
|
|
*** 432,438 ****
|
|
int res = DMTClientConfig::readDevInfoConfig(syncMLNode, syncMLNode);
|
|
|
|
// always read device ID from the traditional property "deviceId"
|
|
! eptr<char> tmp(syncMLNode.readPropertyValue("deviceId"));
|
|
deviceConfig.setDevID(tmp);
|
|
|
|
return res;
|
|
--- 432,438 ----
|
|
int res = DMTClientConfig::readDevInfoConfig(syncMLNode, syncMLNode);
|
|
|
|
// always read device ID from the traditional property "deviceId"
|
|
! arrayptr<char> tmp(syncMLNode.readPropertyValue("deviceId"));
|
|
deviceConfig.setDevID(tmp);
|
|
|
|
return res;
|
|
***************
|
|
*** 482,489 ****
|
|
// redirect logging as soon as possible
|
|
SourceList sourceList(m_server, m_doLogging);
|
|
|
|
! eptr<char> logdir(config.getSyncMLNode()->readPropertyValue("logdir"));
|
|
! eptr<char> maxlogdirs(config.getSyncMLNode()->readPropertyValue("maxlogdirs"));
|
|
sourceList.setLogdir(logdir, atoi(maxlogdirs));
|
|
|
|
SyncSourceConfig *sourceconfigs = config.getSyncSourceConfigs();
|
|
--- 482,489 ----
|
|
// redirect logging as soon as possible
|
|
SourceList sourceList(m_server, m_doLogging);
|
|
|
|
! arrayptr<char> logdir(config.getSyncMLNode()->readPropertyValue("logdir"));
|
|
! arrayptr<char> maxlogdirs(config.getSyncMLNode()->readPropertyValue("maxlogdirs"));
|
|
sourceList.setLogdir(logdir, atoi(maxlogdirs));
|
|
|
|
SyncSourceConfig *sourceconfigs = config.getSyncSourceConfigs();
|
|
Index: src/EvolutionSyncSource.h
|
|
===================================================================
|
|
RCS file: /cvsroot/sync4jevolution/sync4jevolution/src/EvolutionSyncSource.h,v
|
|
retrieving revision 1.24
|
|
diff -c -r1.24 EvolutionSyncSource.h
|
|
*** src/EvolutionSyncSource.h 10 Dec 2006 17:35:19 -0000 1.24
|
|
--- src/EvolutionSyncSource.h 22 Feb 2007 19:27:51 -0000
|
|
***************
|
|
*** 33,38 ****
|
|
--- 33,40 ----
|
|
#include <spdm/ManagementNode.h>
|
|
#include <base/Log.h>
|
|
|
|
+ #include <EvolutionSmartPtr.h>
|
|
+
|
|
/**
|
|
* This class implements the functionality shared by
|
|
* both EvolutionCalenderSource and EvolutionContactSource:
|
|
***************
|
|
*** 371,374 ****
|
|
--- 373,400 ----
|
|
string m_user, m_passwd;
|
|
};
|
|
|
|
+ /**
|
|
+ * Utility class which hides the mechanisms needed to handle events
|
|
+ * during asynchronous calls.
|
|
+ */
|
|
+ class EvolutionAsync {
|
|
+ public:
|
|
+ EvolutionAsync() :
|
|
+ m_loop(g_main_loop_new(NULL, FALSE), "main loop")
|
|
+ {}
|
|
+
|
|
+ /** start processing events */
|
|
+ void run() {
|
|
+ g_main_loop_run(m_loop);
|
|
+ }
|
|
+
|
|
+ /** stop processing events, to be called inside run() by callback */
|
|
+ void quit() {
|
|
+ g_main_loop_quit(m_loop);
|
|
+ }
|
|
+
|
|
+ private:
|
|
+ eptr<GMainLoop> m_loop;
|
|
+ };
|
|
+
|
|
#endif // INCL_EVOLUTIONSYNCSOURCE
|