Add LRU to mime icons cache.
authorbarbieri <barbieri@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Tue, 3 Mar 2009 22:38:21 +0000 (22:38 +0000)
committerbarbieri <barbieri@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Tue, 3 Mar 2009 22:38:21 +0000 (22:38 +0000)
This should really remove unused items that would age forever in the
last, forcing old but not so to be evicted before them.

Fortunately it was not so complex to add, and should wait just 3
pointers more of space per node.

git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/efreet@39350 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

src/lib/efreet_mime.c

index 2868802..412229d 100644 (file)
@@ -13,6 +13,7 @@ static Eina_List *magics = NULL;    /* contains Efreet_Mime_Magic structs */
 static Eina_Hash *wild = NULL;      /* contains *.ext and mime.types globs*/
 static Eina_Hash *monitors = NULL;  /* contains file monitors */
 static Eina_Hash *mime_icons = NULL; /* contains cache with mime->icons */
+static Eina_Inlist *mime_icons_lru = NULL;
 static unsigned int _init_count = 0;
 
 /**
@@ -95,6 +96,7 @@ struct Efreet_Mime_Magic_Entry
 typedef struct Efreet_Mime_Icon_Entry_Head Efreet_Mime_Icon_Entry_Head;
 struct Efreet_Mime_Icon_Entry_Head
 {
+    EINA_INLIST; /* node of mime_icons_lru */
     Eina_Inlist *list;
     const char *mime;
     time_t timestamp;
@@ -318,7 +320,10 @@ EAPI void
 efreet_mime_type_cache_clear(void)
 {
     if (mime_icons)
+    {
         eina_hash_free(mime_icons);
+        mime_icons_lru = NULL;
+    }
     mime_icons = eina_hash_pointer_new(EINA_FREE_CB(efreet_mime_icon_entry_head_free));
 }
 
@@ -1327,53 +1332,31 @@ efreet_mime_glob_case_match(char *str, const char *glob)
     return 0;
 }
 
-struct Efreet_Mime_Icons_Flush_Data
-{
-    time_t now;
-    int todo;
-    Eina_List *removal;
-};
-
-static Eina_Bool
-efreet_mime_icons_flush_cb(const Eina_Hash *hash __UNUSED__,
-                           const void *key __UNUSED__,
-                           void *data,
-                           void *fdata)
-{
-    struct Efreet_Mime_Icons_Flush_Data *d = fdata;
-    Efreet_Mime_Icon_Entry_Head *entry = data;
-
-    if (d->now - entry->timestamp < EFREET_MIME_ICONS_EXPIRE_TIMEOUT)
-        return 1;
-
-    d->removal = eina_list_append(d->removal, entry->mime);
-    d->todo--;
-
-    return d->todo > 0;
-}
-
 static void
 efreet_mime_icons_flush(time_t now)
 {
-    struct Efreet_Mime_Icons_Flush_Data data;
+    Eina_Inlist *l;
     static time_t old = 0;
     int todo;
-    const char *key;
 
     if (now - old < EFREET_MIME_ICONS_FLUSH_TIMEOUT)
         return;
+    old = now;
 
     todo = eina_hash_population(mime_icons) - EFREET_MIME_ICONS_MAX_POPULATION;
     if (todo <= 0)
         return;
 
-    data.now = now;
-    data.todo = todo;
-    data.removal = NULL;
-    eina_hash_foreach(mime_icons, efreet_mime_icons_flush_cb, &data);
+    l = mime_icons_lru->last; /* mime_icons_lru is not NULL, since todo > 0 */
+    for (; todo > 0; todo--)
+    {
+        Efreet_Mime_Icon_Entry_Head *entry = (Efreet_Mime_Icon_Entry_Head *)l;
+        Eina_Inlist *prev = l->prev;
 
-    EINA_LIST_FREE(data.removal, key)
-        eina_hash_del_by_key(mime_icons, key);
+        mime_icons_lru = eina_inlist_remove(mime_icons_lru, l);
+        eina_hash_del_by_key(mime_icons, entry->mime);
+        l = prev;
+    }
 
     efreet_mime_icons_debug();
 }
