Here is the 2.1.4 port of the master process counting patch. It will be in Debian's Cyrus IMAPd package 2.1.4-9, to be uploaded today or tomorrow.
None of the unrelated changes in the fastmail.fm patchset were included, just the improvements to the tracking of the number of available workers. Original patch credits goes to the fastmail.fm crew. Thanks, guys. Please consider applying this path to 2.1.4 CVS. I will file a bugreport in bugzilla with the patch. -- "One disk to rule them all, One disk to find them. One disk to bring them all and in the darkness grind them. In the Land of Redmond where the shadows lie." -- The Silicon Valley Tarot Henrique Holschuh
Index: master/master.c =================================================================== RCS file: /home/cvs/debian/cyrus21-imapd/master/master.c,v retrieving revision 1.13 retrieving revision 1.14 diff -u -r1.13 -r1.14 --- master/master.c 12 Apr 2002 00:38:19 -0000 1.13 +++ master/master.c 15 May 2002 13:57:00 -0000 1.14 @@ -124,6 +124,7 @@ struct centry { pid_t pid; + int is_available; struct service *s; struct centry *next; }; @@ -658,6 +659,7 @@ /* add to child table */ c = get_centry(); c->pid = p; + c->is_available = 1; c->s = s; c->next = ctable[p % child_table_size]; ctable[p % child_table_size] = c; @@ -792,7 +794,12 @@ /* first thing in the linked list */ /* decrement active count for service */ - if (c->s) c->s->nactive--; + if (c->s) { + c->s->nactive--; + if (c->is_available) c->s->ready_workers--; + } else { + syslog(LOG_ERR, "no service found, child %d", pid); + } ctable[pid % child_table_size] = c->next; c->next = cfreelist; @@ -809,7 +816,12 @@ t = c->next; /* decrement active count for service */ - if (t->s) t->s->nactive--; + if (t->s) { + t->s->nactive--; + if (c->is_available) t->s->ready_workers--; + } else { + syslog(LOG_ERR, "no service found, child %d", pid); + } c->next = t->next; /* remove node */ t->next = cfreelist; /* add to freelist */ @@ -899,24 +911,39 @@ } } -void process_msg(struct service *s, int msg) +void process_msg(struct service *s, struct notify_message *msg) { - switch (msg) { + struct centry * c; + + /* Search hash table with linked list for pid */ + c = ctable[msg->service_pid % child_table_size]; + while (c && c->pid != msg->service_pid) c = c->next; + + /* Did we find it? */ + if (!c || c->pid != msg->service_pid) { + syslog(LOG_ERR, "can't find pid %d to process message %d", + msg->service_pid, msg->message); + return; + } + + switch (msg->message) { case MASTER_SERVICE_AVAILABLE: + c->is_available = 1; s->ready_workers++; break; case MASTER_SERVICE_UNAVAILABLE: + c->is_available = 0; s->ready_workers--; break; case MASTER_SERVICE_CONNECTION: s->nconnections++; break; - + default: syslog(LOG_ERR, "unrecognized message for service '%s': %x", - s->name, msg); + s->name, msg->message); break; } @@ -1340,7 +1367,7 @@ syslog(LOG_NOTICE, "ready for work"); for (;;) { - int r, i, msg, maxfd; + int r, i, maxfd; struct timeval tv, *tvptr; time_t now = time(NULL); #if HAVE_UCDSNMP @@ -1448,13 +1475,15 @@ int j; if (FD_ISSET(x, &rfds)) { - r = read(x, &msg, sizeof(int)); - if (r != sizeof(int)) { + struct notify_message message; + + r = read(x, &message, sizeof(message)); + if (r != sizeof(message)) { syslog(LOG_ERR, "got weird response from child: %x", i); continue; } - - process_msg(&Services[i], msg); + + process_msg(&Services[i], &message); } if (Services[i].nactive < Services[i].max_workers) { Index: master/service.c =================================================================== RCS file: /home/cvs/debian/cyrus21-imapd/master/service.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- master/service.c 14 May 2002 13:18:25 -0000 1.2 +++ master/service.c 15 May 2002 13:57:00 -0000 1.3 @@ -79,8 +79,11 @@ void notify_master(int fd, int msg) { - if (verbose) syslog(LOG_DEBUG, "telling master %d", msg); - if (write(fd, &msg, sizeof(msg)) != sizeof(msg)) { + struct notify_message notifymsg; + if (verbose) syslog(LOG_DEBUG, "telling master %x", msg); + notifymsg.message = msg; + notifymsg.service_pid = getpid(); + if (write(fd, ¬ifymsg, sizeof(notifymsg)) != sizeof(notifymsg)) { syslog(LOG_ERR, "unable to tell master %x: %m", msg); } } Index: master/service.h =================================================================== RCS file: /home/cvs/debian/cyrus21-imapd/master/service.h,v retrieving revision 1.1.1.2 retrieving revision 1.2 diff -u -r1.1.1.2 -r1.2 --- master/service.h 11 Feb 2002 17:41:45 -0000 1.1.1.2 +++ master/service.h 15 May 2002 13:57:00 -0000 1.2 @@ -63,4 +63,9 @@ REUSE_TIMEOUT = 60 }; +struct notify_message { + int message; + pid_t service_pid; +}; + #endif