ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rholo.c
Revision: 3.34
Committed: Sun Jan 4 18:36:43 1998 UTC (26 years, 3 months ago) by gregl
Content type: text/plain
Branch: MAIN
Changes since 3.33: +3 -2 lines
Log Message:
made loading of RIF dependent on -n option

File Contents

# Content
1 /* Copyright (c) 1997 Silicon Graphics, Inc. */
2
3 #ifndef lint
4 static char SCCSid[] = "$SunId$ SGI";
5 #endif
6
7 /*
8 * Radiance holodeck generation controller
9 */
10
11 #include "rholo.h"
12 #include "random.h"
13 #include <signal.h>
14 #include <sys/types.h>
15 #include <sys/stat.h>
16
17 #ifndef MAXQTIME
18 #define MAXQTIME 5 /* target maximum seconds in queue */
19 #endif
20 /* the following must be consistent with rholo.h */
21 int NVARS = NRHVARS; /* total number of variables */
22
23 VARIABLE vv[] = RHVINIT; /* variable-value pairs */
24
25 char *progname; /* our program name */
26 char *hdkfile; /* holodeck file name */
27 char froot[256]; /* root file name */
28
29 int nowarn = 0; /* turn warnings off? */
30
31 int ncprocs = 0; /* desired number of compute processes */
32
33 char *outdev = NULL; /* output device name */
34
35 int readinp = 0; /* read commands from stdin */
36
37 int force = 0; /* allow overwrite of holodeck */
38
39 time_t starttime; /* time we got started */
40 time_t endtime; /* time we should end by */
41 time_t reporttime; /* time for next report */
42
43 long maxdisk; /* maximum file space (bytes) */
44
45 int rtargc = 1; /* rtrace command */
46 char *rtargv[128] = {"rtrace", NULL};
47
48 int orig_mode = -1; /* original file mode (-1 if unchanged) */
49
50 long nraysdone = 0L; /* number of rays done */
51 long npacksdone = 0L; /* number of packets done */
52
53 PACKET *freepacks; /* available packets */
54 int avgqlen; /* average queue length when full */
55
56 char *sigerr[NSIG]; /* signal error messages */
57
58 extern time_t time();
59
60
61 main(argc, argv)
62 int argc;
63 char *argv[];
64 {
65 int i;
66
67 initurand(16384); /* initialize urand */
68 progname = argv[0]; /* get arguments */
69 for (i = 1; i < argc && argv[i][0] == '-'; i++)
70 switch (argv[i][1]) {
71 case 'w': /* turn off warnings */
72 nowarn++;
73 break;
74 case 'f': /* force overwrite */
75 force++;
76 break;
77 case 'i': /* read input from stdin */
78 readinp++;
79 break;
80 case 'n': /* compute processes */
81 if (i >= argc-2)
82 goto userr;
83 ncprocs = atoi(argv[++i]);
84 break;
85 case 'o': /* output display */
86 if (i >= argc-2)
87 goto userr;
88 outdev = argv[++i];
89 break;
90 default:
91 goto userr;
92 }
93 /* get root file name */
94 if (i >= argc)
95 goto userr;
96 rootname(froot, hdkfile=argv[i++]);
97 /* load variables? */
98 if (i < argc)
99 if (argv[i][0] != '-' && argv[i][0] != '+')
100 loadvars(argv[i]); /* load variables from file */
101
102 if (i >= argc || argv[i][0] == '+')
103 loadholo(); /* load existing holodeck */
104
105 while (++i < argc) /* get command line settings */
106 if (setvariable(argv[i], matchvar) < 0) {
107 sprintf(errmsg, "unknown variable: %s", argv[i]);
108 error(USER, errmsg);
109 }
110 /* check settings */
111 checkvalues();
112 /* load RIF if rtrace */
113 if (ncprocs)
114 getradfile();
115
116 if (hdlist[0] == NULL) { /* create new holodeck */
117 HDGRID hdg[HDMAX];
118 /* set defaults */
119 setdefaults(hdg);
120 /* holodeck exists? */
121 if (!force && access(hdkfile, R_OK|W_OK) == 0)
122 error(USER,
123 "holodeck file exists -- use -f to overwrite");
124 /* create holodeck */
125 creatholo(hdg);
126 } else /* else just set defaults */
127 setdefaults(NULL);
128 /* initialize */
129 initrholo();
130 /* main loop */
131 while (rholo())
132 ;
133 /* done */
134 quit(0);
135 userr:
136 fprintf(stderr,
137 "Usage: %s [-n nprocs][-o disp][-w][-f] output.hdk [control.hif|+|- [VAR=val ..]]\n",
138 progname);
139 quit(1);
140 }
141
142
143 onsig(signo) /* fatal signal */
144 int signo;
145 {
146 static int gotsig = 0;
147
148 if (gotsig++) /* two signals and we're gone! */
149 _exit(signo);
150
151 alarm(60); /* allow 60 seconds to clean up */
152 signal(SIGALRM, SIG_DFL); /* make certain we do die */
153 eputs("signal - ");
154 eputs(sigerr[signo]);
155 eputs("\n");
156 quit(3);
157 }
158
159
160 sigdie(signo, msg) /* set fatal signal */
161 int signo;
162 char *msg;
163 {
164 if (signal(signo, onsig) == SIG_IGN)
165 signal(signo, SIG_IGN);
166 sigerr[signo] = msg;
167 }
168
169
170 int
171 resfmode(fd, mod) /* restrict open file access mode */
172 int fd, mod;
173 {
174 struct stat stbuf;
175 /* get original mode */
176 if (fstat(fd, &stbuf) < 0)
177 error(SYSTEM, "cannot stat open holodeck file");
178 mod &= stbuf.st_mode; /* always more restrictive */
179 if (mod == stbuf.st_mode)
180 return(-1); /* already set */
181 /* else change it */
182 if (fchmod(fd, mod) < 0) {
183 error(WARNING, "cannot change holodeck file access mode");
184 return(-1);
185 }
186 return(stbuf.st_mode); /* return original mode */
187 }
188
189
190 initrholo() /* get our holodeck running */
191 {
192 extern int global_packet();
193 register int i;
194 /* close holodeck on exec() */
195 fcntl(hdlist[0]->fd, F_SETFD, FD_CLOEXEC);
196
197 if (outdev != NULL) /* open output device */
198 disp_open(outdev);
199 else if (ncprocs > 0) /* else use global ray feed */
200 init_global();
201 /* record disk space limit */
202 if (!vdef(DISKSPACE))
203 maxdisk = 0;
204 else
205 maxdisk = 1024.*1024.*vflt(DISKSPACE);
206 /* set up memory cache */
207 if (outdev == NULL)
208 hdcachesize = 0; /* manual flushing */
209 else if (vdef(CACHE))
210 hdcachesize = 1024.*1024.*vflt(CACHE);
211 /* open report file */
212 if (vdef(REPORT)) {
213 register char *s = sskip2(vval(REPORT), 1);
214 if (*s && freopen(s, "a", stderr) == NULL)
215 quit(2);
216 }
217 /* mark the starting time */
218 starttime = time(NULL);
219 /* compute end time */
220 if (!vdef(TIME) || vflt(TIME) <= FTINY)
221 endtime = 0;
222 else
223 endtime = starttime + vflt(TIME)*3600. + .5;
224 /* start rtrace */
225 if (ncprocs > 0) {
226 i = start_rtrace();
227 if (i < 1)
228 error(USER, "cannot start rtrace process(es)");
229 if (vdef(REPORT)) { /* make first report */
230 printargs(rtargc, rtargv, stderr);
231 report(0);
232 }
233 /* allocate packets */
234 freepacks = (PACKET *)bmalloc(i*sizeof(PACKET));
235 if (freepacks == NULL)
236 goto memerr;
237 if (!(avgqlen = i/nprocs)) /* record mean queue length */
238 avgqlen = 1;
239 freepacks[--i].nr = 0;
240 freepacks[i].next = NULL;
241 if (!vdef(OBSTRUCTIONS) || !vbool(OBSTRUCTIONS)) {
242 freepacks[i].offset = (float *)bmalloc(
243 RPACKSIZ*sizeof(float)*(i+1) );
244 if (freepacks[i].offset == NULL)
245 goto memerr;
246 } else
247 freepacks[i].offset = NULL;
248 while (i--) {
249 freepacks[i].nr = 0;
250 freepacks[i].offset = freepacks[i+1].offset == NULL ?
251 NULL : freepacks[i+1].offset+RPACKSIZ ;
252 freepacks[i].next = &freepacks[i+1];
253 }
254 }
255 /* set up signal handling */
256 sigdie(SIGINT, "Interrupt");
257 sigdie(SIGHUP, "Hangup");
258 sigdie(SIGTERM, "Terminate");
259 sigdie(SIGPIPE, "Broken pipe");
260 sigdie(SIGALRM, "Alarm clock");
261 #ifdef SIGXCPU
262 sigdie(SIGXCPU, "CPU limit exceeded");
263 sigdie(SIGXFSZ, "File size exceeded");
264 #endif
265 /* protect holodeck file */
266 orig_mode = resfmode(hdlist[0]->fd, ncprocs>0 ? 0 : 0444);
267 return;
268 memerr:
269 error(SYSTEM, "out of memory in initrholo");
270 }
271
272
273 rholo() /* holodeck main loop */
274 {
275 static int idle = 0;
276 PACKET *pl = NULL, *plend;
277 int pksiz;
278 register PACKET *p;
279 time_t t;
280 /* check display */
281 if (nprocs <= 0)
282 idle = 1;
283 if (outdev != NULL) {
284 if (!disp_check(idle))
285 return(0); /* quit request */
286 if (nprocs <= 0)
287 return(1);
288 } else if (idle)
289 return(0); /* all done */
290 /* check file size */
291 if (maxdisk > 0 && hdfilen(hdlist[0]->fd) >= maxdisk) {
292 error(WARNING, "file limit exceeded");
293 done_rtrace();
294 return(1); /* comes back */
295 }
296 t = time(NULL); /* check time */
297 if (endtime > 0 && t >= endtime) {
298 error(WARNING, "time limit exceeded");
299 done_rtrace();
300 return(1); /* comes back */
301 }
302 if (reporttime > 0 && t >= reporttime)
303 report(t);
304 /* figure out good packet size */
305 #if MAXQTIME
306 pksiz = nraysdone*MAXQTIME/(avgqlen*(t - starttime + 1L));
307 if (pksiz < 1)
308 pksiz = 1;
309 else if (pksiz > RPACKSIZ)
310 #endif
311 pksiz = RPACKSIZ;
312 idle = 0; /* get packets to process */
313 while (freepacks != NULL) {
314 p = freepacks; freepacks = p->next; p->next = NULL;
315 if (!next_packet(p, pksiz)) {
316 p->next = freepacks; freepacks = p;
317 idle = 1;
318 break;
319 }
320 if (pl == NULL) pl = p;
321 else plend->next = p;
322 plend = p;
323 }
324 /* process packets */
325 done_packets(do_packets(pl));
326 return(1); /* and continue */
327 }
328
329
330 setdefaults(gp) /* set default values */
331 register HDGRID *gp;
332 {
333 extern char *atos();
334 register int i;
335 int n;
336 double len[3], maxlen, d;
337 char buf[64];
338
339 if (!vdef(SECTION)) {
340 sprintf(errmsg, "%s must be defined", vnam(SECTION));
341 error(USER, errmsg);
342 }
343 if (!vdef(OCTREE)) {
344 if ((vval(OCTREE) = bmalloc(strlen(froot)+5)) == NULL)
345 error(SYSTEM, "out of memory");
346 sprintf(vval(OCTREE), "%s.oct", froot);
347 vdef(OCTREE)++;
348 }
349 if (!vdef(VDIST)) {
350 vval(VDIST) = "F";
351 vdef(VDIST)++;
352 }
353 /* append rendering options */
354 if (vdef(RENDER))
355 rtargc += wordstring(rtargv+rtargc, vval(RENDER));
356
357 if (gp == NULL) /* already initialized? */
358 return;
359 /* set grid parameters */
360 for (n = 0; n < vdef(SECTION); n++, gp++) {
361 gp->grid[0] = gp->grid[1] = gp->grid[2] = 0;
362 if (sscanf(nvalue(SECTION, n),
363 "%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %hd %hd %hd",
364 &gp->orig[0], &gp->orig[1], &gp->orig[2],
365 &gp->xv[0][0], &gp->xv[0][1], &gp->xv[0][2],
366 &gp->xv[1][0], &gp->xv[1][1], &gp->xv[1][2],
367 &gp->xv[2][0], &gp->xv[2][1], &gp->xv[2][2],
368 &gp->grid[0], &gp->grid[1], &gp->grid[2]) < 12)
369 badvalue(SECTION);
370 maxlen = 0.;
371 for (i = 0; i < 3; i++)
372 if ((len[i] = VLEN(gp->xv[i])) > maxlen)
373 maxlen = len[i];
374 if (!vdef(GRID))
375 d = 0.125*maxlen;
376 else if ((d = vflt(GRID)) <= FTINY)
377 badvalue(GRID);
378 for (i = 0; i < 3; i++)
379 if (gp->grid[i] <= 0)
380 gp->grid[i] = len[i]/d + (1.-FTINY);
381 }
382 }
383
384
385 creatholo(gp) /* create a holodeck output file */
386 HDGRID *gp;
387 {
388 extern char VersionID[];
389 int4 lastloc, nextloc;
390 int n;
391 int fd;
392 FILE *fp;
393 /* open & truncate file */
394 if ((fp = fopen(hdkfile, "w+")) == NULL) {
395 sprintf(errmsg, "cannot open \"%s\" for writing", hdkfile);
396 error(SYSTEM, errmsg);
397 }
398 /* write information header */
399 newheader("RADIANCE", fp);
400 fprintf(fp, "SOFTWARE= %s\n", VersionID);
401 printvars(fp);
402 fputformat(HOLOFMT, fp);
403 fputc('\n', fp);
404 putw(HOLOMAGIC, fp); /* put magic number */
405 fd = dup(fileno(fp));
406 fclose(fp); /* flush and close stdio stream */
407 lastloc = lseek(fd, 0L, 2);
408 for (n = vdef(SECTION); n--; gp++) { /* initialize each section */
409 nextloc = 0L;
410 write(fd, (char *)&nextloc, sizeof(nextloc));
411 hdinit(fd, gp); /* writes beam index */
412 if (!n)
413 break;
414 nextloc = hdfilen(fd); /* write section pointer */
415 if (lseek(fd, (long)lastloc, 0) < 0)
416 error(SYSTEM,
417 "cannot seek on holodeck file in creatholo");
418 write(fd, (char *)&nextloc, sizeof(nextloc));
419 lseek(fd, (long)(lastloc=nextloc), 0);
420 }
421 }
422
423
424 headline(s) /* process information header line */
425 char *s;
426 {
427 extern char FMTSTR[];
428 register char *cp;
429 char fmt[32];
430
431 if (formatval(fmt, s)) {
432 if (strcmp(fmt, HOLOFMT)) {
433 sprintf(errmsg, "%s file \"%s\" has %s%s",
434 HOLOFMT, hdkfile, FMTSTR, fmt);
435 error(USER, errmsg);
436 }
437 return;
438 }
439 for (cp = s; *cp; cp++) /* take off any comments */
440 if (*cp == '#') {
441 *cp = '\0';
442 break;
443 }
444 setvariable(s, matchvar); /* don't flag errors */
445 }
446
447
448 loadholo() /* start loading a holodeck from fname */
449 {
450 extern long ftell();
451 FILE *fp;
452 int fd;
453 int n;
454 int4 nextloc;
455 /* open holodeck file */
456 if ((fp = fopen(hdkfile, ncprocs>0 ? "r+" : "r")) == NULL) {
457 sprintf(errmsg, "cannot open \"%s\" for %s", hdkfile,
458 ncprocs>0 ? "appending" : "reading");
459 error(SYSTEM, errmsg);
460 }
461 /* load variables from header */
462 getheader(fp, headline, NULL);
463 /* check magic number */
464 if (getw(fp) != HOLOMAGIC) {
465 sprintf(errmsg, "bad magic number in holodeck file \"%s\"",
466 hdkfile);
467 error(USER, errmsg);
468 }
469 nextloc = ftell(fp); /* get stdio position */
470 fd = dup(fileno(fp));
471 fclose(fp); /* done with stdio */
472 for (n = 0; nextloc > 0L; n++) { /* initialize each section */
473 lseek(fd, (long)nextloc, 0);
474 read(fd, (char *)&nextloc, sizeof(nextloc));
475 hdinit(fd, NULL);
476 }
477 if (n != vdef(SECTION)) {
478 sprintf(errmsg, "number of sections does not match %s setting",
479 vnam(SECTION));
480 error(WARNING, errmsg);
481 }
482 }
483
484
485 done_packets(pl) /* handle finished packets */
486 PACKET *pl;
487 {
488 static int n2flush = 0;
489 register PACKET *p;
490
491 while (pl != NULL) {
492 p = pl; pl = p->next; p->next = NULL;
493 if (p->nr > 0) { /* add to holodeck */
494 bcopy((char *)p->ra,
495 (char *)hdnewrays(hdlist[p->hd],p->bi,p->nr),
496 p->nr*sizeof(RAYVAL));
497 if (outdev != NULL) /* display it */
498 disp_packet((PACKHEAD *)p);
499 if (hdcachesize <= 0) /* manual flushing */
500 n2flush++;
501 nraysdone += p->nr;
502 npacksdone++;
503 p->nr = 0;
504 }
505 p->next = freepacks; /* push onto free list */
506 freepacks = p;
507 }
508 if (n2flush > 300/MAXQTIME*avgqlen*nprocs) {
509 hdflush(NULL); /* flush holodeck buffers */
510 n2flush = 0;
511 }
512 }
513
514
515 rootname(rn, fn) /* remove tail from end of fn */
516 register char *rn, *fn;
517 {
518 char *tp, *dp;
519
520 for (tp = NULL, dp = rn; *rn = *fn++; rn++)
521 if (*rn == '/')
522 dp = rn;
523 else if (*rn == '.')
524 tp = rn;
525 if (tp != NULL && tp > dp)
526 *tp = '\0';
527 }
528
529
530 badvalue(vc) /* report bad variable value and exit */
531 int vc;
532 {
533 sprintf(errmsg, "bad value for variable '%s'", vnam(vc));
534 error(USER, errmsg);
535 }
536
537
538 eputs(s) /* put error message to stderr */
539 register char *s;
540 {
541 static int midline = 0;
542
543 if (!*s)
544 return;
545 if (!midline++) { /* prepend line with program name */
546 fputs(progname, stderr);
547 fputs(": ", stderr);
548 }
549 fputs(s, stderr);
550 if (s[strlen(s)-1] == '\n') {
551 fflush(stderr);
552 midline = 0;
553 }
554 }
555
556
557 wputs(s) /* put warning string to stderr */
558 char *s;
559 {
560 if (!nowarn)
561 eputs(s);
562 }
563
564
565 quit(ec) /* exit program gracefully */
566 int ec;
567 {
568 int status = 0;
569
570 if (hdlist[0] != NULL) { /* close holodeck */
571 if (nprocs > 0)
572 status = done_rtrace(); /* calls hdsync() */
573 if (ncprocs > 0 && vdef(REPORT)) {
574 long fsiz, fuse;
575 fsiz = hdfilen(hdlist[0]->fd);
576 fuse = hdfiluse(hdlist[0]->fd, 1);
577 fprintf(stderr,
578 "%s: %.1f Mbyte holodeck file, %.1f%% fragmentation\n",
579 hdkfile, fsiz/(1024.*1024.),
580 100.*(fsiz-fuse)/fsiz);
581 }
582 }
583 if (orig_mode >= 0) /* reset holodeck access mode */
584 fchmod(hdlist[0]->fd, orig_mode);
585 if (outdev != NULL) /* close display */
586 disp_close();
587 exit(ec ? ec : status); /* exit */
588 }