ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/holofile.c
Revision: 3.3
Committed: Mon Nov 3 13:40:22 1997 UTC (26 years, 5 months ago) by gregl
Content type: text/plain
Branch: MAIN
Changes since 3.2: +11 -7 lines
Log Message:
bug fixes in hdgetbi()

File Contents

# User Rev Content
1 gregl 3.1 /* Copyright (c) 1997 Silicon Graphics, Inc. */
2    
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     #define FREEBEAMS 1024 /* maximum beams to free at a time */
20     #endif
21     #ifndef PCTFREE
22     #define PCTFREE 12 /* maximum fraction to free (%) */
23     #endif
24     #ifndef FFDMAX
25     #define FFDMAX 64 /* max. file descriptor for tracking */
26     #endif
27     #ifndef MAXFRAG
28     #define MAXFRAG 2048 /* maximum fragments tracked in each file */
29     #endif
30    
31     int hdcachesize = CACHESIZE*1024*1024; /* target cache size (bytes) */
32     unsigned long hdclock; /* clock value */
33    
34     HOLO *hdlist[HDMAX+1]; /* holodeck pointers (NULL term.) */
35    
36     static struct fragment {
37     short nlinks; /* number of holodeck sections using us */
38     short nfrags; /* number of known fragments */
39     BEAMI fi[MAXFRAG]; /* fragments, descending file position */
40     long flen; /* last known file length */
41     } *hdfrag[FFDMAX]; /* fragment lists, indexed by file descriptor */
42    
43    
44     hdattach(fd) /* start tracking file fragments for some section */
45     register int fd;
46     {
47     if (fd >= FFDMAX)
48     return; /* descriptor out of range */
49     if (hdfrag[fd] == NULL) {
50     if ((hdfrag[fd] = (struct fragment *)
51     malloc(sizeof(struct fragment))) == NULL)
52     return; /* should flag error? */
53     hdfrag[fd]->nlinks = 0;
54     hdfrag[fd]->nfrags = 0;
55     }
56     hdfrag[fd]->nlinks++;
57     hdfrag[fd]->flen = lseek(fd, 0L, 2); /* get file length */
58     }
59    
60    
61     /* Do we need a routine to locate file fragments given known occupants? */
62    
63    
64     hdrelease(fd) /* stop tracking file fragments for some section */
65     register int fd;
66     {
67     if (fd >= FFDMAX || hdfrag[fd] == NULL)
68     return;
69     if (!--hdfrag[fd]->nlinks) {
70     free((char *)hdfrag[fd]);
71     hdfrag[fd] = NULL;
72     }
73     }
74    
75    
76     HOLO *
77     hdinit(fd, hproto) /* initialize a holodeck section in a file */
78     int fd; /* corresponding file descriptor */
79     HDGRID *hproto; /* holodeck section grid */
80     {
81     long fpos;
82     register HOLO *hp;
83     register int n;
84     /* prepare for system errors */
85     errno = 0;
86     if ((fpos = lseek(fd, 0L, 1)) < 0)
87     error(SYSTEM, "cannot determine holodeck file position");
88     if (hproto == NULL) { /* assume we're loading it */
89     HDGRID hpr;
90     /* load header */
91     if (read(fd, (char *)&hpr, sizeof(HDGRID)) != sizeof(HDGRID))
92     error(SYSTEM, "cannot load holodeck header");
93     /* allocate grid */
94     if ((hp = hdalloc(&hpr)) == NULL)
95     goto memerr;
96     /* load beam directory */
97     n = nbeams(hp)*sizeof(BEAMI);
98     if (read(fd, (char *)(hp->bi+1), n) != n)
99     error(SYSTEM, "failure loading holodeck directory");
100     } else { /* assume we're creating it */
101     if ((hp = hdalloc(hproto)) == NULL)
102     goto memerr;
103     /* write header and skeleton */
104     n = nbeams(hp)*sizeof(BEAMI);
105     if (write(fd, (char *)hproto, sizeof(HDGRID)) !=
106     sizeof(HDGRID) ||
107     write(fd, (char *)(hp->bi+1), n) != n)
108     error(SYSTEM, "cannot write header to holodeck file");
109     }
110     hp->fd = fd;
111     hp->dirty = 0;
112     biglob(hp)->fo = fpos + sizeof(HDGRID);
113     biglob(hp)->nrd = 0; /* count rays on disk */
114     for (n = nbeams(hp); n > 0; n--)
115     biglob(hp)->nrd += hp->bi[n].nrd;
116     /* add to holodeck list */
117     for (n = 0; n < HDMAX; n++)
118     if (hdlist[n] == NULL) {
119     hdlist[n] = hp;
120     break;
121     }
122     /* start tracking fragments (last) */
123     hdattach(fd);
124     /* all done */
125     return(hp);
126     memerr:
127     error(SYSTEM, "cannot allocate holodeck grid");
128     }
129    
130    
131     int
132     hdsync(hp) /* update directory on disk if necessary */
133     register HOLO *hp;
134     {
135     register int j, n;
136    
137     if (hp == NULL) { /* do all */
138     n = 0;
139     for (j = 0; hdlist[j] != NULL; j++)
140     n += hdsync(hdlist[j]);
141     return(n);
142     }
143     if (!hp->dirty) /* check first */
144     return(0);
145 gregl 3.3 errno = 0;
146 gregl 3.1 if (lseek(hp->fd, biglob(hp)->fo, 0) < 0)
147     error(SYSTEM, "cannot seek on holodeck file");
148     n = nbeams(hp)*sizeof(BEAMI);
149     if (write(hp->fd, (char *)(hp->bi+1), n) != n)
150     error(SYSTEM, "cannot update holodeck section directory");
151     hp->dirty = 0;
152     return(1);
153     }
154    
155    
156     long
157     hdmemuse(all) /* return memory usage (in bytes) */
158     int all; /* include overhead (painful) */
159     {
160     long total = 0;
161     register int i, j;
162    
163     for (j = 0; hdlist[j] != NULL; j++) {
164     total += blglob(hdlist[j])->nrm * sizeof(RAYVAL);
165     if (all) {
166     total += sizeof(HOLO) + sizeof(BEAM *) +
167     nbeams(hdlist[j]) *
168     (sizeof(BEAM *)+sizeof(BEAMI));
169     for (i = nbeams(hdlist[j]); i > 0; i--)
170     if (hdlist[j]->bl[i] != NULL)
171     total += sizeof(BEAM);
172     }
173     }
174     if (all)
175     for (j = 0; j < FFDMAX; j++)
176     if (hdfrag[j] != NULL)
177     total += sizeof(struct fragment);
178     return(total);
179     }
180    
181    
182     long
183     hdfiluse(fd, all) /* compute file usage (in bytes) */
184     int fd; /* open file descriptor to check */
185     int all; /* include overhead and unflushed data */
186     {
187     long total = 0;
188     register int i, j;
189    
190     for (j = 0; hdlist[j] != NULL; j++) {
191     if (hdlist[j]->fd != fd)
192     continue;
193     total += biglob(hdlist[j])->nrd * sizeof(RAYVAL);
194     if (all) {
195     for (i = nbeams(hdlist[j]); i > 0; i--)
196     if (hdlist[j]->bl[i] != NULL)
197     total += sizeof(RAYVAL) *
198     (hdlist[j]->bl[i]->nrm -
199     hdlist[j]->bi[i].nrd);
200     total += sizeof(HDGRID) +
201     nbeams(hdlist[j])*sizeof(BEAMI);
202     }
203     }
204     return(total); /* does not include fragments */
205     }
206    
207    
208     RAYVAL *
209     hdnewrays(hp, i, nr) /* allocate space for add'l rays and return pointer */
210     register HOLO *hp;
211     register int i;
212     int nr; /* number of new rays desired */
213     {
214     RAYVAL *p;
215     int n;
216    
217     if (nr <= 0)
218     return(NULL);
219     if (i < 1 | i > nbeams(hp))
220     error(CONSISTENCY, "bad beam index given to hdnewrays");
221     if (hp->bl[i] != NULL)
222     hp->bl[i]->tick = hdclock; /* preempt swap */
223     if (hdcachesize > 0 && hdmemuse(0) >= hdcachesize)
224     hdfreecache(PCTFREE, NULL); /* free some space */
225 gregl 3.3 errno = 0;
226 gregl 3.1 if (hp->bl[i] == NULL) { /* allocate (and load) */
227     n = hp->bi[i].nrd + nr;
228     if ((hp->bl[i] = (BEAM *)malloc(hdbsiz(n))) == NULL)
229     goto memerr;
230     blglob(hp)->nrm += n;
231     if (n = hp->bl[i]->nrm = hp->bi[i].nrd) {
232     if (lseek(hp->fd, hp->bi[i].fo, 0) < 0)
233     error(SYSTEM, "seek error on holodeck file");
234     n *= sizeof(RAYVAL);
235     if (read(hp->fd, (char *)hdbray(hp->bl[i]), n) != n)
236     error(SYSTEM,
237     "error reading beam from holodeck file");
238     }
239     } else { /* just grow in memory */
240     hp->bl[i] = (BEAM *)realloc( (char *)hp->bl[i],
241     hdbsiz(hp->bl[i]->nrm + nr) );
242     if (hp->bl[i] == NULL)
243     goto memerr;
244     blglob(hp)->nrm += nr;
245     }
246     p = hdbray(hp->bl[i]) + hp->bl[i]->nrm;
247     hp->bl[i]->nrm += nr; /* update in-core structure */
248     bzero((char *)p, nr*sizeof(RAYVAL));
249     hp->bl[i]->tick = ++hdclock; /* update LRU clock */
250     blglob(hp)->tick = hdclock;
251     return(p); /* point to new rays */
252     memerr:
253     error(SYSTEM, "out of memory in hdnewrays");
254     }
255    
256    
257     BEAM *
258     hdgetbeam(hp, i) /* get beam (from file if necessary) */
259     register HOLO *hp;
260     register int i;
261     {
262     register int n;
263    
264     if (i < 1 | i > nbeams(hp))
265     error(CONSISTENCY, "bad beam index given to hdgetbeam");
266     if (hp->bl[i] == NULL) { /* load from disk */
267     if (!(n = hp->bi[i].nrd))
268     return(NULL);
269     if (hdcachesize > 0 && hdmemuse(0) >= hdcachesize)
270     hdfreecache(PCTFREE, NULL); /* get free space */
271     errno = 0;
272     if ((hp->bl[i] = (BEAM *)malloc(hdbsiz(n))) == NULL)
273     error(SYSTEM, "cannot allocate memory for beam");
274     blglob(hp)->nrm += hp->bl[i]->nrm = n;
275     if (lseek(hp->fd, hp->bi[i].fo, 0) < 0)
276     error(SYSTEM, "seek error on holodeck file");
277     n *= sizeof(RAYVAL);
278     if (read(hp->fd, (char *)hdbray(hp->bl[i]), n) != n)
279     error(SYSTEM, "error reading beam from holodeck file");
280     }
281     hp->bl[i]->tick = ++hdclock; /* update LRU clock */
282     blglob(hp)->tick = hdclock;
283     return(hp->bl[i]);
284     }
285    
286    
287     int
288     hdgetbi(hp, i) /* allocate a file fragment */
289     register HOLO *hp;
290     register int i;
291     {
292     int nrays = hp->bl[i]->nrm;
293    
294     if (hp->bi[i].nrd == nrays) /* current one will do? */
295     return(0);
296    
297     if (hp->fd >= FFDMAX || hdfrag[hp->fd] == NULL) /* untracked */
298     hp->bi[i].fo = lseek(hp->fd, 0L, 2);
299    
300     else if (hp->bi[i].fo + hp->bi[i].nrd*sizeof(RAYVAL) ==
301     hdfrag[hp->fd]->flen) /* EOF special case */
302     hdfrag[hp->fd]->flen = hp->bi[i].fo + nrays*sizeof(RAYVAL);
303    
304     else { /* general case */
305     register struct fragment *f = hdfrag[hp->fd];
306     register int j, k;
307     /* relinquish old fragment */
308 gregl 3.2 if (hp->bi[i].nrd) {
309     if ((j = ++f->nfrags) >= MAXFRAG)
310     f->nfrags--;
311     for ( ; ; ) { /* stick it in our descending list */
312     if (!--j || hp->bi[i].fo < f->fi[j-1].fo) {
313     f->fi[j].fo = hp->bi[i].fo;
314     f->fi[j].nrd = hp->bi[i].nrd;
315     break;
316     }
317     copystruct(f->fi+j, f->fi+j-1);
318 gregl 3.1 }
319     /* coalesce adjacent fragments */
320 gregl 3.2 for (j = k = 0; k < f->nfrags; j++, k++) {
321 gregl 3.3 if (k > j)
322 gregl 3.2 copystruct(f->fi+j, f->fi+k);
323 gregl 3.3 while (k+1 < f->nfrags && f->fi[k+1].fo +
324     f->fi[k+1].nrd*sizeof(RAYVAL)
325     == f->fi[j].fo) {
326 gregl 3.2 f->fi[j].fo -=
327     f->fi[++k].nrd*sizeof(RAYVAL);
328 gregl 3.3 f->fi[j].nrd += f->fi[k].nrd;
329     }
330 gregl 3.2 }
331     f->nfrags = j;
332 gregl 3.1 }
333     k = -1; /* find closest-sized fragment */
334     for (j = f->nfrags; j-- > 0; )
335     if (f->fi[j].nrd >= nrays &&
336 gregl 3.3 (k < 0 || f->fi[j].nrd < f->fi[k].nrd))
337     if (f->fi[k=j].nrd == nrays)
338     break;
339 gregl 3.1 if (k < 0) { /* no fragment -- extend file */
340     hp->bi[i].fo = f->flen;
341     f->flen += nrays*sizeof(RAYVAL);
342     } else { /* else use fragment */
343     hp->bi[i].fo = f->fi[k].fo;
344     if (f->fi[k].nrd == nrays) { /* delete fragment */
345     f->nfrags--;
346     for (j = k; j < f->nfrags; j++)
347     copystruct(f->fi+j, f->fi+j+1);
348     } else { /* else shrink it */
349     f->fi[k].fo += nrays*sizeof(RAYVAL);
350     f->fi[k].nrd -= nrays;
351     }
352     }
353     }
354     biglob(hp)->nrd += nrays - hp->bi[i].nrd;
355     hp->bi[i].nrd = nrays;
356     hp->dirty++; /* section directory now out of date */
357     return(1);
358     }
359    
360    
361     int
362     hdfreebeam(hp, i) /* free beam, writing if dirty */
363     register HOLO *hp;
364     register int i;
365     {
366     int nchanged, n;
367    
368     if (hp == NULL) { /* clear all holodecks */
369     nchanged = 0;
370     for (i = 0; hdlist[i] != NULL; i++)
371     nchanged += hdfreebeam(hdlist[i], 0);
372     return(nchanged);
373     }
374     if (i == 0) { /* clear entire holodeck */
375     nchanged = 0;
376     for (i = 1; i <= nbeams(hp); i++)
377     nchanged += hdfreebeam(hp, i);
378     return(nchanged);
379     }
380     if (i < 1 | i > nbeams(hp))
381     error(CONSISTENCY, "bad beam index to hdfreebeam");
382     if (hp->bl[i] == NULL)
383     return(0);
384     /* check for additions */
385     nchanged = hp->bl[i]->nrm - hp->bi[i].nrd;
386     if (nchanged) {
387     hdgetbi(hp, i); /* allocate a file position */
388     errno = 0;
389     if (lseek(hp->fd, hp->bi[i].fo, 0) < 0)
390     error(SYSTEM, "cannot seek on holodeck file");
391     n = hp->bl[i]->nrm * sizeof(RAYVAL);
392     if (write(hp->fd, (char *)hdbray(hp->bl[i]), n) != n)
393     error(SYSTEM, "write error in hdfreebeam");
394     }
395     blglob(hp)->nrm -= hp->bl[i]->nrm;
396     free((char *)hp->bl[i]); /* free memory */
397     hp->bl[i] = NULL;
398     return(nchanged);
399     }
400    
401    
402     hdlrulist(ha, ba, n, hp) /* add beams from holodeck to LRU list */
403     register HOLO *ha[]; /* section list (NULL terminated) */
404     register int ba[]; /* beam index to go with section */
405     int n; /* length of arrays minus 1 */
406     register HOLO *hp; /* section we're adding from */
407     {
408     register int i, j;
409     int nents;
410     /* find last entry in LRU list */
411     for (j = 0; ha[j] != NULL; j++)
412     ;
413     nents = j;
414     /* insert each beam from hp */
415     for (i = nbeams(hp); i > 0; i-- ) {
416     if (hp->bl[i] == NULL) /* check if loaded */
417     continue;
418     if ((j = ++nents) > n) /* grow list if we can */
419     nents--;
420     for ( ; ; ) { /* bubble into place */
421     if (!--j || hp->bl[i]->tick >=
422     ha[j-1]->bl[ba[j-1]]->tick) {
423     ha[j] = hp;
424     ba[j] = i;
425     break;
426     }
427     ha[j] = ha[j-1];
428     ba[j] = ba[j-1];
429     }
430     }
431     ha[nents] = NULL; /* all done */
432     ba[nents] = 0;
433     }
434    
435    
436     hdfreecache(pct, honly) /* free up cache space, writing changes */
437     int pct; /* maximum percentage to free */
438     register HOLO *honly; /* NULL means check all */
439     {
440     HOLO *hp[FREEBEAMS+1];
441     int bn[FREEBEAMS+1];
442     int freetarget;
443     register int i;
444     /* compute free target */
445     freetarget = (honly != NULL) ? blglob(honly)->nrm :
446     hdmemuse(0)/sizeof(RAYVAL) ;
447     freetarget = freetarget*pct/100;
448     /* find least recently used */
449     hp[0] = NULL;
450     bn[0] = 0;
451     if (honly != NULL)
452     hdlrulist(hp, bn, FREEBEAMS, honly);
453     else
454     for (i = 0; hdlist[i] != NULL; i++)
455     hdlrulist(hp, bn, FREEBEAMS, hdlist[i]);
456     /* free LRU beams */
457     for (i = 0; hp[i] != NULL; i++) {
458     hdfreebeam(hp[i], bn[i]);
459     if ((freetarget -= hp[i]->bi[bn[i]].nrd) <= 0)
460     break;
461     }
462     hdsync(honly); /* synchronize directories as necessary */
463     }
464    
465    
466     hddone(hp) /* clean up holodeck section and free */
467     register HOLO *hp; /* NULL means clean up all */
468     {
469     register int i;
470    
471     if (hp == NULL) { /* NULL means clean up everything */
472     while (hdlist[0] != NULL)
473     hddone(hdlist[0]);
474     return;
475     }
476     /* flush all data and free memory */
477     hdflush(hp);
478     /* release fragment resources */
479     hdrelease(hp->fd);
480     /* remove hp from active list */
481     for (i = 0; hdlist[i] != NULL; i++)
482     if (hdlist[i] == hp) {
483     while ((hdlist[i] = hdlist[i+1]) != NULL)
484     i++;
485     break;
486     }
487     free((char *)hp->bl); /* free beam list */
488     free((char *)hp); /* free holodeck struct */
489     }