1: /* putnode -- store node and link structrures temporarily in a disk file */
   2: 
   3: #include "def.h"
   4: #ifdef TMPFILES
   5: /*
   6:  * Sizes of node and link caches.  These must be big enough to prevent entries
   7:  * being flushed during assignments (e.g. getlink(l)->l_to = function(x),
   8:  * where function(x) pulls more than LINKCACHE entries into the cache).  This
   9:  * is because the left hand side of the assignment is evaluated first and
  10:  * subsequent evaluation of the right hand side may replace the contents of
  11:  * the address being written into by a more recently used link (at least in
  12:  * Ritchie's compiler).  This causes obscure errors.  Avoid assignments of
  13:  * this type if the function makes lots of calls to getlink() or getnode().
  14:  * Ten is certainly big enough, but hardly optimal.  If you need more memory,
  15:  * shrink the hash table in addnode.c, don't change these.
  16:  */
  17: #define NODECACHE 35    /* tradeoff between user and sys time */
  18: #define LINKCACHE 35
  19: 
  20: /*
  21:  * Linked lists and other miscellaneous cache debris.
  22:  */
  23: static struct nodecache {
  24:     struct nodecache *next;
  25:     struct nodecache *prev;
  26:     struct node node;
  27: } nodecache[NODECACHE];
  28: 
  29: static struct linkcache {
  30:     struct linkcache *next;
  31:     struct linkcache *prev;
  32:     struct link link;
  33: } linkcache[LINKCACHE];
  34: 
  35: static struct nodecache *topnode;
  36: static struct linkcache *toplink;
  37: 
  38: /*
  39:  * We set up offsets of zero to map to NULL for simplicity.
  40:  */
  41: node    nullnode;
  42: link    nulllink;
  43: 
  44: /* exports */
  45: void initstruct();
  46: extern node *getnode();
  47: extern link *getlink();
  48: char *nfile, *lfile, *sfile;
  49: int fdnode, fdlink, fdname;
  50: long nhits, lhits, nmisses, lmisses;
  51: 
  52: /* imports */
  53: extern void nomem(), die();
  54: char *mktemp();
  55: off_t lseek();
  56: 
  57: /* privates */
  58: STATIC void nodewrite(), noderead(), linkwrite(), linkread();
  59: 
  60: /*
  61:  * Opens and initializes temporary files and caches.
  62:  */
  63: void
  64: initstruct()
  65: {
  66:     register int i;
  67: 
  68:     /* Open the temporary files. */
  69:     nfile = mktemp("/tmp/nodeXXXXXX");
  70:     if ((fdnode = open(nfile, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0) {
  71:         perror(nfile);
  72:         exit(1);
  73:     }
  74:     lfile = mktemp("/tmp/linkXXXXXX");
  75:     if ((fdlink = open(lfile, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0) {
  76:         perror(lfile);
  77:         exit(1);
  78:     }
  79:     sfile = mktemp("/tmp/nameXXXXXX");
  80:     if ((fdname = open(sfile, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0) {
  81:         perror(sfile);
  82:         exit(1);
  83:     }
  84: 
  85:     /* Put the handy null nodes, etc. at offset zero. */
  86:     (void) write(fdnode, (char *) &nullnode, sizeof(nullnode));
  87:     (void) write(fdlink, (char *) &nulllink, sizeof(nulllink));
  88:     (void) write(fdname, "\0", 1);
  89: 
  90:     /* Link the caches together. */
  91:     topnode = &nodecache[0];
  92:     topnode->prev = (struct nodecache *) NULL;
  93:     topnode->next = &nodecache[1];
  94:     for (i = 1; i < NODECACHE - 1; i++) {
  95:         nodecache[i].next = &nodecache[i+1];
  96:         nodecache[i].prev = &nodecache[i-1];
  97:     }
  98:     nodecache[NODECACHE - 1].prev = &nodecache[NODECACHE - 2];
  99:     nodecache[NODECACHE - 1].next = (struct nodecache *) NULL;
 100: 
 101:     toplink = &linkcache[0];
 102:     toplink->prev = (struct linkcache *) NULL;
 103:     toplink->next = &linkcache[1];
 104:     for (i = 1; i < LINKCACHE - 1; i++) {
 105:         linkcache[i].next = &linkcache[i+1];
 106:         linkcache[i].prev = &linkcache[i-1];
 107:     }
 108:     linkcache[LINKCACHE - 1].prev = &linkcache[LINKCACHE - 2];
 109:     linkcache[LINKCACHE - 1].next = (struct linkcache *) NULL;
 110: }
 111: 
 112: /*
 113:  * Returns pointer to node; takes sequence number of node.
 114:  */
 115: node *
 116: getnode(n_seq)
 117: register p_node n_seq;
 118: {
 119:     register struct nodecache *tnode;
 120: 
 121:     /* Don't bother to retrieve the null entry. */
 122:     if (n_seq == 0)
 123:         return((node *) NULL);
 124: 
 125:     /*
 126: 	 * First search for the correct entry in the cache.  If we find it,
 127: 	 * move it to the top of the cache.
 128: 	 */
 129:     for (tnode = topnode; tnode->next; tnode = tnode->next) {
 130:         if (n_seq == tnode->node.n_seq) {
 131: found:          if (tnode->prev) {
 132:                 tnode->prev->next = tnode->next;
 133:                 if (tnode->next)
 134:                     tnode->next->prev = tnode->prev;
 135:                 tnode->prev = (struct nodecache *) NULL;
 136:                 tnode->next = topnode;
 137:                 topnode->prev = tnode;
 138:                 topnode = tnode;
 139:             }
 140:             nhits++;
 141:             return(&tnode->node);
 142:         }
 143:     }
 144:     if (n_seq == tnode->node.n_seq)
 145:         goto found;
 146: 
 147:     /*
 148: 	 * If it isn't in the cache, see if the last one in the
 149: 	 * cache has valid data.  If it does, write it out, free
 150: 	 * the name pointer, fill it with the data we want, and
 151: 	 * move it to the top of the cache.
 152: 	 */
 153:     if (tnode->node.n_seq)
 154:         nodewrite(&tnode->node);
 155:     if (tnode->node.n_name)
 156:         free((char *) tnode->node.n_name);
 157:     tnode->prev->next = (struct nodecache *) NULL;
 158:     tnode->prev = (struct nodecache *) NULL;
 159:     tnode->next = topnode;
 160:     topnode->prev = tnode;
 161:     topnode = tnode;
 162: 
 163:     noderead(&tnode->node, n_seq);
 164: 
 165:     nmisses++;
 166:     return(&tnode->node);
 167: }
 168: 
 169: /*
 170:  * Write out a node in cache to disk.  Takes a pointer to the node to be
 171:  * written.  If the name of the node hasn't ever been written to disk (as
 172:  * will be the case with new nodes), n_fname will be null; we fill it in and
 173:  * write the name to the name temporary file.
 174:  */
 175: STATIC void
 176: nodewrite(n)
 177: node *n;
 178: {
 179:     if (n->n_fname == 0) {
 180:         n->n_fname = lseek(fdname, (off_t) 0, L_XTND);
 181:         if (write(fdname, n->n_name, strlen(n->n_name) + 1) < 0) {
 182:             perror("writename");
 183:             exit(1);
 184:         }
 185:     }
 186:     (void) lseek(fdnode, (off_t) n->n_seq * sizeof(node), L_SET);
 187:     if (write(fdnode, (char *) n, sizeof(node)) < 0) {
 188:         perror("nodewrite");
 189:         exit(1);
 190:     }
 191: }
 192: 
 193: /*
 194:  * Read a node from the disk into the cache.  Takes the sequence number of the
 195:  * node to be read.  We first read in the node, then set and fill in the
 196:  * pointer to the name of the node.
 197:  */
 198: STATIC void
 199: noderead(n, n_seq)
 200: node *n;
 201: p_node n_seq;
 202: {
 203:     (void) lseek(fdnode, (off_t) n_seq * sizeof(node), L_SET);
 204:     if (read(fdnode, (char *) n, sizeof(node)) < 0) {
 205:         perror("noderead");
 206:         exit(1);
 207:     }
 208:     if (n->n_fname) {
 209:         if ((n->n_name = calloc(1, MAXNAME + 1)) == 0)
 210:             nomem();
 211:         (void) lseek(fdname, n->n_fname, L_SET);
 212:         if (read(fdname, n->n_name, MAXNAME + 1) < 0) {
 213:             perror("readname");
 214:             exit(1);
 215:         }
 216:     }
 217:     if (n->n_seq && n->n_seq != n_seq) {        /* sanity check */
 218:         fprintf(stderr, "noderead %u gives %u\n", n_seq, n->n_seq);
 219:         die("impossible retrieval error");
 220:     }
 221: }
 222: 
 223: /*
 224:  * Returns pointer to link; takes sequence number of link.
 225:  */
 226: link *
 227: getlink(l_seq)
 228: register p_link l_seq;
 229: {
 230:     register struct linkcache *tlink;
 231: 
 232:     /* Don't bother to retrieve the null entry. */
 233:     if (l_seq == 0)
 234:         return((link *) NULL);
 235: 
 236:     /*
 237: 	 * First search for the correct entry in the cache.  If we find it,
 238: 	 * move it to the top of the cache.
 239: 	 */
 240:     for (tlink = toplink; tlink->next; tlink = tlink->next) {
 241:         if (l_seq == tlink->link.l_seq) {
 242: found:          if (tlink->prev) {
 243:                 tlink->prev->next = tlink->next;
 244:                 if (tlink->next)
 245:                     tlink->next->prev = tlink->prev;
 246:                 tlink->prev = (struct linkcache *) NULL;
 247:                 tlink->next = toplink;
 248:                 toplink->prev = tlink;
 249:                 toplink = tlink;
 250:             }
 251:             lhits++;
 252:             return(&tlink->link);
 253:         }
 254:     }
 255:     if (l_seq == tlink->link.l_seq)
 256:         goto found;
 257: 
 258:     /*
 259: 	 * If it isn't in the cache, see if the last one in the cache has
 260: 	 * valid data.  If it does, write it out, fill it with the data we
 261: 	 * want, and move it to the top of the cache.
 262: 	 */
 263:     if (tlink->link.l_seq)
 264:         linkwrite(&tlink->link);
 265:     tlink->prev->next = (struct linkcache *) NULL;
 266:     tlink->prev = (struct linkcache *) NULL;
 267:     tlink->next = toplink;
 268:     toplink->prev = tlink;
 269:     toplink = tlink;
 270: 
 271:     linkread(&tlink->link, l_seq);
 272: 
 273:     lmisses++;
 274:     return(&tlink->link);
 275: }
 276: 
 277: /*
 278:  * Write out a link in cache to disk.  Takes a pointer to the link to be
 279:  * written.
 280:  */
 281: STATIC void
 282: linkwrite(l)
 283: link *l;
 284: {
 285:     (void) lseek(fdlink, (off_t) l->l_seq * sizeof(link), L_SET);
 286:     if (write(fdlink, (char *) l, sizeof(link)) < 0) {
 287:         perror("linkwrite");
 288:         exit(1);
 289:     }
 290: }
 291: 
 292: /*
 293:  * Read a link from the disk into the cache.  Takes the sequence number of the
 294:  * link to be read.
 295:  */
 296: STATIC void
 297: linkread(l, l_seq)
 298: link *l;
 299: p_link l_seq;
 300: {
 301:     (void) lseek(fdlink, (off_t) l_seq * sizeof(link), L_SET);
 302:     if (read(fdlink, (char *) l, sizeof(link)) < 0) {
 303:         perror("linkread");
 304:         exit(1);
 305:     }
 306: }
 307: #endif /*TMPFILES*/

Defined functions

getlink defined in line 226; used 3 times
getnode defined in line 115; used 3 times
initstruct defined in line 63; used 3 times
linkread defined in line 296; used 2 times
linkwrite defined in line 281; used 2 times
noderead defined in line 198; used 2 times
nodewrite defined in line 175; used 2 times

Defined variables

fdlink defined in line 49; used 8 times
fdname defined in line 49; used 6 times
fdnode defined in line 49; used 8 times
lfile defined in line 48; used 5 times
lhits defined in line 50; used 2 times
linkcache defined in line 33; used 9 times
lmisses defined in line 50; used 2 times
nfile defined in line 48; used 3 times
nhits defined in line 50; used 2 times
nmisses defined in line 50; used 2 times
nodecache defined in line 27; used 9 times
nulllink defined in line 42; used 3 times
nullnode defined in line 41; used 3 times
sfile defined in line 48; used 5 times
toplink defined in line 36; used 10 times
topnode defined in line 35; used 10 times

Defined struct's

linkcache defined in line 29; used 18 times
nodecache defined in line 23; used 18 times

Defined macros

LINKCACHE defined in line 18; used 5 times
NODECACHE defined in line 17; used 5 times
Last modified: 1988-07-10
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4326
Valid CSS Valid XHTML 1.0 Strict