Note to readers: After you apply this patch, your queue will no longer be readable in its current state. So, either install this into /var/qmail2 and run both qmails until the queue is emptied on the old one, or else accept that your current queue will have to be destroyed and ``rm -rf /var/qmail/queue; make setup''. From: Bruce Guenter To: Russell Nelson Subject: Missing piece of your big-todo patch Date: Tue, 3 Aug 1999 08:12:11 -0600 Greetings. While testing the performance of a big todo directory, I observed that qmail-qstat miscounted the number of messages in the todo directory. I've appended the necessary patch to yours. -- Bruce Guenter http://em.ca/~bruceg/ diff -u orig/qmail-clean.c ./qmail-clean.c --- orig/qmail-clean.c Tue Apr 15 01:05:23 1997 +++ ./qmail-clean.c Thu Jul 10 16:20:33 1997 @@ -73,22 +73,26 @@ if (line.len < 7) { respond("x"); continue; } if (line.len > 100) { respond("x"); continue; } if (line.s[line.len - 1]) { respond("x"); continue; } /* impossible */ - for (i = 5;i < line.len - 1;++i) + for (i = line.len - 2;i > 4;--i) + { + if (line.s[i] == '/') break; if ((unsigned char) (line.s[i] - '0') > 9) { respond("x"); continue; } - if (!scan_ulong(line.s + 5,&id)) { respond("x"); continue; } + } + if (line.s[i] == '/') + if (!scan_ulong(line.s + i + 1,&id)) { respond("x"); continue; } if (byte_equal(line.s,5,"foop/")) { #define U(prefix,flag) fmtqfn(fnbuf,prefix,id,flag); \ if (unlink(fnbuf) == -1) if (errno != error_noent) { respond("!"); continue; } - U("intd/",0) + U("intd/",1) U("mess/",1) respond("+"); } else if (byte_equal(line.s,4,"todo/")) { - U("intd/",0) - U("todo/",0) + U("intd/",1) + U("todo/",1) respond("+"); } else diff -u orig/hier.c ./hier.c --- orig/hier.c Tue Apr 15 01:05:23 1997 +++ ./hier.c Tue Jul 8 13:40:50 1997 @@ -100,6 +100,8 @@ substdio_puts(subfdout,"622:/queue/lock/:trigger:\n"); dsplit("queue/mess",auto_uidq,0750); + dsplit("queue/todo",auto_uidq,0750); + dsplit("queue/intd",auto_uidq,0700); dsplit("queue/info",auto_uids,0700); dsplit("queue/local",auto_uids,0700); dsplit("queue/remote",auto_uids,0700); diff -u orig/qmail-queue.c ./qmail-queue.c --- orig/qmail-queue.c Tue Apr 15 01:05:23 1997 +++ ./qmail-queue.c Tue Jul 8 13:33:17 1997 @@ -180,8 +180,8 @@ messnum = pidst.st_ino; messfn = fnnum("mess/",1); - todofn = fnnum("todo/",0); - intdfn = fnnum("intd/",0); + todofn = fnnum("todo/",1); + intdfn = fnnum("intd/",1); if (link(pidfn,messfn) == -1) die(105); if (unlink(pidfn) == -1) die(105); diff -u orig/qmail-send.c ./qmail-send.c --- orig/qmail-send.c Tue Apr 15 01:05:23 1997 +++ ./qmail-send.c Wed Jul 9 02:04:09 1997 @@ -101,7 +101,7 @@ } void fnmake_info(id) unsigned long id; { fn.len = fmtqfn(fn.s,"info/",id,1); } -void fnmake_todo(id) unsigned long id; { fn.len = fmtqfn(fn.s,"todo/",id,0); } +void fnmake_todo(id) unsigned long id; { fn.len = fmtqfn(fn.s,"todo/",id,1); } void fnmake_mess(id) unsigned long id; { fn.len = fmtqfn(fn.s,"mess/",id,1); } void fnmake_foop(id) unsigned long id; { fn.len = fmtqfn(fn.s,"foop/",id,0); } void fnmake_split(id) unsigned long id; { fn.len = fmtqfn(fn.s,"",id,1); } @@ -1242,7 +1242,8 @@ /* this file is too long ---------------------------------------------- TODO */ datetime_sec nexttodorun; -DIR *tododir; /* if 0, have to opendir again */ +int flagtododir = 0; /* if 0, have to readsubdir_init again */ +readsubdir todosubdir; stralloc todoline = {0}; char todobuf[SUBSTDIO_INSIZE]; char todobufinfo[512]; @@ -1250,7 +1251,7 @@ void todo_init() { - tododir = 0; + flagtododir = 0; nexttodorun = now(); trigger_set(); } @@ -1262,7 +1263,7 @@ { if (flagexitasap) return; trigger_selprep(nfds,rfds); - if (tododir) *wakeup = 0; + if (flagtododir) *wakeup = 0; if (*wakeup > nexttodorun) *wakeup = nexttodorun; } @@ -1279,8 +1280,7 @@ char ch; int match; unsigned long id; - unsigned int len; - direntry *d; + int z; int c; unsigned long uid; unsigned long pid; @@ -1291,32 +1291,26 @@ if (flagexitasap) return; - if (!tododir) + if (!flagtododir) { if (!trigger_pulled(rfds)) if (recent < nexttodorun) return; trigger_set(); - tododir = opendir("todo"); - if (!tododir) - { - pausedir("todo"); - return; - } + readsubdir_init(&todosubdir, "todo", pausedir); + flagtododir = 1; nexttodorun = recent + SLEEP_TODO; } - d = readdir(tododir); - if (!d) + switch(readsubdir_next(&todosubdir, &id)) { - closedir(tododir); - tododir = 0; - return; + case 1: + break; + case 0: + flagtododir = 0; + default: + return; } - if (str_equal(d->d_name,".")) return; - if (str_equal(d->d_name,"..")) return; - len = scan_ulong(d->d_name,&id); - if (!len || d->d_name[len]) return; fnmake_todo(id); --- qmail-1.03/qmail-qstat.sh.orig Tue Aug 3 08:06:47 1999 +++ qmail-1.03/qmail-qstat.sh Tue Aug 3 08:06:38 1999 @@ -3,7 +3,7 @@ cd /var/qmail messdirs=`echo queue/mess/* | wc -w` messfiles=`find queue/mess/* -print | wc -w` -tododirs=`echo queue/todo | wc -w` -todofiles=`find queue/todo -print | wc -w` +tododirs=`echo queue/todo/* | wc -w` +todofiles=`find queue/todo/* -print | wc -w` echo messages in queue: `expr $messfiles - $messdirs` echo messages in queue but not yet preprocessed: `expr $todofiles - $tododirs`