On Sat, 12 Mar 2011 13:36:07 +0100, Jesper Saxtorph  
<jesper.saxto...@prevas.dk> wrote:

> 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.
>
This still makes files with a future time stamp uncached when using  
imlib_image_set_changes_on_disk().

What was wrong with my suggestion?

/Kim

------------------------------------------------------------------------------
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

Reply via email to