* Each message's metadata now has the ability to cache the length of
authorArt Cancro <ajc@citadel.org>
Sat, 22 Jan 2005 03:14:21 +0000 (03:14 +0000)
committerArt Cancro <ajc@citadel.org>
Sat, 22 Jan 2005 03:14:21 +0000 (03:14 +0000)
  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.

citadel/ChangeLog
citadel/msgbase.c
citadel/serv_pop3.c
citadel/serv_pop3.h
citadel/server.h

index 75659d32ad80f63e5655cb2f6f298556e0cf439c..4c365b5c1da2b5ddbc63f5cc44facf6c6ee6043c 100644 (file)
@@ -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 <bryant@cs.usm.maine.edu>
 
 Fri Jul 10 1998 Art Cancro <ajc@uncensored.citadel.org>
        * Initial CVS import
-
index 697a67fbb78dccf4d2f198309e919d1b21ae4a16..2c34eaa76956a535e5e32c6745919dd467d3060f 100644 (file)
@@ -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 */
index 8401acc489d45038c59186a7d6d655ed96e8875b..cc01a6b1ac5a305a2d0dc014c2117d200cec3cea 100644 (file)
  * 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; i<POP3->num_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");
 }
 
index 40b527c0cd3d9fb88fba4b900ae04c95cb5a11a7..c2f2bc440568a6c2fd283c115a934d3a7bbc7d0b 100644 (file)
@@ -7,7 +7,6 @@ struct pop3msg {
        long msgnum;
        size_t rfc822_length;
        int deleted;
-       FILE *temp;
 };
 
 struct citpop3 {               /* Information about the current session */
index e0b5335bcec74b76b564157edbfa080530fe5ad0..8b3bf29315bd494efc85aecf7a066e779c68af22 100644 (file)
@@ -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 */
 };