[evolution-data-server/meego-eds: 42/47] Add support to mobile extension of POP/IMAP and implement the new APIs.



commit 887b5d59d91b4d7f65836aa2849b5e718f3fe286
Author: Srinivasa Ragavan <sragavan gnome org>
Date:   Tue Jun 7 23:19:27 2011 +0530

    Add support to mobile extension of POP/IMAP and implement the new APIs.

 mail/daemon/e-mail-data-folder.c    |   59 +++++++++++++++++++++++++++
 mail/daemon/e-mail-data-folder.xml  |    4 ++
 mail/daemon/e-mail-data-session.c   |   49 +++++++++++++++++++++++
 mail/daemon/e-mail-data-session.xml |    6 +++
 mail/daemon/mail-ops.c              |   75 +++++++++++++++++++++++++++++++++-
 mail/daemon/mail-ops.h              |    2 +-
 mail/daemon/mail-send-recv.c        |    4 +-
 7 files changed, 193 insertions(+), 6 deletions(-)
---
diff --git a/mail/daemon/e-mail-data-folder.c b/mail/daemon/e-mail-data-folder.c
index 4636381..fd092de 100644
--- a/mail/daemon/e-mail-data-folder.c
+++ b/mail/daemon/e-mail-data-folder.c
@@ -1617,6 +1617,64 @@ ps_done (gboolean success, gpointer sdata, GError *error)
 	g_free (data);
 }
 
+/* Fetch Old messages */
+typedef struct _email_folder_fetch_data {
+	EMailDataFolder *mfolder;
+	EGdbusFolderCF *object;
+	GDBusMethodInvocation *invocation;
+	gint count;
+}EMailFolderFetchData;
+
+
+static gboolean
+fetch_old_operate (CamelFolder *folder, gpointer sdata, GError **error)
+{
+	EMailFolderFetchData *data = (EMailFolderFetchData *)sdata;
+
+	return camel_folder_fetch_old_messages (folder, data->count, error);
+}
+
+static void
+fetch_old_done (gboolean success, gpointer sdata, GError *error)
+{
+	EMailFolderFetchData *data = (EMailFolderFetchData *)sdata;
+	EMailDataFolderPrivate *priv = DATA_FOLDER_PRIVATE(data->mfolder);	
+	
+	if (error && error->message) {
+		g_warning ("Fetch old messages failed: %s: %s\n", priv->path, error->message);
+		g_dbus_method_invocation_return_gerror (data->invocation, error);		
+		ipc(printf("Fetch old messages: %s failed: %s\n", priv->path, error->message));
+		return;
+	}
+
+
+	egdbus_folder_cf_complete_fetch_old_messages (data->object, data->invocation, success);
+
+	ipc(printf("Fetch old messages: %s success: %d\n", priv->path, success));
+
+	g_free (data);
+}
+
+
+
+static 
+gboolean
+impl_Mail_fetchOldMessages (EGdbusFolderCF *object, GDBusMethodInvocation *invocation, int count, EMailDataFolder *mfolder)
+{
+	EMailFolderFetchData *data;
+	EMailDataFolderPrivate *priv = DATA_FOLDER_PRIVATE(mfolder);	
+
+	data = g_new0 (EMailFolderFetchData, 1);
+	data->mfolder = mfolder;
+	data->invocation = invocation;
+	data->object = object;
+	data->count = count;
+
+	mail_operate_on_folder (priv->folder, fetch_old_operate, fetch_old_done, data);
+
+	return TRUE;
+}
+
 static gboolean
 impl_Mail_prepareSummary (EGdbusFolderCF *object, GDBusMethodInvocation *invocation, EMailDataFolder *mfolder)
 {
@@ -1674,6 +1732,7 @@ e_mail_data_folder_init (EMailDataFolder *self)
 	g_signal_connect (priv->gdbus_object, "handle-get-message-info", G_CALLBACK (impl_Mail_getMessageInfo), self);
 	g_signal_connect (priv->gdbus_object, "handle-transfer-messages-to", G_CALLBACK (impl_Mail_transferMessagesTo), self);
 	g_signal_connect (priv->gdbus_object, "handle-prepare-summary", G_CALLBACK (impl_Mail_prepareSummary), self);
+	g_signal_connect (priv->gdbus_object, "handle-fetch-old-messages", G_CALLBACK (impl_Mail_fetchOldMessages), self);
 	
 	
 }
