home *** CD-ROM | disk | FTP | other *** search
/ Unix System Administration Handbook 1997 October / usah_oct97.iso / news / cnews.tar / libbig / active.fast.c next >
C/C++ Source or Header  |  1993-03-13  |  5KB  |  205 lines

  1. /*
  2.  * active file access functions (big, fast, in-memory version)
  3.  */
  4.  
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <errno.h>
  9. #include "fixerrno.h"
  10. #include <sys/types.h>
  11. #include <sys/stat.h>
  12.  
  13. #include "libc.h"
  14. #include "news.h"
  15. #include "config.h"
  16. #include "active.h"
  17. #include "hdbm.h"
  18.  
  19. /* private */
  20. static char *active = NULL;    /* cache: points at entire active file */
  21. static int actsize;        /* bytes in active: type int fixed by fread */
  22. static char **actlnps;        /* point at lines in active file */
  23. static unsigned actlines;    /* lines in actlnps actually used */
  24. static HASHTABLE *acttbl;
  25.  
  26. /* imports from active.c */
  27. extern char actrelnm[];
  28.  
  29. STATIC statust
  30. actmkindx()            /* build actlnps index for active */
  31. {
  32.     register statust status = ST_OKAY;
  33.     unsigned lnpsz;
  34.     int maxlines;        /* should this really be long? */
  35.  
  36.     active[actsize] = '\0';        /* make a proper string */
  37.     /* +1 for a possible partial line +1 for a dummy to check overflow */
  38.     maxlines = charcount(active, '\n') + 2;
  39.     lnpsz = sizeof(char *) * (long) maxlines;
  40.     if (lnpsz != sizeof(char *) * (long)maxlines ||
  41.         (actlnps = (char **)malloc(lnpsz)) == NULL) {
  42.         persistent(NOART, 'm', "`%s' index won't fit in memory",
  43.             ctlfile(actrelnm));
  44.         status |= ST_DROPPED|ST_NEEDATTN;
  45.     } else {
  46.         actlnps[maxlines - 2] = "";    /* in case no partial line */
  47.         actlnps[maxlines - 1] = "";    /* end sentinel */
  48.         actlines = linescan(active, actlnps, maxlines);
  49.         if (actlines >= maxlines) {
  50.             canthappen(NOART, 'i', "too many newsgroups in `%s'",
  51.                 ctlfile(actrelnm));
  52.             status |= ST_DROPPED|ST_NEEDATTN;
  53.         }
  54.     }
  55.     return status;
  56. }
  57.  
  58. STATIC statust
  59. hashlines()
  60. {
  61.     register statust status = ST_OKAY;
  62.     register char *pos;
  63.     register unsigned line = 0;
  64.  
  65.     acttbl = hdbmcreate(1000, (unsigned (*)())NULL);
  66.     while (pos = actlnps[line], line++ < actlines && pos[0] != '\0') {
  67.         register char *sp;
  68.         HDBMDATUM key, data;
  69.  
  70.         STRCHR(pos, ' ', sp);
  71.         if (sp == NULL)
  72.             continue;        /* junk */
  73.         key.dat_len = sp - pos;
  74.         key.dat_ptr = pos;
  75.         data.dat_len = 0;        /* fake */
  76.         data.dat_ptr = pos;
  77.         errno = 0;
  78.         if (!hdbmstore(acttbl, key, data)) {
  79.             persistent(NOART, 'f', "can't store active hash item",
  80.                 "");
  81.             status |= ST_DROPPED|ST_NEEDATTN;
  82.             break;
  83.         }
  84.     }
  85.     return status;
  86. }
  87.  
  88. STATIC void
  89. freeactive()
  90. {
  91.     nnfree(&active);
  92.     nnafree(&actlnps);
  93.     hdbmdestroy(acttbl);
  94.     acttbl = NULL;
  95. }
  96.  
  97. statust
  98. actfload(fp)
  99. FILE *fp;
  100. {
  101.     statust status = ST_OKAY;
  102.  
  103.     if (fp != NULL && active == NULL) {
  104.         struct stat sb;
  105.  
  106.         errno = 0;
  107.         if (fstat(fileno(fp), &sb) < 0)
  108.             persistent(NOART, 'f', "can't fstat `%s'",
  109.                    ctlfile(actrelnm));
  110.         else if (actsize = sb.st_size, /* squeeze into an int */
  111.             (unsigned)actsize != sb.st_size)
  112.             persistent(NOART, 'f', "`%s' won't fit into memory",
  113.                    ctlfile(actrelnm));
  114.         else if ((active = malloc((unsigned)actsize+1)) == NULL)
  115.             persistent(NOART, 'm', "can't allocate memory for `%s'",
  116.                 ctlfile(actrelnm));
  117.         else {
  118.             rewind(fp);
  119.             /*
  120.              * If we read with fgetms, we might be able to avoid
  121.              * calling linescan().
  122.              */
  123.             if (fread(active, 1, actsize, fp) != actsize) {
  124.                 persistent(NOART, 'f', "error reading `%s'",
  125.                     ctlfile(actrelnm));
  126.                 status |= ST_DROPPED|ST_NEEDATTN;
  127.             } else
  128.                 status |= actmkindx();
  129.         }
  130.         if (active == NULL) {
  131.             persistent(NOART, '\0', "can't read active", "");
  132.             status |= ST_DROPPED|ST_NEEDATTN;
  133.         }
  134.         if (status == ST_OKAY)
  135.             status |= hashlines();
  136.         if (status != ST_OKAY)
  137.             freeactive();
  138.     }
  139.     return status;
  140. }
  141.  
  142. /*
  143.  * Store in lnarray the addresses of the starts of lines in s.
  144.  * Return the number of lines found; if greater than nent,
  145.  * store only nent and return nent.
  146.  * Thus lnarray should be one bigger than needed to detect overflow.
  147.  */
  148. int
  149. linescan(s, lnarray, nent)
  150. char *s;
  151. char **lnarray;
  152. register int nent;
  153. {
  154.     register char **lnarrp = lnarray;
  155.     register int i = 0;
  156.     register char *nlp = s;
  157.  
  158.     if (i < nent)
  159.         *lnarrp++ = nlp;
  160.     while (++i < nent && (nlp=strchr(nlp, '\n')) != NULL && *++nlp != '\0')
  161.         *lnarrp++ = nlp;
  162.     return i;        /* number of addrs stored */
  163. }
  164.  
  165. statust
  166. actfsync(fp)            /* write to disk, fp is open */
  167. FILE *fp;
  168. {
  169.     statust status = ST_OKAY;
  170.  
  171.     rewind(fp);
  172.     if (active != NULL) {
  173.         if (fwrite(active, actsize, 1, fp) != 1) {
  174.             persistent(NOART, '\0', "write failed", "");
  175.             status |= ST_DROPPED|ST_NEEDATTN;
  176.         }
  177.         freeactive();
  178.     }
  179.     return status;
  180. }
  181.  
  182. /* ARGSUSED fp */
  183. char *
  184. actfind(fp, ng, nglen)
  185. FILE *fp;
  186. register char *ng;
  187. register int nglen;
  188. {
  189.     HDBMDATUM key, data;
  190.  
  191.     key.dat_ptr = ng;
  192.     key.dat_len = nglen;
  193.     data = hdbmfetch(acttbl, key);
  194.     return data.dat_ptr;
  195. }
  196.  
  197. /* ARGSUSED */
  198. statust
  199. actfwrnum(fp, pos)
  200. FILE *fp;
  201. char *pos;
  202. {
  203.     return ST_OKAY;
  204. }
  205.