[evolution-patches] [Fwd: CamelImapFolder improvement that will make get_message stream immediately to the CamelImapMessageCache]
- From: Philip Van Hoof <me pvanhoof be>
- To: evolution-patches <evolution-patches gnome org>
- Subject: [evolution-patches] [Fwd: CamelImapFolder improvement that will make get_message stream immediately to the CamelImapMessageCache]
- Date: Tue, 16 Jan 2007 06:04:17 +0100
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 ---
- From: Philip Van Hoof <spam pvanhoof be>
- To: evolution-hackers gnome org
- Cc: Matthew Barnes <mbarnes redhat com>, Veerapuram Varadhan <vvaradhan novell com>
- Subject: CamelImapFolder improvement that will make get_message stream immediately to the CamelImapMessageCache
- Date: Tue, 16 Jan 2007 06:02:55 +0100
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]