diff --git a/mail/daemon/e-mail-data-folder.xml b/mail/daemon/e-mail-data-folder.xml
index 1161eaf..ff9bcac 100644
--- a/mail/daemon/e-mail-data-folder.xml
+++ b/mail/daemon/e-mail-data-folder.xml
@@ -130,6 +130,10 @@
       <arg name="uid" type="s" direction="in"/>	    	    	    	    	    
       <arg name="message" type="s" direction="out"/>	    	    	    	    
     </method>        
+    <method name="fetchOldMessages">
+      <arg name="count" type="i" direction="in"/>	    	    
+      <arg name="success" type="b" direction="out"/>	    	                
+    </method>
     <method name="searchByExpression">
       <arg name="expression" type="s" direction="in"/>	    	    	    	    	    
       <arg name="uids" type="as" direction="out"/>	    	    	    	    
diff --git a/mail/daemon/e-mail-data-session.c b/mail/daemon/e-mail-data-session.c
index 8be36b6..00913d8 100644
--- a/mail/daemon/e-mail-data-session.c
+++ b/mail/daemon/e-mail-data-session.c
@@ -7,6 +7,8 @@
 #include <camel/camel.h>
 #include <gio/gio.h>
 #include "mail-ops.h"
+#include "mail-tools.h"
+#include "mail-send-recv.h"
 #include "utils.h"
 #include <libedataserver/e-account-list.h>
 #include <libedataserverui/e-passwords.h>
@@ -381,6 +383,52 @@ impl_Mail_fetchAccount (EGdbusSessionCS *object, GDBusMethodInvocation *invocati
 	return TRUE;
 }
 
