Xref: utzoo gnu.emacs.gnus:556 alt.sources:1562 Path: utzoo!censor!geac!torsqnt!jarvis.csri.toronto.edu!clyde.concordia.ca!uunet!mcsun!hp4nl!mhres!jv From: jv@mh.nl (Johan Vromans) Newsgroups: gnu.emacs.gnus,alt.sources Subject: Fast nnspool-find-article-by-message-id function Message-ID: Date: 5 Mar 90 20:42:07 GMT Sender: jv@mhres.mh.nl Organization: Multihouse Gouda, the Netherlands Lines: 286 This shar archive contains a fast lookup article by id mechanism for GNUS using NNSPOOL. It works only if yoy have built NEWS with [n]dbm or dbz. Enjoy. Johan #---------------------------------- cut here ---------------------------------- # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # # Wrapped by Johan Vromans on Mon Mar 5 13:38:39 1990 # # This archive contains: # README getartbyid.c getartbyid.el # # Existing files will not be overwritten. # Error checking via wc(1) will be performed. LANG=""; export LANG if test -f README then echo Ok to overwrite existing file README\? read answer case "$answer" in [yY]*) echo Proceeding;; *) echo Aborting; exit 1;; esac rm -f README if test -f README then echo Error: could not remove README, aborting exit 1 fi fi echo x - README cat >README <<'@EOF' This shar archive contains a fast lookup article by id mechanisme for GNUS using NNSPOOL. It works only if yoy have built NEWS with [n]dbm or dbz. It consists of a replacement function for nnspool-find-article-by-message-id, and a fast lookup program. The program should be compiled and placed somewher in your PATH. Compile with: gcc -s -O getartbyid.c -o getartbyid -ldbm It also works with vanilla CC and Jon Zeeff's DBZ. Load getartbyid.el after loading gnus/nnspool, and you will have a blinding fast '^' key. Motivation: I created this function since I could not afford Emacs to carry an 8Mb buffer all of the time - other programs started running out of VM. Enjoy. @EOF set `wc -lwc getartbyid.c <<'@EOF' /* getartinfo.c - fetch article info using Bnews history file */ /* Usage: getartinfo [-v] [id] ... */ #include #include #include /* DBM / DBZ declarations */ typedef struct { char *dptr; int dsize; } datum; datum fetch (); /* other forwards */ char *memcpy (); static char *lcase (); #define HISTFILE "/usr/lib/news/history" #define BUFLEN 512 int f_verbose = 0; main (argc, argv) int argc; char *argv[]; { FILE *hist = NULL; /* history file, if opened */ datum key, val; /* DBM items */ int fail = 0; /* failure count */ char artbuf [BUFLEN]; /* buf to hold article id */ char *artid; /* pointer to article id */ char buf [BUFLEN]; /* read buf for history file */ long fpos; /* seek position in hist file */ char *p; /* */ if (argc >= 1 && !strcmp (argv[1], "-v")) { argc--; argv++; f_verbose = 1; } /* initialize DBM */ if (dbminit (HISTFILE) < 0) { perror (HISTFILE); return -1; } /* process arguments */ while (--argc > 0) { /* copy article id into article buf, provide < and > if needed */ strcpy (artid = artbuf+1, *++argv); if (*artid != '<') { *--artid = '<'; strcat (artid, ">"); } /* lowcase and build DBM key */ key.dptr = artid; key.dsize = strlen (key.dptr)+1; lcase (key.dptr, key.dsize-1); /* fetch from DBM */ val = fetch (key); if (val.dptr == NULL) { if (f_verbose) fprintf (stderr, "%s: not found\n", *argv); fail++; /* tally */ continue; } /* open the history file upon first need */ if (hist == NULL) { if ((hist = fopen (HISTFILE, "r")) == NULL) { perror (HISTFILE); return -1; } } /* get the file pos from the DBM return value */ memcpy ((char*)&fpos, val.dptr, sizeof(long)); /* look it up */ if (fseek (hist, fpos, 0) < 0 ) { if (f_verbose) perror ("seek"); fail++; continue; } if (fgets (buf, BUFLEN, hist) == NULL) { if (f_verbose) perror ("read"); fail++; continue; } /* check if it is the right article */ p = strchr (buf, '\t'); if (p == NULL) p = strchr (buf, '\n'); *p = 0; lcase (buf, strlen (buf)); if (strcmp (buf, key.dptr) != 0) { /* it's not */ if (f_verbose) fprintf (stderr, "db corrupt?\n"); fail++; continue; } *p = '\t'; /* print results */ buf[strlen(buf)-1] = '\0'; /* zap the \n */ printf ("%s\n", buf); } /* wrap up */ dbmclose (); if (hist != NULL) fclose (hist); /* return number of failures */ return fail; } static char *lcase (s) register char *s; { register int n = strlen (s); for (s += n; n > 0; --n) { if (isupper(*--s)) *s = tolower(*s); } return s; } @EOF set `wc -lwc getartbyid.el <<'@EOF' (defun nnspool-find-article-by-message-id (id) "Return full pathname of an article identified by message-ID. This function uses an external C-program to do the history lookup." (save-excursion (let ((aname nil) (buffer (get-buffer-create "*newshistory*"))) (set-buffer buffer) (erase-buffer) (call-process "getartbyid" nil t nil id) (goto-char (point-min)) (prog1 (if (re-search-forward (concat "^" (regexp-quote id) "[ \t].*[ \t]\\([^ \t/]+\\)/\\([0-9]+\\)[ \t]*$") nil t) (let ((group (buffer-substring (match-beginning 1) (match-end 1))) (number (buffer-substring (match-beginning 2) (match-end 2)))) (concat (nnspool-article-pathname (nnspool-replace-chars-in-string group ?. ?/)) number))) (set-buffer-modified-p nil) (kill-buffer buffer))))) @EOF set `wc -lwc