[evolution-patches] [Fwd: CamelImapFolder improvement that will make get_message stream immediately to the CamelImapMessageCache]



Attaching/sending the patch here (patches ml) so that copyright
reassignment can be done.


-- 
Philip Van Hoof, software developer
home: me at pvanhoof dot be 
gnome: pvanhoof at gnome dot org 
http://www.pvanhoof.be/blog



--- Begin Message ---
http://bugzilla.gnome.org/show_bug.cgi?id=397130

Please review.

Thanks

-- 
Philip Van Hoof, software developer
home: me at pvanhoof dot be 
gnome: pvanhoof at gnome dot org 
http://www.pvanhoof.be/blog




--- End Message ---
Index: camel/providers/imap/camel-imap-folder.c
===================================================================
--- camel/providers/imap/camel-imap-folder.c	(revision 7583)
+++ camel/providers/imap/camel-imap-folder.c	(working copy)
@@ -2680,6 +2680,21 @@
 }
 
 
+static void 
+handle_freeup (CamelImapStore *store, gint nread, CamelException *ex)
+{
+	if (nread <= 0) {
+		if (errno == EINTR)
+			camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, _("Operation cancelled"));
+		else
+			camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
+					      _("Server unexpectedly disconnected: %s"),
+					      g_strerror (errno));
+		
+		camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL);
+	}
+}
+
 CamelStream *
 camel_imap_folder_fetch_data (CamelImapFolder *imap_folder, const char *uid,
 			      const char *section_text, gboolean cache_only,
@@ -2687,12 +2702,13 @@
 {
 	CamelFolder *folder = CAMEL_FOLDER (imap_folder);
 	CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store);
-	CamelImapResponse *response;
-	CamelStream *stream;
-	GData *fetch_data;
-	char *found_uid;
-	int i;
-	
+	CamelStreamBuffer *server_stream = CAMEL_STREAM_BUFFER (store->istream);
+	gboolean err=FALSE, isnextdone = FALSE, hadr = FALSE;
+	CamelStream *stream = NULL;
+	gchar line[512], *tag = NULL;
+	guint linenum = 0, taglen = 0;
+	ssize_t nread; 
+
 	/* EXPUNGE responses have to modify the cache, which means
 	 * they have to grab the cache_lock while holding the
 	 * connect_lock.
@@ -2703,6 +2719,7 @@
 	 * getting the same data from the cache, but that is only
 	 * an inefficiency, and bad luck.
 	 */
+
 	CAMEL_IMAP_FOLDER_LOCK (imap_folder, cache_lock);
 	stream = camel_imap_message_cache_get (imap_folder->cache, uid, section_text, ex);
 	if (!stream && (!strcmp (section_text, "HEADER") || !strcmp (section_text, "0"))) {
@@ -2716,56 +2733,106 @@
 
 	camel_exception_clear(ex);
 
-	CAMEL_SERVICE_LOCK (store, connect_lock);
 	CAMEL_IMAP_FOLDER_LOCK (imap_folder, cache_lock);
 
 	if (!camel_imap_store_connected(store, ex)) {
 		camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
 				     _("This message is not currently available"));
 		CAMEL_IMAP_FOLDER_UNLOCK (imap_folder, cache_lock);
-		CAMEL_SERVICE_UNLOCK (store, connect_lock);
 		return NULL;
 	}
 	
 	camel_exception_clear (ex);
-	if (store->server_level < IMAP_LEVEL_IMAP4REV1 && !*section_text) {
-		response = camel_imap_command (store, folder, ex,
-					       "UID FETCH %s RFC822.PEEK",
-					       uid);
-	} else {
-		response = camel_imap_command (store, folder, ex,
-					       "UID FETCH %s BODY.PEEK[%s]",
-					       uid, section_text);
+
+	stream = camel_imap_message_cache_insert (imap_folder->cache, 
+			uid, section_text, "", 0, NULL);
+
+	if (stream == NULL)
+		stream = camel_stream_mem_new ();
+
+	if (!stream)
+		goto errorhander;
+
+	/* camel_imap_command_start is a CAMEL_SERVICE_LOCK (store, connect_lock); */
+
+	if (store->server_level < IMAP_LEVEL_IMAP4REV1 && !*section_text)
+	   camel_imap_command_start (store, folder, ex,
+		"UID FETCH %s RFC822.PEEK",uid);
+	else
+	   camel_imap_command_start (store, folder, ex,
+		"UID FETCH %s BODY.PEEK[%s]",uid, section_text);
+
+	tag = g_strdup_printf ("%c%.5u", store->tag_prefix, store->command-1);
+	taglen = strlen (tag);
+	store->command++;
+
+	while (nread = camel_stream_buffer_gets (server_stream, line, 512) > 0) {
+
+		    /* It might be the line before the last line */
+		    if (line[0] == ')' && (line[1] == '\n' || (line[1] == '\r' && line[2] == '\n'))) {
+			    if (line[1] == '\r')
+				hadr = TRUE;
+			    isnextdone = TRUE;
+			    continue;
+		    }
+
+		    /* It's the first line */
+		    if (linenum == 0 && (line [0] != '*' || line[1] != ' ')) {
+			    err=TRUE;
+			    break;
+		    } else if (linenum == 0) { 
+			linenum++; continue; 
+		    }
+
+		    /* It's the last line (isnextdone will be ignored if that is the case) */
+		    if (!strncmp (line, tag, taglen))
+			    break;
+
+		    camel_seekable_stream_seek (CAMEL_SEEKABLE_STREAM (stream), 0, CAMEL_STREAM_END);
+
+		    if (isnextdone) {
+			    if (hadr)
+				    camel_stream_write (stream, ")\n", 2);
+			    else
+				    camel_stream_write (stream, ")\r\n", 3);
+
+			    hadr = FALSE;
+			    isnextdone = FALSE;
+		    }
+
+		    camel_stream_write (stream, line, strlen (line));
+
+		    linenum++;
 	}
-	/* We won't need the connect_lock again after this. */
+
 	CAMEL_SERVICE_UNLOCK (store, connect_lock);
-	
-	if (!response) {
-		CAMEL_IMAP_FOLDER_UNLOCK (imap_folder, cache_lock);
-		return NULL;
-	}
-	
-	for (i = 0; i < response->untagged->len; i++) {
-		fetch_data = parse_fetch_response (imap_folder, response->untagged->pdata[i]);
-		found_uid = g_datalist_get_data (&fetch_data, "UID");
-		stream = g_datalist_get_data (&fetch_data, "BODY_PART_STREAM");
-		if (found_uid && stream && !strcmp (uid, found_uid))
-			break;
+
+	if (nread <= 0) 
+		handle_freeup (store, nread, ex);
 		
-		g_datalist_clear (&fetch_data);
-		stream = NULL;
-	}
-	camel_imap_response_free (store, response);
+	g_free (tag);
+
+	if (err)
+		goto errorhander;
+
+	camel_stream_reset (stream);
+		
+
 	CAMEL_IMAP_FOLDER_UNLOCK (imap_folder, cache_lock);
-	if (!stream) {
-		camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
-				      _("Could not find message body in FETCH response."));
-	} else {
-		camel_object_ref (CAMEL_OBJECT (stream));
-		g_datalist_clear (&fetch_data);
-	}
-	
+
 	return stream;
+
+errorhander:
+
+	CAMEL_IMAP_FOLDER_UNLOCK (imap_folder, cache_lock);
+
+	camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
+		    _("Could not find message body in FETCH response."));
+
+	if (stream)
+		camel_object_unref (CAMEL_OBJECT (stream));
+
+	return NULL;
 }
 
 static GData *
Index: camel/ChangeLog
===================================================================
--- camel/ChangeLog	(revision 7583)
+++ camel/ChangeLog	(working copy)
@@ -1,3 +1,8 @@
+2007-01-16  Philip Van Hoof  <pvanhoof gnome org>
+
+	* providers/imap/camel-imap-folder.c: Improvements when getting new
+	messages (no more memory copy, streams immediately to the cache)
+
 2006-01-08  Veerapuram Varadhan  <vvaradhan novell com>
 
 	** Fixes eds part of bgo #362638 - Patch submitted by Matthew


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