From: Art Cancro Date: Sat, 22 Jan 2005 03:14:21 +0000 (+0000) Subject: * Each message's metadata now has the ability to cache the length of X-Git-Tag: v7.86~5123 X-Git-Url: https://code.citadel.org/?a=commitdiff_plain;h=0fe465c3657c3b2440c1dfcbd86ae8acd5bf2964;p=citadel.git * Each message's metadata now has the ability to cache the length of the message when output in RFC822 format. The POP3 service populates this field the first time it sees each message, and fetches the length from cache on subsequent visits. * Because of this optimization, we no longer need to keep the entire POP3 mailbox stored in open temp files during a session. Each message is opened again when it is fetched. --- diff --git a/citadel/ChangeLog b/citadel/ChangeLog index 75659d32a..4c365b5c1 100644 --- a/citadel/ChangeLog +++ b/citadel/ChangeLog @@ -1,4 +1,13 @@ $Log$ + Revision 630.1 2005/01/22 03:14:20 ajc + * Each message's metadata now has the ability to cache the length of + the message when output in RFC822 format. The POP3 service populates + this field the first time it sees each message, and fetches the length + from cache on subsequent visits. + * Because of this optimization, we no longer need to keep the entire POP3 + mailbox stored in open temp files during a session. Each message is + opened again when it is fetched. + Revision 630.0 2005/01/21 20:25:08 ajc * THIS IS 6.30 @@ -6293,4 +6302,3 @@ Sat Jul 11 00:20:48 EDT 1998 Nathan Bryant Fri Jul 10 1998 Art Cancro * Initial CVS import - diff --git a/citadel/msgbase.c b/citadel/msgbase.c index 697a67fbb..2c34eaa76 100644 --- a/citadel/msgbase.c +++ b/citadel/msgbase.c @@ -2069,7 +2069,7 @@ long CtdlSubmitMsg(struct CtdlMessage *msg, /* message to save */ memset(&smi, 0, sizeof(struct MetaData)); smi.meta_msgnum = newmsgid; smi.meta_refcount = 0; - safestrncpy(smi.meta_content_type, content_type, 64); + safestrncpy(smi.meta_content_type, content_type, sizeof smi.meta_content_type); PutMetaData(&smi); /* Now figure out where to store the pointers */ diff --git a/citadel/serv_pop3.c b/citadel/serv_pop3.c index 8401acc48..cc01a6b1a 100644 --- a/citadel/serv_pop3.c +++ b/citadel/serv_pop3.c @@ -70,22 +70,12 @@ * the POP3 server. */ void pop3_cleanup_function(void) { - int i; /* Don't do this stuff if this is not a POP3 session! */ if (CC->h_command_function != pop3_command_loop) return; lprintf(CTDL_DEBUG, "Performing POP3 cleanup hook\n"); - - if (POP3->num_msgs > 0) for (i=0; inum_msgs; ++i) { - if (POP3->msgs[i].temp != NULL) { - fclose(POP3->msgs[i].temp); - POP3->msgs[i].temp = NULL; - } - } if (POP3->msgs != NULL) free(POP3->msgs); - - lprintf(CTDL_DEBUG, "Finished POP3 cleanup hook\n"); } @@ -136,6 +126,7 @@ void pop3_user(char *argbuf) { void pop3_add_message(long msgnum, void *userdata) { FILE *fp; lprintf(CTDL_DEBUG, "in pop3_add_message()\n"); + struct MetaData smi; ++POP3->num_msgs; if (POP3->num_msgs < 2) POP3->msgs = malloc(sizeof(struct pop3msg)); @@ -143,14 +134,23 @@ void pop3_add_message(long msgnum, void *userdata) { (POP3->num_msgs * sizeof(struct pop3msg)) ) ; POP3->msgs[POP3->num_msgs-1].msgnum = msgnum; POP3->msgs[POP3->num_msgs-1].deleted = 0; - fp = tmpfile(); - POP3->msgs[POP3->num_msgs-1].temp = fp; - - CtdlRedirectOutput(fp, -1); - CtdlOutputMsg(msgnum, MT_RFC822, HEADERS_ALL, 0, 1); - CtdlRedirectOutput(NULL, -1); - POP3->msgs[POP3->num_msgs-1].rfc822_length = ftell(fp); + /* We need to know the length of this message when it is printed in + * RFC822 format. Perhaps we have cached this length in the message's + * metadata record. If so, great; if not, measure it and then cache + * it for next time. + */ + GetMetaData(&smi, POP3->num_msgs-1); + if (smi.meta_rfc822_length <= 0L) { + fp = tmpfile(); + CtdlRedirectOutput(fp, -1); + CtdlOutputMsg(msgnum, MT_RFC822, HEADERS_ALL, 0, 1); + CtdlRedirectOutput(NULL, -1); + smi.meta_rfc822_length = ftell(fp); + fclose(fp); + PutMetaData(&smi); + } + POP3->msgs[POP3->num_msgs-1].rfc822_length = smi.meta_rfc822_length; } @@ -343,8 +343,6 @@ void pop3_stat(char *argbuf) { */ void pop3_retr(char *argbuf) { int which_one; - int ch = 0; - size_t bytes_remaining; which_one = atoi(argbuf); if ( (which_one < 1) || (which_one > POP3->num_msgs) ) { @@ -358,15 +356,7 @@ void pop3_retr(char *argbuf) { } cprintf("+OK Message %d:\r\n", which_one); - bytes_remaining = POP3->msgs[which_one -1].rfc822_length; - rewind(POP3->msgs[which_one - 1].temp); - while (bytes_remaining-- > 0) { - ch = getc(POP3->msgs[which_one - 1].temp); - cprintf("%c", ch); - } - if (ch != 10) { - lprintf(CTDL_WARNING, "Problem: message ends with 0x%2x, not 0x0a\n", ch); - } + CtdlOutputMsg(POP3->msgs[which_one - 1].msgnum, MT_RFC822, HEADERS_ALL, 0, 1); cprintf(".\r\n"); } @@ -382,6 +372,7 @@ void pop3_top(char *argbuf) { char *ptr; int in_body = 0; int done = 0; + FILE *fp; sscanf(argbuf, "%d %d", &which_one, &lines_requested); if ( (which_one < 1) || (which_one > POP3->num_msgs) ) { @@ -394,9 +385,18 @@ void pop3_top(char *argbuf) { return; } + fp = tmpfile(); + if (fp == NULL) { + cprintf("-ERR Internal error: could not create temp file\r\n"); + return; + } + CtdlRedirectOutput(fp, -1); + CtdlOutputMsg(POP3->msgs[which_one - 1].msgnum, MT_RFC822, HEADERS_ALL, 0, 1); + CtdlRedirectOutput(NULL, -1); + cprintf("+OK Message %d:\r\n", which_one); - rewind(POP3->msgs[which_one - 1].temp); - while (ptr = fgets(buf, sizeof buf, POP3->msgs[which_one - 1].temp), + rewind(fp); + while (ptr = fgets(buf, sizeof buf, fp), ( (ptr!=NULL) && (done == 0))) { if (in_body == 1) if (lines_dumped >= lines_requested) done = 1; @@ -406,6 +406,7 @@ void pop3_top(char *argbuf) { if ((buf[0]==13)||(buf[0]==10)) in_body = 1; } if (buf[strlen(buf)-1] != 10) cprintf("\n"); + fclose(fp); cprintf(".\r\n"); } diff --git a/citadel/serv_pop3.h b/citadel/serv_pop3.h index 40b527c0c..c2f2bc440 100644 --- a/citadel/serv_pop3.h +++ b/citadel/serv_pop3.h @@ -7,7 +7,6 @@ struct pop3msg { long msgnum; size_t rfc822_length; int deleted; - FILE *temp; }; struct citpop3 { /* Information about the current session */ diff --git a/citadel/server.h b/citadel/server.h index e0b5335bc..8b3bf2931 100644 --- a/citadel/server.h +++ b/citadel/server.h @@ -438,14 +438,15 @@ struct visit { /* Supplementary data for a message on disk - * (These are kept separately from the message itself because they are - * fields whose values may change at some point after the message is saved.) + * These are kept separate from the message itself for one of two reasons: + * 1. Either their values may change at some point after initial save, or + * 2. They are merely caches of data which exist somewhere else, for speed. */ struct MetaData { - long meta_msgnum; /* Message number in *local* message base */ - int meta_refcount; /* Number of rooms which point to this msg */ - char meta_content_type[64]; - /* more stuff will be added to this record in the future */ + long meta_msgnum; /* Message number in *local* message base */ + int meta_refcount; /* Number of rooms pointing to this msg */ + char meta_content_type[64]; /* Cached MIME content-type */ + long meta_rfc822_length; /* Cache of RFC822-translated msg length */ };