evas cache system more pedantic about matches and statting.

SVN revision: 57890
This commit is contained in:
Carsten Haitzler 2011-03-19 07:08:59 +00:00
parent 6fe0efadd5
commit cc58ee1e6a
3 changed files with 76 additions and 63 deletions

View File

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

View File

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

View File

@ -12,6 +12,10 @@
#include <Eina.h>
#include "Evas.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
/* 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