On Friday 11 March 2011, 18:13:20, Jesper Saxtorph wrote: > > -----Original Message----- > > From: Kim Woelders [mailto:k...@woelders.dk] > > Sent: 10. marts 2011 20:52 > > To: Carsten Haitzler > > Cc: enlightenment-devel@lists.sourceforge.net; Jesper Saxtorph > > Subject: Re: [E-devel] imlib2 caching can fail > > > > On Thu, 10 Mar 2011 10:31:32 +0100, Carsten Haitzler > > > > <ras...@rasterman.com> wrote: > > > On Sun, 06 Mar 2011 07:49:59 +0100 "Kim Woelders" <k...@woelders.dk> > > > > said: > > >> On Thu, 03 Mar 2011 15:46:15 +0100, Jesper Saxtorph > > >> > > >> <jesper.saxto...@prevas.dk> wrote: > > >> > I have just submitted a bugraport + a patch on trac (bug #716). > > >> > > > >> > I just wanted to notifify it here also as I do not know the > > >> > enlightenment community and how it works. > > >> > > >> Either is fine. > > >> > > >> > To repeat my bug report: > > >> > "I use imlib2 as a image library in a project. However the use we > > > > have > > > > >> > sometimes tricker a situation where imlib2 uses an invalid cache. > > >> > > > >> > imlib2 uses timestamps to test if a image cache i valid. If a > > files > > > >> > modification time is in the future it is not possible to use > > >> > > >> validation > > >> > > >> > scheme. Further if the timestamp is equal to now, we do not know > > if > > > >> the > > >> > > >> > modification time is in the future or not. The result is that the > > >> > > >> cache > > >> > > >> > should be invalidated for file timestamps >= now. > > >> > An example of a problematic situation: timestamps are in whole > > > > seconds > > > > >> > times given as here as seconds: > > >> > time=32.1 : image.png is written by someone > > >> > time=32.4 : image.png is loaded by imlib2 > > >> > time=32.5 : image.png is written with new data > > >> > The situation is now that the cache has the same timestamp as the > > >> > > >> file, > > >> > > >> > but the content is not the same. > > >> > > > >> > A possible fix is a 3 line patch, which I have attached. It > > > > invalidate > > > > >> > the cache if the files timestamp is >= now. > > >> > The patch is made agains head, however, the image.c file (where > > the > > > >> > patch is applied) has changed very little in it lifetime, so it > > works > > > >> > fine with earlier versions of imlib2 (I use it against 1.4.2)." > > >> > > > >> > I attached an incorrect patch at first to the ticket, but have > > >> > > >> submittet > > >> > > >> > the correct afterwards. Sorry for that. > > >> > > > >> > My suggestion to a patch (I have made the long comment as I think > > it > > > >> is > > >> > > >> > not obvious why it is needed): > > >> > --- imlib2/src/lib/image.c.orig 2011-03-03 14:23:49.000000000 > > +0100 > > > >> > +++ imlib2/src/lib/image.c 2011-03-03 14:45:19.000000000 > > +0100 > > > >> > @@ -1017,6 +1017,18 @@ > > >> > > > >> > im->key = __imlib_FileKey(file); > > >> > > > >> > } > > >> > > > >> > im->moddate = __imlib_FileModDate(file); > > >> > > > >> > + /* If the file modify time is now or in the future, we can > > not > > > >> make > > >> > > >> > a */ > > >> > + /* cache. */ > > >> > + /* One of several possible scenarios: */ > > >> > + /* time=now: file is written by someone */ > > >> > + /* time=now: file is loaded here */ > > >> > + /* time=now: file is written again by someone */ > > >> > + /* Now we have a file a timestamp equal to our cache, but > > with a > > > >> */ > > >> > > >> > + /* different content. */ > > >> > + if (im->moddate >= time(NULL)) > > >> > + { > > >> > + dont_cache = 1; > > >> > + } > > >> > > > >> > /* ok - just check all our loaders are up to date */ > > >> > __imlib_RescanLoaders(); > > >> > /* take a guess by extension on the best loader to use */ > > >> > > > >> > Hope it make sense, otherwise feel free to ask and/or discuss it > > >> > > >> I see there is a problem, but I don't think it is the proper > > solution. > > > >> If you have a file with a "now"/future time stamp it would never be > > >> cached, which is wrong. > > >> > > >> How about in stead changing line 986 (svn) to check whether the > > time > > > >> stamp > > >> has changed in stead of checking if it is newer? > > > > > > while in general you are also right.. he's also trying to fix the > > > problem of > > > "write file at 34.1 secs, then write AGAIN at 34.5 secs" - they both > > > have the > > > SAME timestamp but the 2nd is newer. imlib2 will not load the newer > > file > > > > as the > > > timestamps match due to timestamp resolution (34 vs 34 secs). but > > while > > > > solving > > > this problem it breaks caching for timestamp == now. you'd need > > much > > > > higher > > > resolution timestamps (and even then you still just have a smaller > > race > > > > condition) or .. you'd have to have another way to differentiate the > > > files. > > > file size + timestamp + inode + .... even then you just lower the > > > probability > > > not eliminate it. > > > > Yeah, I know. > > > > The important thing here, IMO, is that images which never change, > > should > > > always be cached (unless explicitly not caching), whichever > > past/now/future time stamp they may have. > > > > How about this: > > > > diff --git src/lib/image.c src/lib/image.c > > index d404961..e8610b2 100644 > > --- src/lib/image.c > > +++ src/lib/image.c > > @@ -982,8 +982,10 @@ __imlib_LoadImage(const char *file, > > ImlibProgressFunction progres > > > > time_t current_modified_time; > > > > current_modified_time = __imlib_FileModDate(file); > > > > - /* if the file on disk is newer than the cached one */ > > - if (current_modified_time > im->moddate) > > + /* if the disk file time stamp is different from the */ > > + /* cached one or appears to have just been set */ > > + if ((current_modified_time != im->moddate) || > > + (current_modified_time == time(NULL))) > > > > { > > > > /* invalidate image */ > > SET_FLAG(im->flags, F_INVALID); > > > > This of course requires using imlib_image_set_changes_on_disk() in the > > application. > > If I remember right, setting the F_INVALID flag will invalidate the > current (old) cach and not prevent caching what we are about to load. > > The problem I describe is that when we load an image with a timestamp > now or in the future, we will never be able to see if there is a never > image on the disk afterwards. Therefore you can not check and invalidate > the cach later on, as you try to do. > If you take my sequence of write image -> imlib load it -> write it > again within the same timestamp, you will not be able to detect that it > has happened afterwards. Your suggestion will simple invalidate any old > cach sitting around, then load the image and cach it and never see it > has changed again within the same timestamp. > > However, as I have been looking at the code again, I found that you are > right that dont_cache will make it never cache the image, as it test > dont_cache in the end of the function and set F_UNCACHEABLE. > I still think the idea of my code is the best way to go, however it need > to be adjusted so it is only the current caching which is avoided. > > I wondered why the code was made like that and began to look further. I > found that the comments in the code do not match the behaviour. > imlib_load_image_without_cache and > imlib_load_image_immediately_without_cache in api.c has comments stating > they will load the image "without looking in the cache first", but do > not state it will not be cached for further use. > As far as I can see, these functions WILL use the cache, if the cache is > valid. However, they will not cache what they load. Also they will set > the F_UNCACHEABLE flag. > As I have not had time to look further into it, I am not sure if the > intention here is what the comments states or what the code do.
How about this one: Index: src/lib/image.c =================================================================== --- src/lib/image.c (revision 57702) +++ src/lib/image.c (working copy) @@ -1017,6 +1017,11 @@ im->key = __imlib_FileKey(file); } im->moddate = __imlib_FileModDate(file); + /* If we can not validate the timestamp, make sure it is always old. */ + if (im->moddate >= time(NULL)) + { + im->moddate = 0; + } /* ok - just check all our loaders are up to date */ __imlib_RescanLoaders(); /* take a guess by extension on the best loader to use */ This will only influence the situation when checking cache by using imlib_image_set_changes_on_disk() and further will only influence the next check, which will lead to a reload. ------------------------------------------------------------------------------ Colocation vs. Managed Hosting A question and answer guide to determining the best fit for your organization - today and in the future. http://p.sf.net/sfu/internap-sfd2d _______________________________________________ enlightenment-devel mailing list enlightenment-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/enlightenment-devel