Back to index

radiance  4R0+20100331
rhoptimize.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char    RCSid[] = "$Id: rhoptimize.c,v 3.18 2004/01/01 11:21:55 schorsch Exp $";
00003 #endif
00004 /*
00005  * Optimize holodeck for quick access.
00006  *
00007  *     11/4/98              Greg Ward Larson
00008  */
00009 
00010 #include <signal.h>
00011 #include <string.h>
00012 #include <stdio.h>
00013 
00014 #include "platform.h"
00015 #include "rterror.h"
00016 #include "resolu.h"
00017 #include "rtprocess.h" /* getpid() */
00018 #include "holo.h"
00019 
00020 #ifndef BKBSIZE
00021 #define BKBSIZE             256           /* beam clump size (kilobytes) */
00022 #endif
00023 
00024 char   *progname;
00025 char   tempfile[128];
00026 int    dupchecking = 0;
00027 
00028 static long rhinitcopy(int hfd[2], char *infn, char *outfn);
00029 static int nuniq(RAYVAL *rva, int n);
00030 static int bpcmp(const void *b1p, const void *b2p);
00031 static int xferclump(HOLO *hp, int *bq, int nb);
00032 static void copysect(int ifd, int ofd);
00033 
00034 
00035 int
00036 main(
00037        int    argc,
00038        char   *argv[]
00039 )
00040 {
00041        char   *inpname, *outname;
00042        int    hdfd[2];
00043        long   nextipos, lastopos, thisopos;
00044 
00045        progname = argv[0];
00046        argv++; argc--;                    /* duplicate checking flag? */
00047        if (argc > 1 && !strcmp(argv[0], "-u")) {
00048               dupchecking++;
00049               argv++; argc--;
00050        }
00051        if ((argc < 1) | (argc > 2)) {
00052               fprintf(stderr, "Usage: %s [-u] input.hdk [output.hdk]\n",
00053                             progname);
00054               exit(1);
00055        }
00056        inpname = argv[0];          /* get input file */
00057        argv++; argc--;
00058        if (argc == 1)                     /* use given output file */
00059               outname = argv[0];
00060        else {                      /* else use temporary file */
00061               if (access(inpname, R_OK|W_OK) < 0) {     /* check permissions */
00062                      sprintf(errmsg, "cannot access \"%s\"", inpname);
00063                      error(SYSTEM, errmsg);
00064               }
00065               strcpy(tempfile, inpname);
00066               if ((outname = strrchr(tempfile, '/')) != NULL)
00067                      outname++;
00068               else
00069                      outname = tempfile;
00070               sprintf(outname, "rho%d.hdk", getpid());
00071               outname = tempfile;
00072        }
00073                                    /* copy holodeck file header */
00074        nextipos = rhinitcopy(hdfd, inpname, outname);
00075        lastopos = 0L;                     /* copy sections one by one */
00076        while (nextipos != 0L) {
00077                                    /* set input position; get next */
00078               lseek(hdfd[0], (off_t)nextipos, SEEK_SET);
00079               read(hdfd[0], (char *)&nextipos, sizeof(nextipos));
00080                                    /* get output position; set last */
00081               thisopos = lseek(hdfd[1], (off_t)0, SEEK_END);
00082               if (lastopos > 0L) {
00083                      lseek(hdfd[1], (off_t)lastopos, SEEK_SET);
00084                      write(hdfd[1], (char *)&thisopos, sizeof(thisopos));
00085                      lseek(hdfd[1], (off_t)0, SEEK_END);
00086               }
00087               lastopos = thisopos;
00088               thisopos = 0L;              /* write place holder */
00089               write(hdfd[1], (char *)&thisopos, sizeof(thisopos));
00090                                    /* copy holodeck section */
00091               copysect(hdfd[0], hdfd[1]);
00092        }
00093                                    /* clean up */
00094        close(hdfd[0]);
00095        close(hdfd[1]);
00096        if (outname == tempfile && rename(outname, inpname) < 0) {
00097               sprintf(errmsg, "cannot rename \"%s\" to \"%s\"",
00098                             outname, inpname);
00099               error(SYSTEM, errmsg);
00100        }
00101        return 0;
00102 }
00103 
00104 
00105 static long
00106 rhinitcopy(   /* open files and copy header */
00107        int    hfd[2],                     /* returned file descriptors */
00108        char   *infn,
00109        char   *outfn
00110 )
00111 {
00112        FILE   *infp, *outfp;
00113        long   ifpos;
00114                                    /* open files for i/o */
00115        if ((infp = fopen(infn, "r")) == NULL) {
00116               sprintf(errmsg, "cannot open \"%s\" for reading", infn);
00117               error(SYSTEM, errmsg);
00118        }
00119        if (access(outfn, F_OK) == 0) {
00120               sprintf(errmsg, "output file \"%s\" already exists!", outfn);
00121               error(USER, errmsg);
00122        }
00123        if ((outfp = fopen(outfn, "w+")) == NULL) {
00124               sprintf(errmsg, "cannot open \"%s\" for writing", outfn);
00125               error(SYSTEM, errmsg);
00126        }
00127                                    /* set up signal handling */
00128        if (signal(SIGINT, quit) == SIG_IGN) signal(SIGINT, SIG_IGN);
00129        if (signal(SIGHUP, quit) == SIG_IGN) signal(SIGHUP, SIG_IGN);
00130        if (signal(SIGTERM, quit) == SIG_IGN) signal(SIGTERM, SIG_IGN);
00131 #ifdef SIGXCPU
00132        if (signal(SIGXCPU, quit) == SIG_IGN) signal(SIGXCPU, SIG_IGN);
00133        if (signal(SIGXFSZ, quit) == SIG_IGN) signal(SIGXFSZ, SIG_IGN);
00134 #endif
00135                                    /* copy and verify header */
00136        if (checkheader(infp, HOLOFMT, outfp) < 0 || getw(infp) != HOLOMAGIC)
00137               error(USER, "input not in holodeck format");
00138        fputformat(HOLOFMT, outfp);
00139        fputc('\n', outfp);
00140        putw(HOLOMAGIC, outfp);
00141                                    /* get descriptors and free stdio */
00142        if ((hfd[0] = dup(fileno(infp))) < 0 ||
00143                      (hfd[1] = dup(fileno(outfp))) < 0)
00144               error(SYSTEM, "dup call failed in rhinitcopy");
00145        ifpos = ftell(infp);
00146        fclose(infp);
00147        if (fclose(outfp) == EOF)
00148               error(SYSTEM, "file flushing error in rhinitcopy");
00149                                    /* check cache size */
00150        if (BKBSIZE*1024*1.5 > hdcachesize)
00151               hdcachesize = BKBSIZE*1024*1.5;
00152                                    /* return input position */
00153        return(ifpos);
00154 }
00155 
00156 
00157 static int
00158 nuniq(               /* sort unique rays to front of beam list */
00159        register RAYVAL      *rva,
00160        int    n
00161 )
00162 {
00163        register int  i, j;
00164        RAYVAL rtmp;
00165 
00166        for (j = 0; j < n; j++)
00167               for (i = j+1; i < n; i++)
00168                      if ( rva[i].d == rva[j].d &&
00169                                    rva[i].r[0][0]==rva[j].r[0][0] &&
00170                                    rva[i].r[0][1]==rva[j].r[0][1] &&
00171                                    rva[i].r[1][0]==rva[j].r[1][0] &&
00172                                    rva[i].r[1][1]==rva[j].r[1][1] ) {
00173                             n--;          /* swap duplicate with end */
00174                             rtmp = *(rva+n);
00175                             *(rva+n) = *(rva+i);
00176                             *(rva+i) = rtmp;
00177                             i--;          /* recheck one we swapped */
00178                      }
00179        return(n);
00180 }
00181 
00182 
00183 static BEAMI  *beamdir;
00184 
00185 static int
00186 bpcmp(               /* compare beam positions on disk */
00187        const void    *b1p,
00188        const void    *b2p
00189 )
00190 {
00191        register off_t       pdif = beamdir[*(int*)b1p].fo - beamdir[*(int*)b2p].fo;
00192 
00193        if (pdif < 0L) return(-1);
00194        return(pdif > 0L);
00195 }
00196 
00197 static HOLO   *hout;
00198 
00199 static int
00200 xferclump(           /* transfer the given clump to hout and free */
00201        HOLO   *hp,
00202        int    *bq,
00203        int    nb
00204 )
00205 {
00206        register int  i;
00207        register BEAM *bp;
00208        int    n;
00209 
00210        beamdir = hp->bi;           /* sort based on file position */
00211        qsort((void *)bq, nb, sizeof(*bq), bpcmp);
00212                                    /* transfer and free each beam */
00213        for (i = 0; i < nb; i++) {
00214               bp = hdgetbeam(hp, bq[i]);
00215               DCHECK(bp==NULL, CONSISTENCY, "empty beam in xferclump");
00216               n = dupchecking ? nuniq(hdbray(bp),bp->nrm) : bp->nrm;
00217               memcpy((void *)hdnewrays(hout,bq[i],n),(void *)hdbray(bp), 
00218                             n*sizeof(RAYVAL));
00219               hdfreebeam(hp, bq[i]);
00220        }
00221        hdfreebeam(hout, 0);        /* write & free clump */
00222        return(0);
00223 }
00224 
00225 static void
00226 copysect(            /* copy holodeck section from ifd to ofd */
00227        int    ifd,
00228        int    ofd
00229 )
00230 {
00231        HOLO   *hinp;
00232                                    /* load input section directory */
00233        hinp = hdinit(ifd, NULL);
00234                                    /* create output section directory */
00235        hout = hdinit(ofd, (HDGRID *)hinp);
00236                                    /* clump the beams */
00237        clumpbeams(hinp, 0, BKBSIZE*1024, xferclump);
00238                                    /* clean up */
00239        hddone(hinp);
00240        hddone(hout);
00241 }
00242 
00243 
00244 void
00245 eputs(s)                    /* put error message to stderr */
00246 register char  *s;
00247 {
00248        static int  midline = 0;
00249 
00250        if (!*s)
00251               return;
00252        if (!midline++) {    /* prepend line with program name */
00253               fputs(progname, stderr);
00254               fputs(": ", stderr);
00255        }
00256        fputs(s, stderr);
00257        if (s[strlen(s)-1] == '\n') {
00258               fflush(stderr);
00259               midline = 0;
00260        }
00261 }
00262 
00263 
00264 void
00265 quit(code)                  /* exit the program gracefully */
00266 int    code;
00267 {
00268        if (tempfile[0])
00269               unlink(tempfile);
00270        exit(code);
00271 }