@@ -1433,18 +1416,33 @@ efreet_mime_icon_entry_add(const char *mime,
     entry = eina_hash_find(mime_icons, mime);
 
     if (entry)
-        entry->list = eina_inlist_prepend(entry->list, EINA_INLIST_GET(n));
+    {
+        Eina_Inlist *l;
+
+        l = EINA_INLIST_GET(n);
+        entry->list = eina_inlist_prepend(entry->list, l);
+
+        l = EINA_INLIST_GET(entry);
+        mime_icons_lru = eina_inlist_promote(mime_icons_lru, l);
+    }
     else
     {
+        Eina_Inlist *l;
+
         entry = malloc(sizeof(*entry));
         if (!entry)
         {
             efreet_mime_icon_entry_free(n);
             return;
         }
-        entry->list = eina_inlist_prepend(NULL, EINA_INLIST_GET(n));
+
+        l = EINA_INLIST_GET(n);
+        entry->list = eina_inlist_prepend(NULL, l);
         entry->mime = mime;
         eina_hash_direct_add(mime_icons, mime, entry);
+
+        l = EINA_INLIST_GET(entry);
+        mime_icons_lru = eina_inlist_prepend(mime_icons_lru, l);
     }
 
     entry->timestamp = (time_t)ecore_loop_time_get();
@@ -1467,9 +1465,16 @@ efreet_mime_icon_entry_find(const char *mime,
     {
         if ((n->theme == theme) && (n->size == size))
         {
-            Eina_Inlist *l = EINA_INLIST_GET(n);
+            Eina_Inlist *l;
+
+            l = EINA_INLIST_GET(n);
             if (entry->list != l)
                 entry->list = eina_inlist_promote(entry->list, l);
+
+            l = EINA_INLIST_GET(entry);
+            if (mime_icons_lru != l)
+                mime_icons_lru = eina_inlist_promote(mime_icons_lru, l);
+
             entry->timestamp = (time_t)ecore_loop_time_get();
             return n->icon;
         }
@@ -1479,29 +1484,29 @@ efreet_mime_icon_entry_find(const char *mime,
 }
 
 #ifdef EFREET_MIME_ICONS_DEBUG
-static Eina_Bool
-efreet_mime_icons_debug_cb(const Eina_Hash *hash __UNUSED__,
-                           const void *key __UNUSED__,
-                           void *data,
-                           void *fdata __UNUSED__)
+static void
+efreet_mime_icons_debug(void)
 {
-    Efreet_Mime_Icon_Entry_Head *entry = data;
-    Efreet_Mime_Icon_Entry *n;
-
-    printf("mime-icon entry: '%s' last used: %s",
-           entry->mime, ctime(&entry->timestamp));
+    time_t now = (time_t)ecore_loop_time_get();
+    Efreet_Mime_Icon_Entry_Head *entry;
+    EINA_INLIST_FOREACH(mime_icons_lru, entry)
+    {
+        Efreet_Mime_Icon_Entry *n;
 
-    EINA_INLIST_FOREACH(entry->list, n)
-           printf("\tsize: %3u theme: '%s' icon: '%s'\n",
-                  n->theme, n->size, n->icon);
+        if ((now > 0) &&
+            (now - entry->timestamp >= EFREET_MIME_ICONS_EXPIRE_TIMEOUT))
+        {
+            puts("*** FOLLOWING ENTRIES ARE AGED AND CAN BE EXPIRED ***");
+            now = 0;
+        }
 
-    return 1;
-}
+        printf("mime-icon entry: '%s' last used: %s",
+               entry->mime, ctime(&entry->timestamp));
 
-static void
-efreet_mime_icons_debug(void)
-{
-    eina_hash_foreach(mime_icons, efreet_mime_icons_debug_cb, NULL);
+        EINA_INLIST_FOREACH(entry->list, n)
+            printf("\tsize: %3u theme: '%s' icon: '%s'\n",
+                   n->theme, n->size, n->icon);
+    }
 }
 #else
 static void