[Evolution-hackers] New implementation of camel_imap_folder_fetch_data
- From: Philip Van Hoof <spam pvanhoof be>
- To: evolution-hackers gnome org
- Subject: [Evolution-hackers] New implementation of camel_imap_folder_fetch_data
- Date: Tue, 09 Jan 2007 02:18:25 +0100
Hi there,
I just finished this one, so there's probably a huge amount of bugs in
it. I know I should first debug them away before posting on mailing
lists ;). However, it would be nice if some (other) people would test
this reimplementation (it's a method in camel-imap-folder.c, by the
way).
Just take a look at it, compare it with the memory consumption of
copying everything into a GData after first copying everything into a
GPtrArray of a CamelImapResponse structure (which is what the original
does).
ps. the if (TRUE) {} thing is because in the version for tinymail,
there's support for partially retrieving messages. The else part
implements that support (feel free to take a look at tinymail's
camel-lite for the implementation, it's not a secret or something).
CamelStream *
camel_imap_folder_fetch_data (CamelImapFolder *imap_folder, const char *uid,
const char *section_text, gboolean cache_only,
CamelException *ex)
{
CamelFolder *folder = CAMEL_FOLDER (imap_folder);
CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store);
CamelStream *stream;
/* EXPUNGE responses have to modify the cache, which means
* they have to grab the cache_lock while holding the
* connect_lock.
* Because getting the service lock may cause MUCH unecessary
* delay when we already have the data locally, we do the
* locking separately. This could cause a race
* getting the same data from the cache, but that is only
* an inefficiency, and bad luck.
*/
CAMEL_IMAP_FOLDER_REC_LOCK (imap_folder, cache_lock);
stream = camel_imap_message_cache_get (imap_folder->cache, uid, section_text, ex);
/* TNY TODO: if (full) Detect retrieval status (if partial refetch) */
if (!stream && (!strcmp (section_text, "HEADER") || !strcmp (section_text, "0")))
{
camel_exception_clear (ex);
stream = camel_imap_message_cache_get (imap_folder->cache, uid, "", ex);
}
CAMEL_IMAP_FOLDER_REC_UNLOCK (imap_folder, cache_lock);
if (stream || cache_only)
return stream;
camel_exception_clear(ex);
CAMEL_SERVICE_REC_LOCK (store, connect_lock);
CAMEL_IMAP_FOLDER_REC_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_REC_UNLOCK (imap_folder, cache_lock);
CAMEL_SERVICE_REC_UNLOCK (store, connect_lock);
return NULL;
}
camel_exception_clear (ex);
stream = camel_imap_message_cache_insert (imap_folder->cache,
uid, full?section_text:"", "", 0, NULL);
if (stream == NULL)
stream = camel_stream_mem_new ();
if (!stream)
goto errorhander;
if (TRUE)
{
gboolean first = TRUE;
gchar line[512];
guint linenum = 0;
ssize_t nread;
CamelStreamBuffer *server_stream = CAMEL_STREAM_BUFFER (store->istream);
gchar *tag;
guint taglen;
gboolean isnextdone = FALSE;
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')))
{
isnextdone = TRUE;
continue;
}
/* It's the first line */
if (linenum == 0 && (line [0] != '*' || line[1] != ' '))
{
g_free (tag);
goto errorhander;
} else if (linenum == 0) { linenum++; continue; }
/* It's the last line */
if (!strncmp (line, tag, taglen))
break;
camel_seekable_stream_seek (CAMEL_SEEKABLE_STREAM (stream), 0, CAMEL_STREAM_END);
if (isnextdone)
{
camel_stream_write (stream, ")\n", 2);
isnextdone = FALSE;
}
camel_stream_write (stream, line, strlen (line));
linenum++;
}
g_free (tag);
camel_stream_reset (stream);
}
CAMEL_SERVICE_REC_UNLOCK (store, connect_lock);
CAMEL_IMAP_FOLDER_REC_UNLOCK (imap_folder, cache_lock);
return stream;
errorhander:
CAMEL_SERVICE_REC_UNLOCK (store, connect_lock);
CAMEL_IMAP_FOLDER_REC_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;
}
--
Philip Van Hoof, software developer
home: me at pvanhoof dot be
gnome: pvanhoof at gnome dot org
http://www.pvanhoof.be/blog
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]