evas cache system more pedantic about matches and statting.
authorraster <raster@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Sat, 19 Mar 2011 07:08:59 +0000 (07:08 +0000)
committerraster <raster@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Sat, 19 Mar 2011 07:08:59 +0000 (07:08 +0000)
git-svn-id: http://svn.enlightenment.org/svn/e/trunk/evas@57890 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

ChangeLog
src/lib/cache/evas_cache_image.c
src/lib/include/evas_common.h

index 37b78b9..4c81a79 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
 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.
+
index 7998ae3..d6ac89a 100644 (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
index 81849a6..b84c1aa 100644 (file)
 #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