> Here's an abbreviated transcript of the *per group* conversation, > ignoring the beginning and ending parts: > > <- list active newsgroup-name > -> 215: list: > -> newsgroup-name <high> <low> <flag> > > This is repeated for each newsgroup in the screen. I suspect it tries > to avoid a full 'list active' which can be a long operation on a > loaded server. Ugh. That is rouge behavior. The list command should NOT be used for obtaining upto-date singular group information. The GROUP command is the correct place for that. nntpcache can locate an individual group data from the sum of newsgroups very quickly. It uses a 31337 (prime) entry hash table, with binary trees for resolving hash collisions. RFC977 defines the arguments to list as: LIST {active,newsgroup,active,times,overview.fmt} [pattern] Note the optional usage of the pattern keyword. This is typically used for examples like: LIST active alt.* and not for pulling in information on a specific group in isolation, which is what your news-reader appears to be doing. When the pattern argument is specified, nntpcache walks the entire group list, pattern matching every against every group. Here is a tiny patch to optimise for the case where the pattern isn't really a pattern at all, and use the hashing lookup scheme that other parts of nntpcache rely on - I'd be very surprised if trn4 isn't blindly fast after the following: -- Prof. Julian Assange |If you want to build a ship, don't drum up people |together to collect wood and don't assign them tasks proff@suburbia.net |and work, but rather teach them to long for the endless proff@gnu.ai.mit.edu |immensity of the sea. -- Antoine de Saint Exupery Index: list.c =================================================================== RCS file: /usr/local/cvs/nntpcache/list.c,v retrieving revision 1.92 diff -u -r1.92 list.c --- list.c 1997/03/06 10:48:56 1.92 +++ list.c 1997/03/23 19:18:07 @@ -407,6 +456,25 @@ } return lo; } +static void print_active(struct newsgroup *n) +{ + int hi, lo; + if (!n->moderation) + return; + hi = MAX(n->hi, n->hi_server); + if (n->lo>0) + lo = n->lo; + else + lo = 0; + if (n->lo_server>0) + { + if (lo>0) + lo = MIN(lo, n->lo_server); + else + lo = n->lo_server; + } + emitf ("%s %d %d %c\r\n", n->group, hi, lo, n->moderation); +} static bool doList (struct list_s *list, char *group_pat) { @@ -473,6 +541,20 @@ emitrn (NNTP_XGTITLE_OK); else emitrn (NNTP_LIST_FOLLOWS); + if (group_pat && !strpbrk(group_pat, "*?[]")) + { + if ((n = newsgroup_find_add(group_pat, NULL, FALSE))) +#ifdef READ_LOCKS + if (newsgroupLockRead(n)) + { + print_active(n); + n->read_locks--; + } +#else + print_active(n); +#endif + goto end; + } for (n=Ni->newsgroup_head; n; n=n->next) { #ifdef READ_LOCKS @@ -489,25 +571,8 @@ switch (list->type) { case l_active: - { - int hi, lo; - if (!n->moderation) - break; - hi = MAX(n->hi, n->hi_server); - if (n->lo>0) - lo = n->lo; - else - lo = 0; - if (n->lo_server>0) - { - if (lo>0) - lo = MIN(lo, n->lo_server); - else - lo = n->lo_server; - } - emitf ("%s %d %d %c\r\n", n->group, hi, lo, n->moderation); + print_active(n); break; - } case l_active_times: if (n->creation_time && n->creator) emitf ("%s %lu %s\r\n", n->group, n->creation_time, n->creator); @@ -527,6 +592,7 @@ continue; #endif } +end: emitrn ("."); return TRUE; }