+static void
+fetch_old_messages_done (gboolean still_more, EMailGetStoreData *data)
+{
+	ipc(printf("Done: Fetch old messages in POP: %d\n", still_more));
+	egdbus_session_cs_complete_fetch_old_messages (data->object, data->invocation, still_more);
+
+	g_free (data);
+}
+
+static gboolean
+impl_Mail_fetchOldMessages (EGdbusSessionCS *object, GDBusMethodInvocation *invocation, char *uid, int count, EMailDataSession *msession)
+{
+	EIterator *iter;
+	EAccountList *accounts;
+	EAccount *account;
+	EMailGetStoreData *data = g_new0(EMailGetStoreData, 1);
+
+	data->invocation = invocation;
+	data->msession = msession;
+	data->object = object;
+	
+	accounts = e_get_account_list ();
+	for (iter = e_list_get_iterator ((EList *)accounts);
+	     e_iterator_is_valid (iter);
+	     e_iterator_next (iter)) {
+		account = (EAccount *) e_iterator_get (iter);
+		if (account->uid && strcmp (account->uid, uid) == 0) {
+			const gchar *uri;
+			gboolean keep_on_server;
+
+			uri = e_account_get_string (
+				account, E_ACCOUNT_SOURCE_URL);
+			keep_on_server = e_account_get_bool (
+				account, E_ACCOUNT_SOURCE_KEEP_ON_SERVER);
+			mail_fetch_mail (uri, keep_on_server,
+				 E_FILTER_SOURCE_INCOMING,
+				 NULL, count,
+				 NULL, NULL,
+				 NULL, NULL,
+				 (void (*)(const gchar *, void *)) fetch_old_messages_done, data);
+		}
+	}
+
+	return TRUE;
+}
+
 static gboolean
 impl_Mail_cancelOperations (EGdbusSessionCS *object, GDBusMethodInvocation *invocation, EMailDataSession *msession)
 {
@@ -453,6 +501,7 @@ e_mail_data_session_init (EMailDataSession *self)
 	g_signal_connect (priv->gdbus_object, "handle-add-password", G_CALLBACK (impl_Mail_addPassword), self);
 	g_signal_connect (priv->gdbus_object, "handle-send-receive", G_CALLBACK (impl_Mail_sendReceive), self);
 	g_signal_connect (priv->gdbus_object, "handle-fetch-account", G_CALLBACK (impl_Mail_fetchAccount), self);
+	g_signal_connect (priv->gdbus_object, "handle-fetch-old-messages", G_CALLBACK (impl_Mail_fetchOldMessages), self);
 	g_signal_connect (priv->gdbus_object, "handle-cancel-operations", G_CALLBACK (impl_Mail_cancelOperations), self);
 
 	priv->stores_lock = g_mutex_new ();
diff --git a/mail/daemon/e-mail-data-session.xml b/mail/daemon/e-mail-data-session.xml
index 793a7f6..731fe7e 100644
--- a/mail/daemon/e-mail-data-session.xml
+++ b/mail/daemon/e-mail-data-session.xml
@@ -45,6 +45,12 @@
     <method name="fetchAccount">
       <arg name="uid" type="s" direction="in"/>	    
     </method>
+    
+    <method name="fetchOldMessages">
+      <arg name="uid" type="s" direction="in"/>	 
+      <arg name="count" type="i" direction="in"/>	    	             
+      <arg name="success" type="b" direction="out"/>            
+    </method>
 
     <method name="cancelOperations">
     </method>    
diff --git a/mail/daemon/mail-ops.c b/mail/daemon/mail-ops.c
index 70b06ba..fbc53a5 100644
--- a/mail/daemon/mail-ops.c
+++ b/mail/daemon/mail-ops.c
@@ -49,6 +49,10 @@
 /* XXX Make this a preprocessor definition. */
 const gchar *x_mailer = "Evolution Mail Data Server 0.1 ";
 
+/* POP is a non storage store, and has to be sequential between same accounts. We'll use this to lock it*/
+static GStaticMutex pop3_hash_lock = G_STATIC_MUTEX_INIT;
+static GHashTable *pop3_hash = NULL;
+
 /* used for both just filtering a folder + uid's, and for filtering a whole folder */
 /* used both for fetching mail, and for filtering mail */
 struct _filter_mail_msg {
@@ -69,6 +73,8 @@ struct _fetch_mail_msg {
 
 	CamelOperation *cancel;	/* we have our own cancellation struct, the other should be empty */
 	gint keep;		/* keep on server? */
+	gint more;
+	gboolean still_more;
 
 	gchar *source_uri;
 
@@ -217,6 +223,54 @@ mail_filter_junk (CamelFolder *folder, GPtrArray *uids)
 #endif
 
 /* ********************************************************************** */
+static void
+my_mutex_free (GMutex *lock)
+{
+	g_mutex_free (lock);
+}
+
+static GHashTable *
+get_pop3_hash ()
+{
+	g_static_mutex_lock (&pop3_hash_lock);
+	if (!pop3_hash)
+		pop3_hash = g_hash_table_new_full ( g_str_hash, g_str_equal, (GDestroyNotify)g_free, (GDestroyNotify)my_mutex_free);
+
+	g_static_mutex_unlock (&pop3_hash_lock);	
+
+	return pop3_hash;
+}
+
+static void
+pop3_fetch_lock (const char *source)
+{
+	GMutex *lock;
+	GHashTable *hash = get_pop3_hash();
+
+	g_static_mutex_lock (&pop3_hash_lock);
+	lock = g_hash_table_lookup (hash, source);
+	if (!lock) {
+		lock = g_mutex_new();
+		g_hash_table_insert (hash, g_strdup(source), lock);
+	}
+	g_static_mutex_unlock (&pop3_hash_lock);
+
+	g_mutex_lock (lock);
+}
+
+static void
+pop3_fetch_unlock (const char *source)
+{
+	GMutex *lock;
+	GHashTable *hash = get_pop3_hash();
+
+	g_static_mutex_lock (&pop3_hash_lock);
+	/* lock can't disappear from hash */
+	lock = g_hash_table_lookup (hash, source);
+	g_static_mutex_unlock (&pop3_hash_lock);
+
+	g_mutex_unlock (lock);
+}
 
 /* Temporary workaround for various issues. Gone before 0.11 */
 static gchar *
@@ -332,6 +386,8 @@ fetch_mail_exec (struct _fetch_mail_msg *m)
 	} else {
 		CamelFolder *folder;
 
+		/* This is a account level lock to ensure that no two same accounts get fetched at the same time */
+		pop3_fetch_lock (m->source_uri);
 		folder = fm->source_folder =
 			mail_tool_get_inbox (m->source_uri, &fm->base.error);
 
@@ -341,6 +397,11 @@ fetch_mail_exec (struct _fetch_mail_msg *m)
 			CamelUIDCache *cache = NULL;
 			CamelStore *parent_store;
 			gchar *cachename;
+			
+			if (m->more) {
+				printf("Fetching %d old messages\n", m->more);
+				m->still_more = camel_folder_fetch_old_messages(folder, m->more, &fm->base.error);
+			}
 
 			parent_store = camel_folder_get_parent_store (folder);
 			cachename = uid_cachename_hack (parent_store);
@@ -356,6 +417,7 @@ fetch_mail_exec (struct _fetch_mail_msg *m)
 
 				folder_uids = camel_folder_get_uids (folder);
 				cache_uids = camel_uid_cache_get_new_uids (cache, folder_uids);
+				printf("Gonna cache uids: %d\n", cache_uids->len);
 				if (cache_uids) {
 					/* need to copy this, sigh */
 					fm->source_uids = uids = g_ptr_array_new ();
@@ -402,6 +464,8 @@ fetch_mail_exec (struct _fetch_mail_msg *m)
 			g_object_unref (fm->source_folder);
 			fm->source_folder = NULL;
 		}
+
+		pop3_fetch_unlock(m->source_uri);
 	}
 fail:
 	if (m->cancel)
@@ -419,8 +483,12 @@ fail:
 static void
 fetch_mail_done (struct _fetch_mail_msg *m)
 {
-	if (m->done)
-		m->done (m->source_uri, m->data);
+	if (m->done) {
+		if (m->more)
+			m->done (m->still_more, m->data);	
+		else
+			m->done (m->source_uri, m->data);
+	}
 }
 
 static void
@@ -443,7 +511,7 @@ static MailMsgInfo fetch_mail_info = {
 
 /* ouch, a 'do everything' interface ... */
 void
-mail_fetch_mail (const gchar *source, gint keep, const gchar *type, CamelOperation *cancel,
+mail_fetch_mail (const gchar *source, gint keep, const gchar *type, CamelOperation *cancel, gint more,
 		 CamelFilterGetFolderFunc get_folder, gpointer get_data,
 		 CamelFilterStatusFunc *status, gpointer status_data,
 		 void (*done)(const gchar *source, gpointer data), gpointer data)
@@ -452,6 +520,7 @@ mail_fetch_mail (const gchar *source, gint keep, const gchar *type, CamelOperati
 	struct _filter_mail_msg *fm;
 
 	m = mail_msg_new (&fetch_mail_info);
+	m->more  = more;
 	fm = (struct _filter_mail_msg *)m;
 	m->source_uri = g_strdup (source);
 	fm->delete = !keep;
diff --git a/mail/daemon/mail-ops.h b/mail/daemon/mail-ops.h
index 99a371c..2e82f7a 100644
--- a/mail/daemon/mail-ops.h
+++ b/mail/daemon/mail-ops.h
@@ -139,7 +139,7 @@ void mail_send_queue (CamelFolder *queue, const gchar *destination,
 		      gpointer data);
 
 void mail_fetch_mail (const gchar *source, gint keep,
-		      const gchar *type, CamelOperation *cancel,
+		      const gchar *type, CamelOperation *cancel, gint more,
 		      CamelFilterGetFolderFunc get_folder, gpointer get_data,
 		      CamelFilterStatusFunc *status, gpointer status_data,
 		      void (*done)(const gchar *source, gpointer data),
diff --git a/mail/daemon/mail-send-recv.c b/mail/daemon/mail-send-recv.c
index 6b218f3..e623548 100644
--- a/mail/daemon/mail-send-recv.c
+++ b/mail/daemon/mail-send-recv.c
@@ -1018,7 +1018,7 @@ mail_send_receive (GtkWindow *parent)
 		case SEND_RECEIVE:
 			mail_fetch_mail(info->uri, info->keep_on_server,
 					E_FILTER_SOURCE_INCOMING,
-					info->cancel,
+					info->cancel, 0,
 					receive_get_folder, info,
 					receive_status, info,
 					receive_done, info);
@@ -1252,7 +1252,7 @@ mail_receive_uri (const gchar *uri, gboolean keep_on_server)
 	case SEND_RECEIVE:
 		mail_fetch_mail (info->uri, info->keep_on_server,
 				 E_FILTER_SOURCE_INCOMING,
-				 info->cancel,
+				 info->cancel, 0,
 				 receive_get_folder, info,
 				 receive_status, info,
 				 receive_done, info);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]