From 7db2cb388cb5d7df4768f6a25a1b02153c192cb2 Mon Sep 17 00:00:00 2001 From: Cedric BAIL Date: Mon, 29 Nov 2010 13:17:33 +0000 Subject: [PATCH] * efreet: improve speed of cache regeneration. SVN revision: 55060 --- .../efreet/src/bin/efreet_icon_cache_create.c | 114 +++++++++++++----- .../efreet/src/bin/efreet_icon_cache_dump.c | 2 +- legacy/efreet/src/lib/efreet_cache.c | 94 ++++++++------- legacy/efreet/src/lib/efreet_cache_private.h | 4 +- legacy/efreet/src/lib/efreet_private.h | 13 +- 5 files changed, 141 insertions(+), 86 deletions(-) diff --git a/legacy/efreet/src/bin/efreet_icon_cache_create.c b/legacy/efreet/src/bin/efreet_icon_cache_create.c index a0bd302953..5a17727dae 100644 --- a/legacy/efreet/src/bin/efreet_icon_cache_create.c +++ b/legacy/efreet/src/bin/efreet_icon_cache_create.c @@ -21,9 +21,37 @@ #include "efreet_cache_private.h" static const char *exts[] = { ".png", ".xpm", ".svg", NULL }; - +static Eina_Array *strs = NULL; static int verbose = 0; +static void +_cache_directory_free(void *dcache) +{ + free(dcache); +} + +static Eina_Bool +cache_directory_find(Eina_Hash *dirs, const char *dir) +{ + Efreet_Cache_Directory *dcache; + struct stat st; + + if (stat(dir, &st)) return EINA_FALSE; + dcache = eina_hash_find(dirs, dir); + if (!dcache) + { + dcache = malloc(sizeof (Efreet_Cache_Directory)); + if (!dcache) return 1; + + dcache->modified_time = (long long) st.st_mtime; + eina_hash_add(dirs, dir, dcache); + } + else if (dcache->modified_time == (long long) st.st_mtime) return EINA_FALSE; + dcache->modified_time = st.st_mtime; + + return EINA_TRUE; +} + static Eina_Bool _cache_extention_lookup(const char *ext) { @@ -41,8 +69,7 @@ cache_fallback_scan_dir(Eina_Hash *icons, Eina_Hash *dirs, const char *dir, Eina Eina_Iterator *it; Eina_File_Direct_Info *entry; - if (eina_hash_find(dirs, dir)) return 1; - eina_hash_add(dirs, dir, (void *)-1); + if (!cache_directory_find(dirs, dir)) return 1; it = eina_file_stat_ls(dir); if (!it) return 1; @@ -69,7 +96,6 @@ cache_fallback_scan_dir(Eina_Hash *icons, Eina_Hash *dirs, const char *dir, Eina if (!icon) { icon = NEW(Efreet_Cache_Fallback_Icon, 1); - icon->free = 1; icon->theme = NULL; eina_hash_add(icons, name, icon); } @@ -85,7 +111,8 @@ cache_fallback_scan_dir(Eina_Hash *icons, Eina_Hash *dirs, const char *dir, Eina /* we don't really track path deat here, so we will leak... */ icon->icons = realloc(icon->icons, sizeof (char *) * (icon->icons_count + 1)); - icon->icons[icon->icons_count++] = eina_stringshare_add(entry->path); + icon->icons[icon->icons_count] = eina_stringshare_add(entry->path); + eina_array_push(strs, icon->icons[icon->icons_count++]); *changed = EINA_TRUE; } @@ -96,14 +123,11 @@ cache_fallback_scan_dir(Eina_Hash *icons, Eina_Hash *dirs, const char *dir, Eina } static Eina_Bool -cache_fallback_scan(Eina_Hash *icons, Eina_Bool *changed) +cache_fallback_scan(Eina_Hash *icons, Eina_Hash *dirs, Eina_Bool *changed) { Eina_List *xdg_dirs, *l; const char *dir; char path[PATH_MAX]; - Eina_Hash *dirs; - - dirs = eina_hash_string_superfast_new(NULL); cache_fallback_scan_dir(icons, dirs, efreet_icon_deprecated_user_dir_get(), changed); cache_fallback_scan_dir(icons, dirs, efreet_icon_user_dir_get(), changed); @@ -125,7 +149,6 @@ cache_fallback_scan(Eina_Hash *icons, Eina_Bool *changed) cache_fallback_scan_dir(icons, dirs, "/usr/share/pixmaps", changed); - eina_hash_free(dirs); return 1; } @@ -134,6 +157,7 @@ cache_scan_path_dir(Efreet_Icon_Theme *theme, const char *path, Efreet_Icon_Theme_Directory *dir, Eina_Hash *icons, + Eina_Hash *dirs, Eina_Bool *changed) { Eina_Iterator *it; @@ -142,6 +166,9 @@ cache_scan_path_dir(Efreet_Icon_Theme *theme, snprintf(buf, sizeof(buf), "%s/%s", path, dir->name); + if (!cache_directory_find(dirs, buf)) + return 1; + it = eina_file_stat_ls(buf); if (!it) return 1; @@ -167,8 +194,8 @@ cache_scan_path_dir(Efreet_Icon_Theme *theme, if (!icon) { icon = NEW(Efreet_Cache_Icon, 1); - icon->free = 1; icon->theme = eina_stringshare_add(theme->name.internal); + eina_array_push(strs, icon->theme); eina_hash_add(icons, name, icon); } else if (icon->theme && strcmp(icon->theme, theme->name.internal)) @@ -218,7 +245,8 @@ cache_scan_path_dir(Efreet_Icon_Theme *theme, /* and finally store the path */ icon->icons[i]->paths = realloc(icon->icons[i]->paths, sizeof (char*) * (icon->icons[i]->paths_count + 1)); - icon->icons[i]->paths[icon->icons[i]->paths_count++] = eina_stringshare_add(entry->path); + icon->icons[i]->paths[icon->icons[i]->paths_count] = eina_stringshare_add(entry->path); + eina_array_push(strs, icon->icons[i]->paths[icon->icons[i]->paths_count++]); *changed = EINA_TRUE; } @@ -229,19 +257,19 @@ cache_scan_path_dir(Efreet_Icon_Theme *theme, } static int -cache_scan_path(Efreet_Icon_Theme *theme, Eina_Hash *icons, const char *path, Eina_Bool *changed) +cache_scan_path(Efreet_Icon_Theme *theme, Eina_Hash *icons, Eina_Hash *dirs, const char *path, Eina_Bool *changed) { Eina_List *l; Efreet_Icon_Theme_Directory *dir; EINA_LIST_FOREACH(theme->directories, l, dir) - if (!cache_scan_path_dir(theme, path, dir, icons, changed)) return 0; + if (!cache_scan_path_dir(theme, path, dir, icons, dirs, changed)) return 0; return 1; } static Eina_Bool -cache_scan(Efreet_Icon_Theme *theme, Eina_Hash *themes, Eina_Hash *icons, Eina_Bool *changed) +cache_scan(Efreet_Icon_Theme *theme, Eina_Hash *themes, Eina_Hash *icons, Eina_Hash *dirs, Eina_Bool *changed) { Eina_List *l; const char *path; @@ -253,7 +281,7 @@ cache_scan(Efreet_Icon_Theme *theme, Eina_Hash *themes, Eina_Hash *icons, Eina_B /* scan theme */ EINA_LIST_FOREACH(theme->paths, l, path) - if (!cache_scan_path(theme, icons, path, changed)) return 0; + if (!cache_scan_path(theme, icons, dirs, path, changed)) return 0; /* scan inherits */ if (theme->inherits) @@ -265,13 +293,13 @@ cache_scan(Efreet_Icon_Theme *theme, Eina_Hash *themes, Eina_Hash *icons, Eina_B inherit = efreet_icon_theme_find(name); if (!inherit) fprintf(stderr, "Theme `%s` not found for `%s`.\n", name, theme->name.internal); - if (!cache_scan(inherit, themes, icons, changed)) return 0; + if (!cache_scan(inherit, themes, icons, dirs, changed)) return 0; } } else if (strcmp(theme->name.internal, "hicolor")) { theme = efreet_icon_theme_find("hicolor"); - if (!cache_scan(theme, themes, icons, changed)) return 0; + if (!cache_scan(theme, themes, icons, dirs, changed)) return 0; } return 1; @@ -336,6 +364,7 @@ main(int argc, char **argv) Eet_File *ef; Eina_List *l = NULL; char file[PATH_MAX]; + const char *path; char *dir = NULL; Eina_Bool changed = EINA_FALSE; int lockfd = -1; @@ -361,6 +390,7 @@ main(int argc, char **argv) if (!ecore_init()) return -1; efreet_cache_update = 0; + strs = eina_array_new(32); /* FIXME: should be in cache dir maybe */ /* create homedir */ @@ -395,7 +425,7 @@ main(int argc, char **argv) ef = eet_open(efreet_icon_cache_file(), EET_FILE_MODE_READ_WRITE); if (!ef) goto on_error_efreet; - edd = efreet_icon_theme_edd(); + edd = efreet_icon_theme_edd(EINA_TRUE); EINA_LIST_FREE(l, theme) { @@ -407,11 +437,12 @@ main(int argc, char **argv) cache = eet_data_read(ef, edd, theme->name.internal); /* Wype out in case of version change */ - if (cache - && cache->version.major != EFREET_CACHE_MAJOR - && cache->version.minor != EFREET_CACHE_MINOR) + if (cache && + (cache->version.major != EFREET_CACHE_MAJOR + || cache->version.minor != EFREET_CACHE_MINOR)) { eina_hash_free(cache->icons); + eina_hash_free(cache->dirs); free(cache); cache = NULL; } @@ -419,18 +450,22 @@ main(int argc, char **argv) /* No existing cache before, so create it */ if (!cache) { - cache = malloc(sizeof (Efreet_Cache_Theme)); + cache = calloc(1, sizeof (Efreet_Cache_Theme)); if (!cache) goto on_error_efreet; cache->version.major = EFREET_CACHE_MAJOR; cache->version.minor = EFREET_CACHE_MINOR; - cache->icons = eina_hash_string_superfast_new((Eina_Free_Cb) efreet_cache_icon_free); - changed = EINA_TRUE; } - if (cache_scan(theme, themes, cache->icons, &changed)) + if (!cache->icons) + cache->icons = eina_hash_string_superfast_new((Eina_Free_Cb) efreet_cache_icon_fallback_free); + + if (!cache->dirs) + cache->dirs = eina_hash_string_superfast_new(_cache_directory_free); + + if (cache_scan(theme, themes, cache->icons, cache->dirs, &changed)) { fprintf(stderr, "generated: '%s' %i (%i)\n", theme->name.internal, @@ -443,16 +478,20 @@ main(int argc, char **argv) eina_hash_free(themes); eina_hash_free(cache->icons); + eina_hash_free(cache->dirs); free(cache); } - edd = efreet_icon_fallback_edd(); + edd = efreet_icon_fallback_edd(EINA_TRUE); /* read fallback icons from the eet file */ cache = eet_data_read(ef, edd, "efreet/fallback"); - if (cache && cache->version.major != EFREET_CACHE_MAJOR) + if (cache && + (cache->version.major != EFREET_CACHE_MAJOR + || cache->version.minor != EFREET_CACHE_MINOR)) { - eina_hash_free(cache->icons); + if (cache->icons) eina_hash_free(cache->icons); + if (cache->dirs) eina_hash_free(cache->dirs); free(cache); cache = NULL; } @@ -460,19 +499,23 @@ main(int argc, char **argv) /* No existing fallback, create it */ if (!cache) { - cache = malloc(sizeof (Efreet_Cache_Theme)); + cache = calloc(1, sizeof (Efreet_Cache_Theme)); if (!cache) goto on_error_efreet; cache->version.major = EFREET_CACHE_MAJOR; cache->version.minor = EFREET_CACHE_MINOR; - cache->icons = eina_hash_string_superfast_new((Eina_Free_Cb) efreet_cache_icon_fallback_free); - changed = EINA_TRUE; } + if (!cache->icons) + cache->icons = eina_hash_string_superfast_new((Eina_Free_Cb) efreet_cache_icon_fallback_free); + + if (!cache->dirs) + cache->dirs = eina_hash_string_superfast_new(_cache_directory_free); + /* Save fallback in the right part */ - if (cache_fallback_scan(cache->icons, &changed)) + if (cache_fallback_scan(cache->icons, cache->dirs, &changed)) { fprintf(stderr, "generated: fallback %i (%i)\n", changed, eina_hash_population(cache->icons)); if (changed) @@ -480,6 +523,7 @@ main(int argc, char **argv) } eina_hash_free(cache->icons); + eina_hash_free(cache->dirs); free(cache); /* save data */ @@ -491,6 +535,10 @@ on_error_efreet: on_error: close(lockfd); + while ((path = eina_array_pop(strs))) + eina_stringshare_del(path); + eina_array_free(strs); + ecore_shutdown(); eet_shutdown(); eina_shutdown(); diff --git a/legacy/efreet/src/bin/efreet_icon_cache_dump.c b/legacy/efreet/src/bin/efreet_icon_cache_dump.c index b5d2338b38..31cb934b72 100644 --- a/legacy/efreet/src/bin/efreet_icon_cache_dump.c +++ b/legacy/efreet/src/bin/efreet_icon_cache_dump.c @@ -78,7 +78,7 @@ main(int argc, char **argv) if (!efreet_init()) return -1; - edd = efreet_icon_theme_edd(); + edd = efreet_icon_theme_edd(EINA_FALSE); if (!edd) return -1; if (argc > 1) diff --git a/legacy/efreet/src/lib/efreet_cache.c b/legacy/efreet/src/lib/efreet_cache.c index d154ac30a7..809fddf04f 100644 --- a/legacy/efreet/src/lib/efreet_cache.c +++ b/legacy/efreet/src/lib/efreet_cache.c @@ -33,6 +33,7 @@ static int _efreet_cache_log_dom = -1; * Data for cache files */ #ifdef ICON_CACHE +static Eet_Data_Descriptor *directory_edd = NULL; static Eet_Data_Descriptor *cache_theme_edd = NULL; static Eet_Data_Descriptor *cache_fallback_edd = NULL; @@ -69,6 +70,7 @@ static Eina_List *old_desktop_caches = NULL; #ifdef ICON_CACHE static void efreet_icon_edd_shutdown(void); +static Efreet_Cache_Theme *_efreet_cache_free(Efreet_Cache_Theme *cache); #endif static void efreet_desktop_edd_shutdown(void); @@ -142,23 +144,12 @@ efreet_cache_shutdown(void) Efreet_Old_Cache *d; #ifdef ICON_CACHE - if (theme_cache) - { - eina_hash_free(theme_cache->icons); - free(theme_cache); - theme_cache = NULL; - } + theme_cache = _efreet_cache_free(theme_cache); + fallback_cache = _efreet_cache_free(fallback_cache); if (theme_name) eina_stringshare_del(theme_name); theme_name = NULL; - if (fallback_cache) - { - eina_hash_free(fallback_cache->icons); - free(fallback_cache); - fallback_cache = NULL; - } - if (cache) eet_close(cache); cache = NULL; #endif @@ -287,6 +278,18 @@ efreet_desktop_cache_dirs(void) "pointer", pointer, Edd_Source); \ } +static Efreet_Cache_Theme * +_efreet_cache_free(Efreet_Cache_Theme *c) +{ + if (!c) return NULL; + + if (c->icons) eina_hash_free(c->icons); + if (c->dirs) eina_hash_free(c->dirs); + free(c); + + return NULL; +} + static void * _efreet_icon_hash_add(void *h, const char *key, void *d) { @@ -300,11 +303,28 @@ _efreet_icon_hash_add(void *h, const char *key, void *d) return hash; } +static Eet_Data_Descriptor * +efreet_icon_directory_edd(void) +{ + Eet_Data_Descriptor_Class eddc; + + if (directory_edd) return directory_edd; + + EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Efreet_Cache_Directory); + directory_edd = eet_data_descriptor_file_new(&eddc); + if (!directory_edd) return NULL; + + EET_DATA_DESCRIPTOR_ADD_BASIC(directory_edd, Efreet_Cache_Directory, + "modified_time", modified_time, EET_T_LONG_LONG); + + return directory_edd; +} + /* * Needs EAPI because of helper binaries */ EAPI Eet_Data_Descriptor * -efreet_icon_theme_edd(void) +efreet_icon_theme_edd(Eina_Bool include_dirs) { Eet_Data_Descriptor_Class eddc; @@ -350,6 +370,10 @@ efreet_icon_theme_edd(void) EET_DATA_DESCRIPTOR_ADD_HASH(cache_theme_edd, Efreet_Cache_Theme, "icons", icons, icon_edd); + if (include_dirs) + EET_DATA_DESCRIPTOR_ADD_HASH(cache_theme_edd, Efreet_Cache_Theme, + "dirs", dirs, efreet_icon_directory_edd()); + return cache_theme_edd; } @@ -370,7 +394,7 @@ _efreet_icon_fallback_hash_add(void *h, const char *key, void *d) * Needs EAPI because of helper binaries */ EAPI Eet_Data_Descriptor * -efreet_icon_fallback_edd(void) +efreet_icon_fallback_edd(Eina_Bool include_dirs) { Eet_Data_Descriptor_Class eddc; Eet_Data_Descriptor *icon_fallback_edd; @@ -396,6 +420,10 @@ efreet_icon_fallback_edd(void) EET_DATA_DESCRIPTOR_ADD_HASH(cache_fallback_edd, Efreet_Cache_Theme, "icons", icons, icon_fallback_edd); + if (include_dirs) + EET_DATA_DESCRIPTOR_ADD_HASH(cache_theme_edd, Efreet_Cache_Theme, + "dirs", dirs, efreet_icon_directory_edd()); + return cache_fallback_edd; } @@ -408,6 +436,7 @@ efreet_icon_edd_shutdown(void) { EDD_SHUTDOWN(cache_fallback_edd); EDD_SHUTDOWN(cache_theme_edd); + EDD_SHUTDOWN(directory_edd); EDD_SHUTDOWN(icon_element_pointer_edd); EDD_SHUTDOWN(icon_element_edd); EDD_SHUTDOWN(icon_edd); @@ -472,19 +501,6 @@ efreet_cache_icon_free(Efreet_Cache_Icon *icon) if (!icon) return; - if (icon->free) - { - unsigned int j; - - eina_stringshare_del(icon->theme); - - for (i = 0; i < icon->icons_count; ++i) - { - for (j = 0; j < icon->icons[i]->paths_count; ++j) - eina_stringshare_del(icon->icons[i]->paths[j]); - } - } - for (i = 0; i < icon->icons_count; ++i) { free(icon->icons[i]->paths); @@ -498,14 +514,8 @@ efreet_cache_icon_free(Efreet_Cache_Icon *icon) EAPI void efreet_cache_icon_fallback_free(Efreet_Cache_Fallback_Icon *icon) { - unsigned int i; - if (!icon) return ; - if (icon->free) - for (i = 0; i < icon->icons_count; ++i) - eina_stringshare_del(icon->icons[i]); - free(icon->icons); free(icon); } @@ -520,17 +530,15 @@ efreet_cache_icon_find(Efreet_Icon_Theme *theme, const char *icon) { /* FIXME: this is bad if people have pointer to this cache, things will go wrong */ INFO("theme_name change from `%s` to `%s`", theme_name, theme->name.internal); - eina_hash_free(theme_cache->icons); - free(theme_cache); eina_stringshare_del(theme_name); - theme_cache = NULL; + theme_cache = _efreet_cache_free(theme_cache); theme_name = NULL; } if (!theme_name) { INFO("loading theme %s", theme->name.internal); - theme_cache = eet_data_read(cache, efreet_icon_theme_edd(), theme->name.internal); + theme_cache = eet_data_read(cache, efreet_icon_theme_edd(EINA_FALSE), theme->name.internal); if (theme_cache && !theme_cache->icons) theme_cache->icons = eina_hash_string_superfast_new((Eina_Free_Cb) efreet_cache_icon_free); if (theme_cache) @@ -551,7 +559,7 @@ efreet_cache_icon_fallback_find(const char *icon) if (!fallback_cache) { INFO("loading fallback cache"); - fallback_cache = eet_data_read(cache, efreet_icon_fallback_edd(), "efreet/fallback"); + fallback_cache = eet_data_read(cache, efreet_icon_fallback_edd(EINA_FALSE), "efreet/fallback"); if (fallback_cache && !fallback_cache->icons) fallback_cache->icons = eina_hash_string_superfast_new((Eina_Free_Cb) efreet_cache_icon_fallback_free); } @@ -697,9 +705,7 @@ cache_update_cb(void *data __UNUSED__, Ecore_File_Monitor *em __UNUSED__, if (theme_cache) { INFO("Destorying theme cache due to cache change."); - eina_hash_free(theme_cache->icons); - free(theme_cache); - theme_cache = NULL; + theme_cache = _efreet_cache_free(theme_cache); } if (theme_name) eina_stringshare_del(theme_name); @@ -708,9 +714,7 @@ cache_update_cb(void *data __UNUSED__, Ecore_File_Monitor *em __UNUSED__, if (fallback_cache) { INFO("Destroying fallback cache due to cache change."); - eina_hash_free(fallback_cache->icons); - free(fallback_cache); - fallback_cache = NULL; + fallback_cache = _efreet_cache_free(fallback_cache); } if (cache) eet_close(cache); diff --git a/legacy/efreet/src/lib/efreet_cache_private.h b/legacy/efreet/src/lib/efreet_cache_private.h index 1a71030f4b..9be712709a 100644 --- a/legacy/efreet/src/lib/efreet_cache_private.h +++ b/legacy/efreet/src/lib/efreet_cache_private.h @@ -3,8 +3,8 @@ EAPI Eet_Data_Descriptor *efreet_desktop_edd_init(void); #ifdef ICON_CACHE -EAPI Eet_Data_Descriptor *efreet_icon_theme_edd(void); -EAPI Eet_Data_Descriptor *efreet_icon_fallback_edd(void); +EAPI Eet_Data_Descriptor *efreet_icon_theme_edd(Eina_Bool include_dirs); +EAPI Eet_Data_Descriptor *efreet_icon_fallback_edd(Eina_Bool include_dirs); #endif #endif diff --git a/legacy/efreet/src/lib/efreet_private.h b/legacy/efreet/src/lib/efreet_private.h index 75a5a37f69..cae33f59ff 100644 --- a/legacy/efreet/src/lib/efreet_private.h +++ b/legacy/efreet/src/lib/efreet_private.h @@ -117,12 +117,13 @@ extern Eina_Hash *efreet_desktop_cache; #ifdef ICON_CACHE #define EFREET_CACHE_MAJOR 0 -#define EFREET_CACHE_MINOR 2 +#define EFREET_CACHE_MINOR 3 typedef struct _Efreet_Cache_Icon_Element Efreet_Cache_Icon_Element; typedef struct _Efreet_Cache_Fallback_Icon Efreet_Cache_Fallback_Icon; typedef struct _Efreet_Cache_Icon Efreet_Cache_Icon; typedef struct _Efreet_Cache_Theme Efreet_Cache_Theme; +typedef struct _Efreet_Cache_Directory Efreet_Cache_Directory; struct _Efreet_Cache_Theme { @@ -132,6 +133,12 @@ struct _Efreet_Cache_Theme } version; Eina_Hash *icons; + Eina_Hash *dirs; +}; + +struct _Efreet_Cache_Directory +{ + long long modified_time; }; struct _Efreet_Cache_Icon @@ -140,8 +147,6 @@ struct _Efreet_Cache_Icon Efreet_Cache_Icon_Element **icons; unsigned int icons_count; - - unsigned char free:1; }; struct _Efreet_Cache_Icon_Element @@ -168,8 +173,6 @@ struct _Efreet_Cache_Fallback_Icon const char **icons; unsigned int icons_count; - - unsigned char free:1; }; #endif