ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/holofile.c
Revision: 3.27
Committed: Wed Nov 4 16:44:16 1998 UTC (25 years, 5 months ago) by gwlarson
Content type: text/plain
Branch: MAIN
Changes since 3.26: +3 -2 lines
Log Message:
bug fixes in hdinit() and hddone()

File Contents

# User Rev Content
1 gregl 3.20 /* Copyright (c) 1998 Silicon Graphics, Inc. */
2 gregl 3.1
3     #ifndef lint
4     static char SCCSid[] = "$SunId$ SGI";
5     #endif
6    
7     /*
8     * Routines for managing holodeck files
9     *
10     * 9/30/97 GWLarson
11     */
12    
13     #include "holo.h"
14    
15     #ifndef CACHESIZE
16     #define CACHESIZE 16 /* default cache size (Mbytes, 0==inf) */
17     #endif
18     #ifndef FREEBEAMS
19 gwlarson 3.25 #define FREEBEAMS 1500 /* maximum beams to free at a time */
20 gregl 3.1 #endif
21     #ifndef PCTFREE
22 gregl 3.21 #define PCTFREE 15 /* maximum fraction to free (%) */
23 gregl 3.1 #endif
24 gregl 3.15 #ifndef MAXFRAG
25 gregl 3.16 #define MAXFRAG 32767 /* maximum fragments/file to track (0==inf) */
26 gregl 3.15 #endif
27 gregl 3.1
28 gregl 3.6 #ifndef BSD
29     #define write writebuf /* safe i/o routines */
30     #define read readbuf
31     #endif
32 gregl 3.4
33 gregl 3.16 #define FRAGBLK 256 /* number of fragments to allocate at a time */
34 gregl 3.4
35 gregl 3.14 unsigned hdcachesize = CACHESIZE*1024*1024; /* target cache size */
36 gregl 3.1 unsigned long hdclock; /* clock value */
37    
38     HOLO *hdlist[HDMAX+1]; /* holodeck pointers (NULL term.) */
39    
40 gregl 3.16 static struct fraglist {
41 gregl 3.1 short nlinks; /* number of holodeck sections using us */
42 gregl 3.13 short writerr; /* write error encountered */
43     int nfrags; /* number of known fragments */
44 gregl 3.4 BEAMI *fi; /* fragments, descending file position */
45 gregl 3.1 long flen; /* last known file length */
46 gregl 3.16 } *hdfragl; /* fragment lists, indexed by file descriptor */
47 gregl 3.1
48 gregl 3.16 static int nhdfragls; /* size of hdfragl array */
49 gregl 3.1
50 gregl 3.4
51 gwlarson 3.26 char *
52     hdrealloc(ptr, siz, rout) /* (re)allocate memory, retry then error */
53     char *ptr;
54     unsigned siz;
55     char *rout;
56     {
57     register char *newp;
58     /* call malloc/realloc */
59     if (ptr == NULL) newp = (char *)malloc(siz);
60     else newp = (char *)realloc(ptr, siz);
61     /* check success */
62     if (newp == NULL && rout != NULL) {
63     hdfreecache(25, NULL); /* free some memory */
64     errno = 0; /* retry */
65     newp = hdrealloc(ptr, siz, NULL);
66     if (newp == NULL) { /* give up and report error */
67     sprintf(errmsg, "out of memory in %s", rout);
68     error(SYSTEM, errmsg);
69     }
70     }
71     return(newp);
72     }
73    
74    
75 gregl 3.1 hdattach(fd) /* start tracking file fragments for some section */
76     register int fd;
77     {
78 gregl 3.16 if (fd >= nhdfragls) {
79 gwlarson 3.26 hdfragl = (struct fraglist *)hdrealloc((char *)hdfragl,
80     (fd+1)*sizeof(struct fraglist), "hdattach");
81 gregl 3.16 bzero((char *)(hdfragl+nhdfragls),
82     (fd+1-nhdfragls)*sizeof(struct fraglist));
83     nhdfragls = fd+1;
84 gregl 3.1 }
85 gregl 3.16 hdfragl[fd].nlinks++;
86     hdfragl[fd].flen = lseek(fd, 0L, 2); /* get file length */
87 gregl 3.1 }
88    
89    
90     /* Do we need a routine to locate file fragments given known occupants? */
91    
92    
93     hdrelease(fd) /* stop tracking file fragments for some section */
94     register int fd;
95     {
96 gregl 3.16 if (fd < 0 | fd >= nhdfragls || !hdfragl[fd].nlinks)
97 gregl 3.1 return;
98 gregl 3.16 if (!--hdfragl[fd].nlinks && hdfragl[fd].nfrags) {
99     free((char *)hdfragl[fd].fi);
100     hdfragl[fd].fi = NULL;
101     hdfragl[fd].nfrags = 0;
102 gregl 3.1 }
103     }
104    
105    
106 gregl 3.6 markdirty(hp) /* mark holodeck section directory dirty */
107     register HOLO *hp;
108     {
109     static BEAMI smudge = {0, -1};
110    
111     if (hp->dirty) /* already marked? */
112     return;
113     hp->dirty = 1;
114     if (lseek(hp->fd, biglob(hp)->fo+(nbeams(hp)-1)*sizeof(BEAMI), 0) < 0
115     || write(hp->fd, (char *)&smudge,
116     sizeof(BEAMI)) != sizeof(BEAMI))
117     error(SYSTEM, "seek/write error in markdirty");
118     }
119    
120    
121 gregl 3.1 HOLO *
122     hdinit(fd, hproto) /* initialize a holodeck section in a file */
123     int fd; /* corresponding file descriptor */
124     HDGRID *hproto; /* holodeck section grid */
125     {
126 gwlarson 3.22 long rtrunc;
127 gregl 3.1 long fpos;
128     register HOLO *hp;
129     register int n;
130     /* prepare for system errors */
131     errno = 0;
132     if ((fpos = lseek(fd, 0L, 1)) < 0)
133     error(SYSTEM, "cannot determine holodeck file position");
134     if (hproto == NULL) { /* assume we're loading it */
135     HDGRID hpr;
136     /* load header */
137     if (read(fd, (char *)&hpr, sizeof(HDGRID)) != sizeof(HDGRID))
138     error(SYSTEM, "cannot load holodeck header");
139     /* allocate grid */
140     if ((hp = hdalloc(&hpr)) == NULL)
141     goto memerr;
142     /* load beam directory */
143     n = nbeams(hp)*sizeof(BEAMI);
144     if (read(fd, (char *)(hp->bi+1), n) != n)
145     error(SYSTEM, "failure loading holodeck directory");
146 gregl 3.6 /* check that it's clean */
147     if (hp->bi[nbeams(hp)].fo < 0)
148 gregl 3.20 error(WARNING, "dirty holodeck section");
149 gregl 3.1 } else { /* assume we're creating it */
150     if ((hp = hdalloc(hproto)) == NULL)
151     goto memerr;
152     /* write header and skeleton */
153     n = nbeams(hp)*sizeof(BEAMI);
154     if (write(fd, (char *)hproto, sizeof(HDGRID)) !=
155     sizeof(HDGRID) ||
156     write(fd, (char *)(hp->bi+1), n) != n)
157     error(SYSTEM, "cannot write header to holodeck file");
158     }
159     hp->fd = fd;
160     hp->dirty = 0;
161     biglob(hp)->fo = fpos + sizeof(HDGRID);
162 gregl 3.13 /* start tracking fragments */
163     hdattach(fd);
164     /* check rays on disk */
165     fpos = hdfilen(fd);
166 gwlarson 3.22 biglob(hp)->nrd = rtrunc = 0;
167 gregl 3.13 for (n = hproto == NULL ? nbeams(hp) : 0; n > 0; n--)
168     if (hp->bi[n].nrd)
169 gwlarson 3.27 if (hp->bi[n].fo+hp->bi[n].nrd*sizeof(RAYVAL) > fpos) {
170 gwlarson 3.22 rtrunc += hp->bi[n].nrd;
171     hp->bi[n].nrd = 0;
172     } else
173 gregl 3.13 biglob(hp)->nrd += hp->bi[n].nrd;
174 gwlarson 3.22 if (rtrunc) {
175     sprintf(errmsg, "truncated section, %ld rays lost (%.1f%%)",
176     rtrunc, 100.*rtrunc/(rtrunc+biglob(hp)->nrd));
177     error(WARNING, errmsg);
178     }
179 gregl 3.1 /* add to holodeck list */
180     for (n = 0; n < HDMAX; n++)
181     if (hdlist[n] == NULL) {
182     hdlist[n] = hp;
183     break;
184     }
185     /* all done */
186     return(hp);
187     memerr:
188     error(SYSTEM, "cannot allocate holodeck grid");
189     }
190    
191    
192     int
193 gregl 3.12 hdsync(hp, all) /* update beams and directory on disk */
194 gregl 3.1 register HOLO *hp;
195 gregl 3.12 int all;
196 gregl 3.1 {
197     register int j, n;
198    
199 gregl 3.12 if (hp == NULL) { /* do all holodecks */
200 gregl 3.1 n = 0;
201     for (j = 0; hdlist[j] != NULL; j++)
202 gregl 3.12 n += hdsync(hdlist[j], all);
203 gregl 3.1 return(n);
204     }
205 gregl 3.12 /* sync the beams */
206 gregl 3.15 for (j = (all ? nbeams(hp) : 0); j > 0; j--)
207 gregl 3.12 if (hp->bl[j] != NULL)
208     hdsyncbeam(hp, j);
209 gregl 3.13 if (!hp->dirty) /* directory clean? */
210 gregl 3.1 return(0);
211 gregl 3.3 errno = 0;
212 gregl 3.1 if (lseek(hp->fd, biglob(hp)->fo, 0) < 0)
213     error(SYSTEM, "cannot seek on holodeck file");
214     n = nbeams(hp)*sizeof(BEAMI);
215     if (write(hp->fd, (char *)(hp->bi+1), n) != n)
216     error(SYSTEM, "cannot update holodeck section directory");
217     hp->dirty = 0;
218     return(1);
219     }
220    
221    
222 gregl 3.14 unsigned
223 gregl 3.1 hdmemuse(all) /* return memory usage (in bytes) */
224     int all; /* include overhead (painful) */
225     {
226     long total = 0;
227     register int i, j;
228    
229     for (j = 0; hdlist[j] != NULL; j++) {
230     total += blglob(hdlist[j])->nrm * sizeof(RAYVAL);
231     if (all) {
232     total += sizeof(HOLO) + sizeof(BEAM *) +
233     nbeams(hdlist[j]) *
234     (sizeof(BEAM *)+sizeof(BEAMI));
235     for (i = nbeams(hdlist[j]); i > 0; i--)
236     if (hdlist[j]->bl[i] != NULL)
237     total += sizeof(BEAM);
238     }
239     }
240     if (all)
241 gregl 3.16 for (j = 0; j < nhdfragls; j++) {
242     total += sizeof(struct fraglist);
243     if (hdfragl[j].nfrags)
244 gregl 3.4 total += FRAGBLK*sizeof(BEAMI) *
245 gregl 3.16 ((hdfragl[j].nfrags-1)/FRAGBLK + 1) ;
246 gregl 3.4 }
247 gregl 3.1 return(total);
248 gregl 3.8 }
249    
250    
251     long
252     hdfilen(fd) /* return file length for fd */
253     int fd;
254     {
255     long fpos, flen;
256    
257     if (fd < 0)
258     return(-1);
259 gregl 3.16 if (fd >= nhdfragls || !hdfragl[fd].nlinks) {
260 gregl 3.8 if ((fpos = lseek(fd, 0L, 1)) < 0)
261     return(-1);
262     flen = lseek(fd, 0L, 2);
263     lseek(fd, fpos, 0);
264     return(flen);
265     }
266 gregl 3.16 return(hdfragl[fd].flen);
267 gregl 3.1 }
268    
269    
270     long
271     hdfiluse(fd, all) /* compute file usage (in bytes) */
272     int fd; /* open file descriptor to check */
273     int all; /* include overhead and unflushed data */
274     {
275     long total = 0;
276     register int i, j;
277    
278     for (j = 0; hdlist[j] != NULL; j++) {
279     if (hdlist[j]->fd != fd)
280     continue;
281     total += biglob(hdlist[j])->nrd * sizeof(RAYVAL);
282     if (all) {
283     for (i = nbeams(hdlist[j]); i > 0; i--)
284     if (hdlist[j]->bl[i] != NULL)
285     total += sizeof(RAYVAL) *
286     (hdlist[j]->bl[i]->nrm -
287     hdlist[j]->bi[i].nrd);
288     total += sizeof(HDGRID) +
289     nbeams(hdlist[j])*sizeof(BEAMI);
290     }
291     }
292     return(total); /* does not include fragments */
293     }
294    
295    
296     RAYVAL *
297     hdnewrays(hp, i, nr) /* allocate space for add'l rays and return pointer */
298     register HOLO *hp;
299     register int i;
300     int nr; /* number of new rays desired */
301     {
302     RAYVAL *p;
303     int n;
304    
305     if (nr <= 0)
306     return(NULL);
307     if (i < 1 | i > nbeams(hp))
308     error(CONSISTENCY, "bad beam index given to hdnewrays");
309     if (hp->bl[i] != NULL)
310     hp->bl[i]->tick = hdclock; /* preempt swap */
311     if (hdcachesize > 0 && hdmemuse(0) >= hdcachesize)
312     hdfreecache(PCTFREE, NULL); /* free some space */
313     if (hp->bl[i] == NULL) { /* allocate (and load) */
314     n = hp->bi[i].nrd + nr;
315 gwlarson 3.26 hp->bl[i] = (BEAM *)hdrealloc(NULL, hdbsiz(n), "hdnewrays");
316 gregl 3.1 blglob(hp)->nrm += n;
317     if (n = hp->bl[i]->nrm = hp->bi[i].nrd) {
318 gwlarson 3.26 errno = 0;
319 gregl 3.1 if (lseek(hp->fd, hp->bi[i].fo, 0) < 0)
320     error(SYSTEM, "seek error on holodeck file");
321     n *= sizeof(RAYVAL);
322     if (read(hp->fd, (char *)hdbray(hp->bl[i]), n) != n)
323     error(SYSTEM,
324     "error reading beam from holodeck file");
325     }
326     } else { /* just grow in memory */
327 gwlarson 3.26 hp->bl[i] = (BEAM *)hdrealloc((char *)hp->bl[i],
328     hdbsiz(hp->bl[i]->nrm + nr), "hdnewrays");
329 gregl 3.1 blglob(hp)->nrm += nr;
330     }
331     p = hdbray(hp->bl[i]) + hp->bl[i]->nrm;
332     hp->bl[i]->nrm += nr; /* update in-core structure */
333     bzero((char *)p, nr*sizeof(RAYVAL));
334 gwlarson 3.25 blglob(hp)->tick = hp->bl[i]->tick = hdclock++; /* update LRU clock */
335 gregl 3.1 return(p); /* point to new rays */
336     }
337    
338    
339     BEAM *
340     hdgetbeam(hp, i) /* get beam (from file if necessary) */
341     register HOLO *hp;
342     register int i;
343     {
344     register int n;
345    
346     if (i < 1 | i > nbeams(hp))
347     error(CONSISTENCY, "bad beam index given to hdgetbeam");
348     if (hp->bl[i] == NULL) { /* load from disk */
349     if (!(n = hp->bi[i].nrd))
350     return(NULL);
351     if (hdcachesize > 0 && hdmemuse(0) >= hdcachesize)
352     hdfreecache(PCTFREE, NULL); /* get free space */
353 gwlarson 3.26 hp->bl[i] = (BEAM *)hdrealloc(NULL, hdbsiz(n), "hdgetbeam");
354     blglob(hp)->nrm += hp->bl[i]->nrm = n;
355 gregl 3.1 errno = 0;
356     if (lseek(hp->fd, hp->bi[i].fo, 0) < 0)
357     error(SYSTEM, "seek error on holodeck file");
358     n *= sizeof(RAYVAL);
359     if (read(hp->fd, (char *)hdbray(hp->bl[i]), n) != n)
360     error(SYSTEM, "error reading beam from holodeck file");
361     }
362 gwlarson 3.25 blglob(hp)->tick = hp->bl[i]->tick = hdclock++; /* update LRU clock */
363 gregl 3.1 return(hp->bl[i]);
364     }
365    
366    
367     int
368 gregl 3.17 hdfilord(hb1, hb2) /* order beams for quick loading */
369 gregl 3.14 register HDBEAMI *hb1, *hb2;
370     {
371 gregl 3.17 register long c;
372     /* residents go first */
373     if (hb2->h->bl[hb2->b] != NULL)
374     return(hb1->h->bl[hb1->b] == NULL);
375     if (hb1->h->bl[hb1->b] != NULL)
376     return(-1);
377     /* otherwise sort by file descriptor */
378 gregl 3.14 if ((c = hb1->h->fd - hb2->h->fd))
379     return(c);
380     /* then by position in file */
381 gregl 3.17 c = hb1->h->bi[hb1->b].fo - hb2->h->bi[hb2->b].fo;
382     return(c > 0 ? 1 : c < 0 ? -1 : 0);
383 gregl 3.14 }
384    
385    
386     hdloadbeams(hb, n, bf) /* load a list of beams in optimal order */
387     register HDBEAMI *hb; /* list gets sorted by hdfilord() */
388     int n; /* list length */
389     int (*bf)(); /* callback function (optional) */
390     {
391     unsigned origcachesize, memuse;
392 gwlarson 3.23 int bytesloaded, needbytes, bytes2free;
393 gregl 3.14 register BEAM *bp;
394     register int i;
395     /* precheck consistency */
396 gwlarson 3.25 if (n <= 0) return;
397 gregl 3.14 for (i = n; i--; )
398     if (hb[i].h == NULL || hb[i].b < 1 | hb[i].b > nbeams(hb[i].h))
399     error(CONSISTENCY, "bad beam in hdloadbeams");
400     /* sort list for optimal access */
401     qsort((char *)hb, n, sizeof(HDBEAMI), hdfilord);
402 gregl 3.17 bytesloaded = 0; /* run through loaded beams */
403     for ( ; n && (bp = hb->h->bl[hb->b]) != NULL; n--, hb++) {
404 gwlarson 3.23 bp->tick = hdclock; /* preempt swap */
405 gregl 3.17 bytesloaded += bp->nrm;
406     if (bf != NULL)
407 gwlarson 3.23 (*bf)(bp, hb);
408 gregl 3.17 }
409     bytesloaded *= sizeof(RAYVAL);
410 gregl 3.15 if ((origcachesize = hdcachesize) > 0) {
411 gregl 3.17 needbytes = 0; /* figure out memory needs */
412 gregl 3.15 for (i = n; i--; )
413 gregl 3.17 needbytes += hb[i].h->bi[hb[i].b].nrd;
414 gregl 3.15 needbytes *= sizeof(RAYVAL);
415     do { /* free enough memory */
416     memuse = hdmemuse(0);
417 gregl 3.17 bytes2free = needbytes - (int)(hdcachesize-memuse);
418     if (bytes2free > (int)(memuse - bytesloaded))
419 gregl 3.15 bytes2free = memuse - bytesloaded;
420     } while (bytes2free > 0 &&
421     hdfreecache(100*bytes2free/memuse, NULL) < 0);
422 gregl 3.17 hdcachesize = 0; /* load beams w/o swap */
423 gregl 3.15 }
424 gregl 3.14 for (i = 0; i < n; i++)
425     if ((bp = hdgetbeam(hb[i].h, hb[i].b)) != NULL && bf != NULL)
426 gwlarson 3.23 (*bf)(bp, hb+i);
427 gregl 3.14 hdcachesize = origcachesize; /* resume dynamic swapping */
428     }
429    
430    
431 gregl 3.19 hdfreefrag(fd, bi) /* free a file fragment */
432     int fd;
433     register BEAMI *bi;
434     {
435     register struct fraglist *f;
436     register int j, k;
437    
438     if (bi->nrd == 0)
439     return;
440     #ifdef DEBUG
441     if (fd < 0 | fd >= nhdfragls || !hdfragl[fd].nlinks)
442     error(CONSISTENCY, "bad file descriptor in hdfreefrag");
443     #endif
444     f = &hdfragl[fd];
445     if (f->nfrags % FRAGBLK == 0) { /* delete empty remnants */
446     for (j = k = 0; k < f->nfrags; j++, k++) {
447     while (f->fi[k].nrd == 0)
448     if (++k >= f->nfrags)
449     goto endloop;
450     if (k > j)
451     copystruct(f->fi+j, f->fi+k);
452     }
453     endloop:
454     f->nfrags = j;
455     }
456     j = f->nfrags++; /* allocate a slot in free list */
457     #if MAXFRAG
458     if (j >= MAXFRAG-1)
459     f->nfrags--;
460     #endif
461     if (j % FRAGBLK == 0) { /* more free list space */
462 gwlarson 3.26 register BEAMI *newp;
463 gregl 3.19 if (f->fi == NULL)
464 gwlarson 3.26 newp = (BEAMI *)malloc((j+FRAGBLK)*sizeof(BEAMI));
465 gregl 3.19 else
466 gwlarson 3.26 newp = (BEAMI *)realloc((char *)f->fi,
467 gregl 3.19 (j+FRAGBLK)*sizeof(BEAMI));
468 gwlarson 3.26 if (newp == NULL) {
469     f->nfrags--; /* graceful failure */
470     return;
471     }
472     f->fi = newp;
473 gregl 3.19 }
474     for ( ; ; j--) { /* insert in descending list */
475     if (!j || bi->fo < f->fi[j-1].fo) {
476     f->fi[j].fo = bi->fo;
477     f->fi[j].nrd = bi->nrd;
478     break;
479     }
480     copystruct(f->fi+j, f->fi+(j-1));
481     }
482     /* coalesce adjacent fragments */
483     /* successors never empty */
484     if (j && f->fi[j-1].fo == f->fi[j].fo + f->fi[j].nrd*sizeof(RAYVAL)) {
485     f->fi[j].nrd += f->fi[j-1].nrd;
486     f->fi[j-1].nrd = 0;
487     }
488     for (k = j+1; k < f->nfrags; k++) /* get non-empty predecessor */
489     if (f->fi[k].nrd) {
490     if (f->fi[j].fo == f->fi[k].fo +
491     f->fi[k].nrd*sizeof(RAYVAL)) {
492     f->fi[k].nrd += f->fi[j].nrd;
493     f->fi[j].nrd = 0;
494     }
495     break;
496     }
497     }
498    
499    
500     long
501     hdallocfrag(fd, nrays) /* allocate a file fragment */
502     int fd;
503     unsigned int4 nrays;
504     {
505     register struct fraglist *f;
506     register int j, k;
507     long nfo;
508    
509     if (nrays == 0)
510     return(-1L);
511     #ifdef DEBUG
512     if (fd < 0 | fd >= nhdfragls || !hdfragl[fd].nlinks)
513     error(CONSISTENCY, "bad file descriptor in hdallocfrag");
514     #endif
515     f = &hdfragl[fd];
516     k = -1; /* find closest-sized fragment */
517     for (j = f->nfrags; j-- > 0; )
518     if (f->fi[j].nrd >= nrays &&
519     (k < 0 || f->fi[j].nrd < f->fi[k].nrd))
520     if (f->fi[k=j].nrd == nrays)
521     break;
522     if (k < 0) { /* no fragment -- extend file */
523     nfo = f->flen;
524     f->flen += nrays*sizeof(RAYVAL);
525     } else { /* else use fragment */
526     nfo = f->fi[k].fo;
527     f->fi[k].fo += nrays*sizeof(RAYVAL);
528     f->fi[k].nrd -= nrays;
529     }
530     return(nfo);
531     }
532    
533    
534 gregl 3.14 int
535 gregl 3.12 hdsyncbeam(hp, i) /* sync beam in memory with beam on disk */
536 gregl 3.1 register HOLO *hp;
537     register int i;
538     {
539 gregl 3.19 unsigned int4 nrays;
540     unsigned int n;
541 gregl 3.11 long nfo;
542 gregl 3.13 /* check file status */
543 gregl 3.16 if (hdfragl[hp->fd].writerr)
544 gregl 3.13 return(-1);
545 gregl 3.12 #ifdef DEBUG
546     if (i < 1 | i > nbeams(hp))
547     error(CONSISTENCY, "bad beam index in hdsyncbeam");
548     #endif
549 gregl 3.11 /* is current fragment OK? */
550 gregl 3.12 if (hp->bl[i] == NULL || (nrays = hp->bl[i]->nrm) == hp->bi[i].nrd)
551 gregl 3.1 return(0);
552 gregl 3.19 if (hp->bi[i].nrd) /* relinquish old fragment */
553     hdfreefrag(hp->fd, &hp->bi[i]);
554     if (nrays) { /* get and write new fragment */
555     nfo = hdallocfrag(hp->fd, nrays);
556 gregl 3.11 errno = 0;
557     if (lseek(hp->fd, nfo, 0) < 0)
558     error(SYSTEM, "cannot seek on holodeck file");
559     n = hp->bl[i]->nrm * sizeof(RAYVAL);
560     if (write(hp->fd, (char *)hdbray(hp->bl[i]), n) != n) {
561 gregl 3.16 hdfragl[hp->fd].writerr++;
562 gregl 3.18 hdsync(NULL, 0); /* sync directories */
563 gregl 3.12 error(SYSTEM, "write error in hdsyncbeam");
564 gregl 3.11 }
565 gregl 3.19 hp->bi[i].fo = nfo;
566     } else
567     hp->bi[i].fo = 0L;
568 gregl 3.1 biglob(hp)->nrd += nrays - hp->bi[i].nrd;
569     hp->bi[i].nrd = nrays;
570 gregl 3.19 markdirty(hp); /* section directory now out of date */
571 gregl 3.1 return(1);
572     }
573    
574    
575     int
576     hdfreebeam(hp, i) /* free beam, writing if dirty */
577     register HOLO *hp;
578     register int i;
579     {
580 gregl 3.11 int nchanged;
581 gregl 3.1
582     if (hp == NULL) { /* clear all holodecks */
583     nchanged = 0;
584     for (i = 0; hdlist[i] != NULL; i++)
585     nchanged += hdfreebeam(hdlist[i], 0);
586     return(nchanged);
587     }
588 gregl 3.16 if (hdfragl[hp->fd].writerr) /* check for file error */
589 gregl 3.13 return(0);
590 gregl 3.1 if (i == 0) { /* clear entire holodeck */
591     nchanged = 0;
592 gregl 3.10 for (i = nbeams(hp); i > 0; i--)
593     if (hp->bl[i] != NULL)
594     nchanged += hdfreebeam(hp, i);
595 gregl 3.1 return(nchanged);
596     }
597 gregl 3.12 #ifdef DEBUG
598 gregl 3.1 if (i < 1 | i > nbeams(hp))
599     error(CONSISTENCY, "bad beam index to hdfreebeam");
600 gregl 3.12 #endif
601 gregl 3.1 if (hp->bl[i] == NULL)
602     return(0);
603     /* check for additions */
604     nchanged = hp->bl[i]->nrm - hp->bi[i].nrd;
605 gregl 3.11 if (nchanged)
606 gregl 3.12 hdsyncbeam(hp, i); /* write new fragment */
607 gregl 3.1 blglob(hp)->nrm -= hp->bl[i]->nrm;
608     free((char *)hp->bl[i]); /* free memory */
609     hp->bl[i] = NULL;
610     return(nchanged);
611     }
612    
613    
614 gregl 3.10 int
615     hdkillbeam(hp, i) /* delete beam from holodeck */
616     register HOLO *hp;
617     register int i;
618     {
619     static BEAM emptybeam;
620 gregl 3.11 int nchanged;
621 gregl 3.10
622     if (hp == NULL) { /* clobber all holodecks */
623     nchanged = 0;
624     for (i = 0; hdlist[i] != NULL; i++)
625     nchanged += hdkillbeam(hdlist[i], 0);
626     return(nchanged);
627     }
628     if (i == 0) { /* clobber entire holodeck */
629     nchanged = 0;
630     for (i = nbeams(hp); i > 0; i--)
631     if (hp->bi[i].nrd > 0 || hp->bl[i] != NULL)
632     nchanged += hdkillbeam(hp, i);
633     #ifdef DEBUG
634     if (biglob(hp)->nrd != 0 | blglob(hp)->nrm != 0)
635     error(CONSISTENCY, "bad beam count in hdkillbeam");
636     #endif
637     return(nchanged);
638     }
639 gregl 3.12 #ifdef DEBUG
640 gregl 3.10 if (i < 1 | i > nbeams(hp))
641     error(CONSISTENCY, "bad beam index to hdkillbeam");
642 gregl 3.12 #endif
643 gregl 3.10 if (hp->bl[i] != NULL) { /* free memory */
644     blglob(hp)->nrm -= nchanged = hp->bl[i]->nrm;
645     free((char *)hp->bl[i]);
646     } else
647     nchanged = hp->bi[i].nrd;
648     if (hp->bi[i].nrd) { /* free file fragment */
649     hp->bl[i] = &emptybeam;
650 gregl 3.12 hdsyncbeam(hp, i);
651 gregl 3.10 }
652     hp->bl[i] = NULL;
653     return(nchanged);
654     }
655    
656    
657 gregl 3.14 int
658     hdlrulist(hb, nents, n, hp) /* add beams from holodeck to LRU list */
659     register HDBEAMI *hb; /* beam list */
660     int nents; /* current list length */
661     int n; /* maximum list length */
662 gregl 3.1 register HOLO *hp; /* section we're adding from */
663     {
664     register int i, j;
665     /* insert each beam from hp */
666 gregl 3.21 for (i = 1; i <= nbeams(hp); i++) {
667 gregl 3.1 if (hp->bl[i] == NULL) /* check if loaded */
668     continue;
669 gregl 3.14 #if 0
670     if (hp->bl[i]->tick == hdclock) /* preempt swap? */
671     continue;
672     #endif
673     if ((j = ++nents) >= n) /* grow list if we can */
674 gregl 3.1 nents--;
675     for ( ; ; ) { /* bubble into place */
676     if (!--j || hp->bl[i]->tick >=
677 gregl 3.14 hb[j-1].h->bl[hb[j-1].b]->tick) {
678     hb[j].h = hp;
679     hb[j].b = i;
680 gregl 3.1 break;
681     }
682 gregl 3.14 copystruct(hb+j, hb+(j-1));
683 gregl 3.1 }
684     }
685 gregl 3.14 return(nents); /* return new list length */
686 gregl 3.1 }
687    
688    
689 gregl 3.14 int
690 gregl 3.1 hdfreecache(pct, honly) /* free up cache space, writing changes */
691     int pct; /* maximum percentage to free */
692     register HOLO *honly; /* NULL means check all */
693     {
694 gregl 3.14 HDBEAMI hb[FREEBEAMS];
695 gregl 3.1 int freetarget;
696 gregl 3.14 int n;
697 gregl 3.1 register int i;
698 gwlarson 3.25 #ifdef DEBUG
699     unsigned membefore;
700    
701     membefore = hdmemuse(0);
702     #endif
703 gregl 3.1 /* compute free target */
704     freetarget = (honly != NULL) ? blglob(honly)->nrm :
705     hdmemuse(0)/sizeof(RAYVAL) ;
706     freetarget = freetarget*pct/100;
707 gregl 3.14 if (freetarget <= 0)
708     return(0);
709 gregl 3.1 /* find least recently used */
710 gregl 3.14 n = 0;
711 gregl 3.1 if (honly != NULL)
712 gregl 3.14 n = hdlrulist(hb, n, FREEBEAMS, honly);
713 gregl 3.1 else
714     for (i = 0; hdlist[i] != NULL; i++)
715 gregl 3.14 n = hdlrulist(hb, n, FREEBEAMS, hdlist[i]);
716 gregl 3.1 /* free LRU beams */
717 gregl 3.14 for (i = 0; i < n; i++) {
718     hdfreebeam(hb[i].h, hb[i].b);
719     if ((freetarget -= hb[i].h->bi[hb[i].b].nrd) <= 0)
720 gregl 3.1 break;
721     }
722 gregl 3.12 hdsync(honly, 0); /* synchronize directories as necessary */
723 gwlarson 3.25 #ifdef DEBUG
724     sprintf(errmsg,
725     "%dK before, %dK after hdfreecache (%dK total), %d rays short\n",
726     membefore>>10, hdmemuse(0)>>10, hdmemuse(1)>>10, freetarget);
727     wputs(errmsg);
728     #endif
729 gregl 3.14 return(-freetarget); /* return how far past goal we went */
730 gregl 3.1 }
731    
732    
733     hddone(hp) /* clean up holodeck section and free */
734     register HOLO *hp; /* NULL means clean up all */
735     {
736     register int i;
737    
738     if (hp == NULL) { /* NULL means clean up everything */
739     while (hdlist[0] != NULL)
740     hddone(hdlist[0]);
741 gwlarson 3.24 free((char *)hdfragl);
742     hdfragl = NULL; nhdfragls = 0;
743 gregl 3.1 return;
744     }
745     /* flush all data and free memory */
746 gwlarson 3.27 hdfreebeam(hp, 0);
747     hdsync(hp, 0);
748 gregl 3.1 /* release fragment resources */
749     hdrelease(hp->fd);
750     /* remove hp from active list */
751     for (i = 0; hdlist[i] != NULL; i++)
752     if (hdlist[i] == hp) {
753     while ((hdlist[i] = hdlist[i+1]) != NULL)
754     i++;
755     break;
756     }
757     free((char *)hp->bl); /* free beam list */
758     free((char *)hp); /* free holodeck struct */
759     }