ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/ambient.c
(Generate patch)

Comparing ray/src/rt/ambient.c (file contents):
Revision 2.130 by greg, Thu Jan 23 18:44:20 2025 UTC vs.
Revision 2.131 by greg, Thu Jan 23 22:03:08 2025 UTC

# Line 34 | Line 34 | static AMBTREE atrunk;         /* our ambient trunk node */
34  
35   static FILE  *ambfp = NULL;     /* ambient file pointer */
36   static int  nunflshed;          /* number of unflushed ambient values */
37 static FILE  *ambinp = NULL;    /* input pointer for ambient i/o */
37  
38   static double  avsum = 0.;              /* computed ambient value sum (log) */
39   static unsigned int  navsum = 0;        /* number of values in avsum */
40   static unsigned int  nambvals = 0;      /* total number of indirect values */
41 + static FILE  *ambinp = NULL;            /* auxiliary file for input */
42   static off_t  lastpos = -1;             /* last flush position */
43  
44   #define  AMBFLUSH       (BUFSIZ/AMBVALSIZ)
# Line 68 | Line 68 | static int     makeambient(SCOLOR acol, RAY *r, FVECT rn,
68   static int      extambient(SCOLOR cr, AMBVAL *ap, FVECT pv, FVECT nv,
69                                  FVECT uvw[3]);
70  
71 + #ifdef  F_SETLKW
72 + static void aflock(int  typ);
73 + #endif
74  
75 +
76   void
77   setambres(                              /* set ambient resolution */
78          int  ar
# Line 111 | Line 115 | setambacc(                             /* set ambient accuracy */
115   void
116   setambient(void)                                /* initialize calculation */
117   {
118 <        int     exists;
118 >        int     readonly = 0;
119          off_t   flen;
120          AMBVAL  amb;
121                                                  /* make sure we're fresh */
# Line 127 | Line 131 | setambient(void)                               /* initialize calculation */
131                  error(WARNING, errmsg);
132                  return;
133          }
134 <        exists = access(ambfile, F_OK) == 0;    /* check existence, first */
135 <        ambfp = fopen(ambfile, "a+");           /* try read/append */
136 <        if (!exists & (ambfp == NULL)) {
137 <                sprintf(errmsg, "cannot create ambient file \"%s\"", ambfile);
138 <                error(SYSTEM, errmsg);
139 <        }
136 <        if (ambfp == NULL) {                    /* try opening read-only? */
137 <                if ((ambfp = fopen(ambfile, "r")) == NULL) {
138 <                        sprintf(errmsg,
139 <                        "cannot open ambient file \"%s\" for reading",
140 <                                        ambfile);
141 <                        error(SYSTEM, errmsg);
142 <                }
143 <                exists = -1;                    /* flag read-only */
144 <        } else if (exists)
145 <                rewind(ambfp);  /* XXX not necessary? */
146 <
147 <        if (exists) {
148 <                initambfile(0);                 /* file already exists */
149 <                lastpos = ftell(ambfp);
134 >                                                /* open ambient file */
135 >        if ((ambfp = fopen(ambfile, "r+")) == NULL)
136 >                readonly = (ambfp = fopen(ambfile, "r")) != NULL;
137 >        if (ambfp != NULL) {
138 >                initambfile(0);                 /* file exists */
139 >                lastpos = ftello(ambfp);
140                  while (readambval(&amb, ambfp))
141 <                        avstore(&amb);          /* load what we can */
142 <                if (exists < 0) {               /* read-only? */
141 >                        avstore(&amb);
142 >                if (readonly) {
143                          sprintf(errmsg,
144                                  "loaded %u values from read-only ambient file",
145                                          nambvals);
146                          error(WARNING, errmsg);
147                          fclose(ambfp);          /* close file so no writes */
148                          ambfp = NULL;
149 <                        return;
149 >                        return;                 /* avoid ambsync() */
150                  }
151                                                  /* align file pointer */
152                  lastpos += (off_t)nambvals*AMBVALSIZ;
153                  flen = lseek(fileno(ambfp), 0, SEEK_END);
154                  if (flen != lastpos) {
155                          sprintf(errmsg,
156 <                        "ignoring last %lu values in ambient file (corrupted)",
157 <                                (unsigned long)((flen - lastpos)/AMBVALSIZ));
156 >                        "ignoring last %ld values in ambient file (corrupted)",
157 >                                        (flen - lastpos)/AMBVALSIZ);
158                          error(WARNING, errmsg);
169                                                /* fseek() not needed? */
159                          fseeko(ambfp, lastpos, SEEK_SET);
160                          ftruncate(fileno(ambfp), lastpos);
161                  }
162 <        } else {
163 <                initambfile(1);                 /* else start new file */
162 >        } else if ((ambfp = fopen(ambfile, "w+")) != NULL) {
163 >                initambfile(1);                 /* else create new file */
164                  fflush(ambfp);
165 <                lastpos = ftell(ambfp);
165 >                lastpos = ftello(ambfp);
166 >        } else {
167 >                sprintf(errmsg, "cannot open ambient file \"%s\"", ambfile);
168 >                error(SYSTEM, errmsg);
169          }
170 + #ifdef  F_SETLKW
171 +        aflock(F_UNLCK);                        /* release file */
172 + #endif
173   }
174  
175  
# Line 182 | Line 177 | void
177   ambdone(void)                   /* close ambient file and free memory */
178   {
179          if (ambfp != NULL) {            /* close ambient file */
180 <                fclose(ambfp);          /* don't call ambsync() */
180 >                ambsync();
181 >                fclose(ambfp);
182                  ambfp = NULL;
183 <                lastpos = -1;
188 <                if (ambinp != NULL) {
183 >                if (ambinp != NULL) {  
184                          fclose(ambinp);
185                          ambinp = NULL;
186                  }
187 +                lastpos = -1;
188          }
189                                          /* free ambient tree */
190          unloadatree(&atrunk, avfree);
# Line 635 | Line 631 | initambfile(           /* initialize ambient file */
631  
632          if (!AMBFLUSH)
633                  error(INTERNAL, "BUFSIZ too small in initambfile");
634 + #ifdef  F_SETLKW
635 +        aflock(cre8 ? F_WRLCK : F_RDLCK);
636 + #endif
637          SET_FILE_BINARY(ambfp);
638          if (mybuf == NULL)
639 <                mybuf = (char *)bmalloc(BUFSIZ);
639 >                mybuf = (char *)bmalloc(BUFSIZ+8);
640          setbuf(ambfp, mybuf);
641          nunflshed = 0;
642   retry:
# Line 668 | Line 667 | retry:
667                  putambmagic(ambfp);
668          } else if (getheader(ambfp, amb_headline, NULL) < 0 || !hasambmagic(ambfp)) {
669                  if (--ntries > 0 && ftell(ambfp) == 0) {
670 + #ifdef  F_SETLKW
671 +                        aflock(F_UNLCK);
672                          clearerr(ambfp);
673                          sleep(2);
674 +                        aflock(F_RDLCK);
675 + #else
676 +                        clearerr(ambfp);
677 +                        sleep(2);
678 + #endif
679                          goto retry;
680                  }
681                  error(USER, "bad/incompatible ambient file");
# Line 807 | Line 813 | sortambvals(void)                      /* resort ambient values */
813   }
814  
815  
816 + #ifdef  F_SETLKW
817 +
818 + static void
819 + aflock(                 /* lock/unlock ambient file */
820 +        int  typ
821 + )
822 + {
823 +        static struct flock  fls;       /* static so initialized to zeroes */
824 +
825 +        if (typ == fls.l_type)          /* already called? */
826 +                return;
827 +
828 +        fls.l_type = typ;
829 +        do
830 +                if (fcntl(fileno(ambfp), F_SETLKW, &fls) != -1)
831 +                        return;
832 +        while (errno == EINTR);
833 +        
834 +        error(SYSTEM, "cannot (un)lock ambient file");
835 + }
836 +
837 +
838   int
839   ambsync(void)                   /* synchronize ambient file */
840   {
841 <        off_t   newpos;
814 <        int     n;
841 >        off_t  flen;
842          AMBVAL  avs;
843 +        int  n;
844  
845          if (ambfp == NULL)      /* no ambient file? */
846                  return(0);
847 <
848 <        if (nunflshed > 0) {    /* append new values? */
849 <                if (fflush(ambfp) < 0)
850 <                        return(EOF);
823 <                newpos = lseek(fileno(ambfp), 0, SEEK_CUR);
824 <        } else
825 <                newpos = lseek(fileno(ambfp), 0, SEEK_END);
826 <
827 <        if (newpos < 0)
847 >                                /* gain appropriate access */
848 >        aflock(nunflshed ? F_WRLCK : F_RDLCK);
849 >                                /* see if file has grown */
850 >        if ((flen = lseek(fileno(ambfp), 0, SEEK_END)) < 0)
851                  goto seekerr;
852 <                                /* how many others added? */
853 <        n = (newpos - lastpos)/AMBVALSIZ - nunflshed;
854 <        nunflshed = 0;
855 <        if (n <= 0) {           /* no one helping this time? */
856 <                lastpos = newpos;
834 <                return(0);
835 <        }
836 <        if (ambinp == NULL) {   /* else need to open for input? */
837 <                ambinp = fopen(ambfile, "r");
838 <                if (ambinp == NULL) {
839 <                        sprintf(errmsg, "cannot reopen ambient file \"%s\"",
840 <                                        ambfile);
841 <                        error(SYSTEM, errmsg);
852 >        if ((n = flen - lastpos) > 0) {         /* file has grown */
853 >                if (ambinp == NULL) {           /* get new file pointer */
854 >                        ambinp = fopen(ambfile, "rb");
855 >                        if (ambinp == NULL)
856 >                                error(SYSTEM, "fopen failed in ambsync");
857                  }
858 <                SET_FILE_BINARY(ambinp);
859 <        }
860 <                                /* read from last endpoint */
861 <        if (fseeko(ambinp, lastpos, SEEK_SET) < 0)
862 <                goto seekerr;
863 <        while (n-- > 0) {       /* load new contributed values */
864 <                if (!readambval(&avs, ambinp)) {
865 <                        sprintf(errmsg, "ambient file \"%s\" corrupted",
866 <                                        ambfile);
867 <                        error(WARNING, errmsg);
868 <                        break;
858 >                if (fseeko(ambinp, lastpos, SEEK_SET) < 0)
859 >                        goto seekerr;
860 >                while (n >= AMBVALSIZ) {        /* load contributed values */
861 >                        if (!readambval(&avs, ambinp)) {
862 >                                sprintf(errmsg,
863 >                        "ambient file \"%s\" corrupted near character %ld",
864 >                                                ambfile, flen - n);
865 >                                error(WARNING, errmsg);
866 >                                break;
867 >                        }
868 >                        avstore(&avs);
869 >                        n -= AMBVALSIZ;
870                  }
871 <                avstore(&avs);
871 >                lastpos = flen - n;             /* check alignment */
872 >                if (n && lseek(fileno(ambfp), lastpos, SEEK_SET) < 0)
873 >                        goto seekerr;
874          }
875 <        lastpos = newpos;       /* update endpoint */
876 <        return(0);
875 >        n = fflush(ambfp);                      /* calls write() at last */
876 >        lastpos += (off_t)nunflshed*AMBVALSIZ;
877 >        aflock(F_UNLCK);                        /* release file */
878 >        nunflshed = 0;
879 >        return(n);
880   seekerr:
881          error(SYSTEM, "seek failed in ambsync");
882          return(EOF);    /* pro forma return */
883   }
884 +
885 + #else   /* ! F_SETLKW */
886 +
887 + int
888 + ambsync(void)                   /* flush ambient file */
889 + {
890 +        if (ambfp == NULL)
891 +                return(0);
892 +        nunflshed = 0;
893 +        return(fflush(ambfp));
894 + }
895 +
896 + #endif  /* ! F_SETLKW */

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines