diff --git a/legacy/evas/ChangeLog b/legacy/evas/ChangeLog index 37b78b910e..4c81a79d46 100644 --- a/legacy/evas/ChangeLog +++ b/legacy/evas/ChangeLog @@ -179,3 +179,11 @@ 2011-03-18 Jiyoun Park * Fix wrong call to free when using mempool for Evas_Object. + +2011-03-19 Carsten Haitzler (The Rasterman) + + * Caching and timestamp checker for image files made much more + pedantic and it checks not just modified timestamp but also + inode number, size, and on linux, the nanonsecond resolution + timestamp as well. + diff --git a/legacy/evas/src/lib/cache/evas_cache_image.c b/legacy/evas/src/lib/cache/evas_cache_image.c index 7998ae36f2..d6ac89aba3 100644 --- a/legacy/evas/src/lib/cache/evas_cache_image.c +++ b/legacy/evas/src/lib/cache/evas_cache_image.c @@ -281,10 +281,41 @@ _evas_cache_image_entry_delete(Evas_Cache_Image *cache, Image_Entry *ie) cache->func.dealloc(ie); } +static Eina_Bool +_timestamp_compare(Image_Timestamp *tstamp, struct stat *st) +{ + if (tstamp->mtime != st->st_mtime) return EINA_FALSE; + if (tstamp->size != st->st_size) return EINA_FALSE; + if (tstamp->ino != st->st_ino) return EINA_FALSE; +#ifdef _STAT_VER_LINUX +#ifdef __USE_MISC + if (tstamp->mtime_nsec != (unsigned long int)st->st_mtim.tv_nsec) return EINA_FALSE; +#else + if (tstamp->mtime_nsec != (unsigned long int)st->st_mtimensec) return EINA_FALSE; +#endif +#endif + return EINA_TRUE; +} + +static void +_timestamp_build(Image_Timestamp *tstamp, struct stat *st) +{ + tstamp->mtime = st->st_mtime; + tstamp->size = st->st_size; + tstamp->ino = st->st_ino; +#ifdef _STAT_VER_LINUX +#ifdef __USE_MISC + tstamp->mtime_nsec = (unsigned long int)st->st_mtim.tv_nsec; +#else + tstamp->mtime_nsec = (unsigned long int)st->st_mtimensec; +#endif +#endif +} + static Image_Entry * _evas_cache_image_entry_new(Evas_Cache_Image *cache, const char *hkey, - time_t timestamp, + Image_Timestamp *tstamp, const char *file, const char *key, RGBA_Image_Loadopts *lo, @@ -322,8 +353,8 @@ _evas_cache_image_entry_new(Evas_Cache_Image *cache, ie->file = file ? eina_stringshare_add(file) : NULL; ie->key = key ? eina_stringshare_add(key) : NULL; - ie->timestamp = timestamp; - ie->laststat = time(NULL); + if (tstamp) ie->tstamp = *tstamp; + else memset(&ie->tstamp, 0, sizeof(Image_Timestamp)); ie->load_opts.scale_down_by = 0; ie->load_opts.dpi = 0; @@ -738,8 +769,6 @@ evas_cache_image_shutdown(Evas_Cache_Image *cache) free(cache); } -#define STAT_GAP 2 - EAPI Image_Entry * evas_cache_image_request(Evas_Cache_Image *cache, const char *file, const char *key, RGBA_Image_Loadopts *lo, int *error) { @@ -752,6 +781,7 @@ evas_cache_image_request(Evas_Cache_Image *cache, const char *file, const char * size_t file_length; size_t key_length; struct stat st; + Image_Timestamp tstamp; assert(cache != NULL); @@ -845,18 +875,12 @@ evas_cache_image_request(Evas_Cache_Image *cache, const char *file, const char * #endif if (im) { - time_t t; - int ok; - - ok = 1; - t = time(NULL); - if ((t - im->laststat) > STAT_GAP) + int ok = 1; + + stat_done = 1; + if (stat(file, &st) < 0) goto on_stat_error; { - stat_done = 1; - if (stat(file, &st) < 0) goto on_stat_error; - - im->laststat = t; - if (st.st_mtime != im->timestamp) ok = 0; + if (!_timestamp_compare(&(im->tstamp), &st)) ok = 0; } if (ok) goto on_ok; @@ -873,25 +897,16 @@ evas_cache_image_request(Evas_Cache_Image *cache, const char *file, const char * #endif if (im) { - int ok; + int ok = 1; - ok = 1; if (!stat_done) { - time_t t; - - t = time(NULL); - if ((t - im->laststat) > STAT_GAP) - { - stat_done = 1; - if (stat(file, &st) < 0) goto on_stat_error; - - im->laststat = t; - if (st.st_mtime != im->timestamp) ok = 0; - } + stat_done = 1; + if (stat(file, &st) < 0) goto on_stat_error; + if (!_timestamp_compare(&(im->tstamp), &st)) ok = 0; } else - if (st.st_mtime != im->timestamp) ok = 0; + if (!_timestamp_compare(&(im->tstamp), &st)) ok = 0; if (ok) { @@ -907,8 +922,8 @@ evas_cache_image_request(Evas_Cache_Image *cache, const char *file, const char * { if (stat(file, &st) < 0) goto on_stat_error; } - - im = _evas_cache_image_entry_new(cache, hkey, st.st_mtime, file, key, lo, error); + _timestamp_build(&tstamp, &st); + im = _evas_cache_image_entry_new(cache, hkey, &tstamp, file, key, lo, error); if (!im) return NULL; if (cache->func.debug) @@ -1071,18 +1086,6 @@ evas_cache_image_dirty(Image_Entry *im, unsigned int x, unsigned int y, unsigned error = cache->func.dirty(im_dirty, im); if (cache->func.debug) cache->func.debug("dirty-out", im_dirty); -/* - im_dirty = _evas_cache_image_entry_new(cache, NULL, im->timestamp, im->file, im->key, &im->load_opts, &error); - if (!im_dirty) goto on_error; - - if (cache->func.debug) - cache->func.debug("dirty-src", im); - error = cache->func.dirty(im_dirty, im); - if (cache->func.debug) - cache->func.debug("dirty-out", im_dirty); - - if (error != 0) goto on_error; - */ #ifdef EVAS_FRAME_QUEUING LKL(im_dirty->lock_references); #endif @@ -1153,18 +1156,6 @@ evas_cache_image_alone(Image_Entry *im) error = cache->func.dirty(im_dirty, im); if (cache->func.debug) cache->func.debug("dirty-out", im_dirty); -/* - im_dirty = _evas_cache_image_entry_new(cache, NULL, im->timestamp, im->file, im->key, &im->load_opts, &error); - if (!im_dirty) goto on_error; - - if (cache->func.debug) - cache->func.debug("dirty-src", im); - error = cache->func.dirty(im_dirty, im); - if (cache->func.debug) - cache->func.debug("dirty-out", im_dirty); - - if (error != 0) goto on_error; - */ #ifdef EVAS_FRAME_QUEUING LKL(im_dirty->lock_references); #endif @@ -1195,7 +1186,7 @@ evas_cache_image_copied_data(Evas_Cache_Image *cache, unsigned int w, unsigned i (cspace == EVAS_COLORSPACE_YCBCR422P709_PL)) w &= ~0x1; - im = _evas_cache_image_entry_new(cache, NULL, 0, NULL, NULL, NULL, NULL); + im = _evas_cache_image_entry_new(cache, NULL, NULL, NULL, NULL, NULL, NULL); if (!im) return NULL; im->space = cspace; @@ -1232,7 +1223,7 @@ evas_cache_image_data(Evas_Cache_Image *cache, unsigned int w, unsigned int h, D (cspace == EVAS_COLORSPACE_YCBCR422P709_PL)) w &= ~0x1; - im = _evas_cache_image_entry_new(cache, NULL, 0, NULL, NULL, NULL, NULL); + im = _evas_cache_image_entry_new(cache, NULL, NULL, NULL, NULL, NULL, NULL); im->w = w; im->h = h; im->flags.alpha = alpha; @@ -1301,7 +1292,7 @@ evas_cache_image_size_set(Image_Entry *im, unsigned int w, unsigned int h) cache = im->cache; - new = _evas_cache_image_entry_new(cache, NULL, 0, NULL, NULL, NULL, &error); + new = _evas_cache_image_entry_new(cache, NULL, NULL, NULL, NULL, NULL, &error); if (!new) goto on_error; new->flags.alpha = im->flags.alpha; @@ -1552,7 +1543,7 @@ evas_cache_image_empty(Evas_Cache_Image *cache) { Image_Entry *im; - im = _evas_cache_image_entry_new(cache, NULL, 0, NULL, NULL, NULL, NULL); + im = _evas_cache_image_entry_new(cache, NULL, NULL, NULL, NULL, NULL, NULL); if (!im) return NULL; #ifdef EVAS_FRAME_QUEUING diff --git a/legacy/evas/src/lib/include/evas_common.h b/legacy/evas/src/lib/include/evas_common.h index 81849a6966..b84c1aa5ac 100644 --- a/legacy/evas/src/lib/include/evas_common.h +++ b/legacy/evas/src/lib/include/evas_common.h @@ -12,6 +12,10 @@ #include #include "Evas.h" +#include +#include +#include + /* macros needed to log message through eina_log */ extern EAPI int _evas_log_dom_global; #ifdef _EVAS_DEFAULT_LOG_DOM @@ -395,6 +399,7 @@ typedef unsigned char DATA8; typedef struct _Image_Entry Image_Entry; typedef struct _Image_Entry_Flags Image_Entry_Flags; +typedef struct _Image_Timestamp Image_Timestamp; typedef struct _Engine_Image_Entry Engine_Image_Entry; typedef struct _Evas_Cache_Target Evas_Cache_Target; typedef struct _Evas_Preload_Pthread Evas_Preload_Pthread; @@ -541,6 +546,16 @@ struct _Evas_Cache_Target void *data; }; +struct _Image_Timestamp +{ + time_t mtime; + off_t size; + ino_t ino; +#ifdef _STAT_VER_LINUX + unsigned long int mtime_nsec; +#endif +}; + struct _Image_Entry { EINA_INLIST; @@ -553,10 +568,9 @@ struct _Image_Entry const char *key; Evas_Cache_Target *targets; - Evas_Preload_Pthread *preload; + Evas_Preload_Pthread *preload; - time_t timestamp; - time_t laststat; + Image_Timestamp tstamp; int references; #ifdef EVAS_FRAME_QUEUING