efreet: redo cache rebuild

Always rebuild cache from scratch when needed, but rely on correct spec
behaviour to check for theme changes. This will considerably speed up
the cache process when there is no change, and improve the correctness
of the cache when changes occur. For example didn't the previous
behaviour handle file removal gracefully.

SVN revision: 62505
This commit is contained in:
Sebastian Dransfeld 2011-08-16 12:46:24 +00:00
parent dfa8b5e29f
commit fa2a688b02
2 changed files with 147 additions and 125 deletions

View File

@ -82,6 +82,15 @@
* Use eina_log more effectively
2011-04-04 Tom Hacohen (TAsn)
2011-04-04 Tom Hacohen (TAsn)
* Fixed uri encoding when opening files.
2011-08-16 sebastian Dransfeld
* Always rebuild cache from scratch when needed, but rely on correct
spec behaviour to check for theme changes. This will considerably
speed up the cache process when there is no change, and improve the
correctness of the cache when changes occur. For example didn't the
previous behaviour handle file removal gracefully.

View File

@ -24,11 +24,7 @@ static int _efreet_icon_cache_log_dom = -1;
#include "efreet_cache_private.h"
/* TODO:
* - Need to cache all exts searched and extra_dirs, so we know if we
* need to rescan dirs. Then re-enable cache_directory_find().
* - Need to check if files has disappeared, as we only add new.
* - Base dir is touched on icon theme update, no need to scan all.
* - There is something weird going on with inheritance when adding extensions
* - Need to handle programs using different exts
*/
static Eina_Array *exts = NULL;
@ -37,10 +33,8 @@ static Eina_Array *strs = NULL;
static Eina_Hash *icon_themes = NULL;
static Eina_Bool
cache_directory_find(Eina_Hash *dirs __UNUSED__, const char *dir __UNUSED__)
cache_directory_modified(Eina_Hash *dirs, const char *dir)
{
return EINA_TRUE;
#if 0
Efreet_Cache_Directory *dcache;
struct stat st;
@ -60,7 +54,6 @@ cache_directory_find(Eina_Hash *dirs __UNUSED__, const char *dir __UNUSED__)
dcache->modified_time = st.st_mtime;
return EINA_TRUE;
#endif
}
static Eina_Bool
@ -75,12 +68,12 @@ cache_extension_lookup(const char *ext)
}
static Eina_Bool
cache_fallback_scan_dir(Eina_Hash *icons, Eina_Hash *dirs, const char *dir, Eina_Bool *changed)
cache_fallback_scan_dir(Eina_Hash *icons, Eina_Hash *dirs, const char *dir)
{
Eina_Iterator *it;
Eina_File_Direct_Info *entry;
if (!cache_directory_find(dirs, dir)) return EINA_TRUE;
if (!cache_directory_modified(dirs, dir)) return EINA_TRUE;
it = eina_file_stat_ls(dir);
if (!it) return EINA_TRUE;
@ -123,8 +116,6 @@ cache_fallback_scan_dir(Eina_Hash *icons, Eina_Hash *dirs, const char *dir, Eina
icon->icons = realloc(icon->icons, sizeof (char *) * (icon->icons_count + 1));
icon->icons[icon->icons_count] = eina_stringshare_add(entry->path);
eina_array_push(strs, icon->icons[icon->icons_count++]);
*changed = EINA_TRUE;
}
eina_iterator_free(it);
@ -133,7 +124,7 @@ cache_fallback_scan_dir(Eina_Hash *icons, Eina_Hash *dirs, const char *dir, Eina
}
static Eina_Bool
cache_fallback_scan(Eina_Hash *icons, Eina_Hash *dirs, Eina_Bool *changed)
cache_fallback_scan(Eina_Hash *icons, Eina_Hash *dirs)
{
unsigned int i;
Eina_List *xdg_dirs, *l;
@ -141,38 +132,88 @@ cache_fallback_scan(Eina_Hash *icons, Eina_Hash *dirs, Eina_Bool *changed)
char path[PATH_MAX];
for (i = 0; i < extra_dirs->count; i++)
cache_fallback_scan_dir(icons, dirs, extra_dirs->data[i], changed);
cache_fallback_scan_dir(icons, dirs, extra_dirs->data[i]);
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);
cache_fallback_scan_dir(icons, dirs, efreet_icon_deprecated_user_dir_get());
cache_fallback_scan_dir(icons, dirs, efreet_icon_user_dir_get());
xdg_dirs = efreet_data_dirs_get();
EINA_LIST_FOREACH(xdg_dirs, l, dir)
{
snprintf(path, sizeof(path), "%s/icons", dir);
cache_fallback_scan_dir(icons, dirs, path, changed);
cache_fallback_scan_dir(icons, dirs, path);
}
#ifndef STRICT_SPEC
EINA_LIST_FOREACH(xdg_dirs, l, dir)
{
snprintf(path, sizeof(path), "%s/pixmaps", dir);
cache_fallback_scan_dir(icons, dirs, path, changed);
cache_fallback_scan_dir(icons, dirs, path);
}
#endif
cache_fallback_scan_dir(icons, dirs, "/usr/share/pixmaps", changed);
cache_fallback_scan_dir(icons, dirs, "/usr/share/pixmaps");
return EINA_TRUE;
}
static Eina_Bool
check_fallback_changed(Efreet_Cache_Icon_Theme *theme)
{
unsigned int i;
Eina_List *xdg_dirs, *l;
const char *dir;
char path[PATH_MAX];
/* Check if the dirs we have cached are changed */
if (theme->dirs)
{
Eina_Iterator *it;
Eina_Bool changed = EINA_FALSE;
it = eina_hash_iterator_key_new(theme->dirs);
EINA_ITERATOR_FOREACH(it, dir)
{
changed = !ecore_file_exists(dir);
if (changed) break;
changed = cache_directory_modified(theme->dirs, dir);
if (changed) break;
}
eina_iterator_free(it);
if (changed) return EINA_TRUE;
}
/* Check if spec dirs have changed */
for (i = 0; i < extra_dirs->count; i++)
if (cache_directory_modified(theme->dirs, extra_dirs->data[i])) return EINA_TRUE;
if (cache_directory_modified(theme->dirs, efreet_icon_deprecated_user_dir_get())) return EINA_TRUE;
if (cache_directory_modified(theme->dirs, efreet_icon_user_dir_get())) return EINA_TRUE;
xdg_dirs = efreet_data_dirs_get();
EINA_LIST_FOREACH(xdg_dirs, l, dir)
{
snprintf(path, sizeof(path), "%s/icons", dir);
if (cache_directory_modified(theme->dirs, path)) return EINA_TRUE;
}
#ifndef STRICT_SPEC
EINA_LIST_FOREACH(xdg_dirs, l, dir)
{
snprintf(path, sizeof(path), "%s/pixmaps", dir);
if (cache_directory_modified(theme->dirs, path)) return EINA_TRUE;
}
#endif
if (cache_directory_modified(theme->dirs, "/usr/share/pixmaps")) return EINA_TRUE;
return EINA_FALSE;
}
static Eina_Bool
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_Hash *icons)
{
Eina_Iterator *it;
char buf[PATH_MAX];
@ -180,9 +221,6 @@ cache_scan_path_dir(Efreet_Icon_Theme *theme,
snprintf(buf, sizeof(buf), "%s/%s", path, dir->name);
if (!cache_directory_find(dirs, buf))
return EINA_TRUE;
it = eina_file_stat_ls(buf);
if (!it) return EINA_TRUE;
@ -261,8 +299,6 @@ cache_scan_path_dir(Efreet_Icon_Theme *theme,
sizeof (char*) * (icon->icons[i]->paths_count + 1));
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;
}
eina_iterator_free(it);
@ -271,19 +307,19 @@ cache_scan_path_dir(Efreet_Icon_Theme *theme,
}
static Eina_Bool
cache_scan_path(Efreet_Icon_Theme *theme, Eina_Hash *icons, Eina_Hash *dirs, const char *path, Eina_Bool *changed)
cache_scan_path(Efreet_Icon_Theme *theme, Eina_Hash *icons, const char *path)
{
Eina_List *l;
Efreet_Icon_Theme_Directory *dir;
EINA_LIST_FOREACH(theme->directories, l, dir)
if (!cache_scan_path_dir(theme, path, dir, icons, dirs, changed)) return EINA_FALSE;
if (!cache_scan_path_dir(theme, path, dir, icons)) return EINA_FALSE;
return EINA_TRUE;
}
static Eina_Bool
cache_scan(Efreet_Icon_Theme *theme, Eina_Hash *themes, Eina_Hash *icons, Eina_Hash *dirs, Eina_Bool *changed)
cache_scan(Efreet_Icon_Theme *theme, Eina_Hash *themes, Eina_Hash *icons)
{
Eina_List *l;
const char *path;
@ -295,7 +331,7 @@ cache_scan(Efreet_Icon_Theme *theme, Eina_Hash *themes, Eina_Hash *icons, Eina_H
/* scan theme */
EINA_LIST_FOREACH(theme->paths, l, path)
if (!cache_scan_path(theme, icons, dirs, path, changed)) return EINA_FALSE;
if (!cache_scan_path(theme, icons, path)) return EINA_FALSE;
/* scan inherits */
if (theme->inherits)
@ -308,13 +344,13 @@ cache_scan(Efreet_Icon_Theme *theme, Eina_Hash *themes, Eina_Hash *icons, Eina_H
if (!inherit)
INF("Theme `%s` not found for `%s`.",
name, theme->name.internal);
if (!cache_scan(inherit, themes, icons, dirs, changed)) return EINA_FALSE;
if (!cache_scan(inherit, themes, icons)) return EINA_FALSE;
}
}
else if (strcmp(theme->name.internal, "hicolor"))
{
theme = eina_hash_find(icon_themes, "hicolor");
if (!cache_scan(theme, themes, icons, dirs, changed)) return EINA_FALSE;
if (!cache_scan(theme, themes, icons)) return EINA_FALSE;
}
return EINA_TRUE;
@ -731,11 +767,9 @@ main(int argc, char **argv)
Efreet_Cache_Version *icon_version;
Efreet_Cache_Version *theme_version;
Efreet_Cache_Icon_Theme *theme;
Efreet_Cache_Icon *icon;
Eet_Data_Descriptor *theme_edd;
Eet_Data_Descriptor *icon_edd;
Eet_Data_Descriptor *fallback_edd;
Eina_Hash *icons;
Eet_File *icon_ef;
Eet_File *theme_ef;
Eina_List *xdg_dirs = NULL;
@ -848,6 +882,8 @@ main(int argc, char **argv)
flush = EINA_TRUE;
if (add_data(theme_ef, extra_dirs, EFREET_CACHE_ICON_EXTRA_DIRS))
flush = EINA_TRUE;
if (flush)
changed = EINA_TRUE;
if (exts->count == 0)
{
@ -893,23 +929,22 @@ main(int argc, char **argv)
it = eina_hash_iterator_data_new(icon_themes);
EINA_ITERATOR_FOREACH(it, theme)
{
Eina_Hash *themes;
if (!theme->valid) continue;
#ifndef STRICT_SPEC
if (!theme->theme.name.name) continue;
#endif
INF("scan theme %s", theme->theme.name.name);
changed = EINA_FALSE;
themes = eina_hash_string_superfast_new(NULL);
theme->changed = check_changed(theme);
if (flush)
theme->changed = EINA_TRUE;
INF("open icon file");
/* open icon file */
icon_ef = eet_open(efreet_icon_cache_file(theme->theme.name.internal), EET_FILE_MODE_READ_WRITE);
if (!icon_ef) goto on_error_efreet;
icon_version = eet_data_read(icon_ef, efreet_version_edd(), EFREET_CACHE_VERSION);
if (flush || (icon_version &&
if (theme->changed || (icon_version &&
((icon_version->major != EFREET_ICON_CACHE_MAJOR) ||
(icon_version->minor != EFREET_ICON_CACHE_MINOR))))
{
@ -921,68 +956,47 @@ main(int argc, char **argv)
}
icon_ef = eet_open(efreet_icon_cache_file(theme->theme.name.internal), EET_FILE_MODE_READ_WRITE);
if (!icon_ef) goto on_error_efreet;
changed = EINA_TRUE;
}
if (!icon_version)
icon_version = NEW(Efreet_Cache_Version, 1);
icon_version->major = EFREET_ICON_CACHE_MAJOR;
icon_version->minor = EFREET_ICON_CACHE_MINOR;
/* load icons */
icons = eina_hash_string_superfast_new(NULL);
keys = eet_list(icon_ef, "*", &num);
if (keys)
{
for (i = 0; i < num; i++)
{
if (!strncmp(keys[i], "__efreet", 8)) continue;
icon = eet_data_read(icon_ef, icon_edd, keys[i]);
if (icon) eina_hash_add(icons, keys[i], icon);
}
free(keys);
theme->changed = EINA_TRUE;
}
theme->changed = check_changed(theme);
if (theme->changed)
changed = EINA_TRUE;
if (flush)
changed = theme->changed = EINA_TRUE;
if (changed && theme->dirs)
{
efreet_hash_free(theme->dirs, free);
theme->dirs = NULL;
}
if (!theme->dirs)
theme->dirs = eina_hash_string_superfast_new(NULL);
INF("scan icons\n");
if (cache_scan(&(theme->theme), themes, icons, theme->dirs, &changed))
if (theme->changed)
{
INF("generated: '%s' %i (%i)",
theme->theme.name.internal,
changed,
eina_hash_population(icons));
if (changed)
Eina_Hash *themes;
Eina_Hash *icons;
if (!icon_version)
icon_version = NEW(Efreet_Cache_Version, 1);
icon_version->major = EFREET_ICON_CACHE_MAJOR;
icon_version->minor = EFREET_ICON_CACHE_MINOR;
themes = eina_hash_string_superfast_new(NULL);
icons = eina_hash_string_superfast_new(NULL);
INF("scan icons\n");
if (cache_scan(&(theme->theme), themes, icons))
{
Eina_Iterator *icons_it;
Eina_Hash_Tuple *tuple;
INF("generated: '%s' %i (%i)",
theme->theme.name.internal,
changed,
eina_hash_population(icons));
icons_it = eina_hash_iterator_tuple_new(icons);
EINA_ITERATOR_FOREACH(icons_it, tuple)
eet_data_write(icon_ef, icon_edd, tuple->key, tuple->data, 1);
eina_iterator_free(icons_it);
}
}
eina_hash_free(themes);
eina_hash_free(icons);
if (changed)
{
if (theme->changed)
INF("theme change: %s %lld", theme->theme.name.internal, theme->last_cache_check);
eet_data_write(theme_ef, theme_edd, theme->theme.name.internal, theme, 1);
eet_data_write(theme_ef, theme_edd, theme->theme.name.internal, theme, 1);
}
eina_hash_free(themes);
eina_hash_free(icons);
}
eet_data_write(icon_ef, efreet_version_edd(), EFREET_CACHE_VERSION, icon_version, 1);
@ -992,14 +1006,22 @@ main(int argc, char **argv)
}
eina_iterator_free(it);
changed = EINA_FALSE;
INF("scan fallback icons");
theme = eet_data_read(theme_ef, theme_edd, EFREET_CACHE_ICON_FALLBACK);
if (!theme)
{
theme = NEW(Efreet_Cache_Icon_Theme, 1);
theme->changed = EINA_TRUE;
}
if (flush)
theme->changed = EINA_TRUE;
INF("open fallback file");
/* open icon file */
icon_ef = eet_open(efreet_icon_cache_file(EFREET_CACHE_ICON_FALLBACK), EET_FILE_MODE_READ_WRITE);
if (!icon_ef) goto on_error_efreet;
icon_version = eet_data_read(icon_ef, efreet_version_edd(), EFREET_CACHE_VERSION);
if (flush || (icon_version &&
if (theme->changed || (icon_version &&
((icon_version->major != EFREET_ICON_CACHE_MAJOR) ||
(icon_version->minor != EFREET_ICON_CACHE_MINOR))))
{
@ -1011,35 +1033,11 @@ main(int argc, char **argv)
}
icon_ef = eet_open(efreet_icon_cache_file(EFREET_CACHE_ICON_FALLBACK), EET_FILE_MODE_READ_WRITE);
if (!icon_ef) goto on_error_efreet;
changed = EINA_TRUE;
theme->changed = EINA_TRUE;
}
if (!icon_version)
icon_version = NEW(Efreet_Cache_Version, 1);
icon_version->major = EFREET_ICON_CACHE_MAJOR;
icon_version->minor = EFREET_ICON_CACHE_MINOR;
/* load icons */
icons = eina_hash_string_superfast_new(NULL);
keys = eet_list(icon_ef, "*", &num);
if (keys)
{
for (i = 0; i < num; i++)
{
if (!strncmp(keys[i], "__efreet", 8)) continue;
icon = eet_data_read(icon_ef, fallback_edd, keys[i]);
if (icon) eina_hash_add(icons, keys[i], icon);
}
free(keys);
}
theme = eet_data_read(theme_ef, theme_edd, EFREET_CACHE_ICON_FALLBACK);
if (!theme)
theme = NEW(Efreet_Cache_Icon_Theme, 1);
theme->changed = changed;
if (flush)
changed = theme->changed = EINA_TRUE;
if (changed && theme->dirs)
if (!theme->changed)
theme->changed = check_fallback_changed(theme);
if (theme->changed && theme->dirs)
{
efreet_hash_free(theme->dirs, free);
theme->dirs = NULL;
@ -1047,25 +1045,40 @@ main(int argc, char **argv)
if (!theme->dirs)
theme->dirs = eina_hash_string_superfast_new(NULL);
INF("scan fallback icons");
/* Save fallback in the right part */
if (cache_fallback_scan(icons, theme->dirs, &changed))
if (theme->changed)
changed = EINA_TRUE;
if (theme->changed)
{
WRN("generated: fallback %i (%i)", changed, eina_hash_population(icons));
if (changed)
Eina_Hash *icons;
if (!icon_version)
icon_version = NEW(Efreet_Cache_Version, 1);
icon_version->major = EFREET_ICON_CACHE_MAJOR;
icon_version->minor = EFREET_ICON_CACHE_MINOR;
icons = eina_hash_string_superfast_new(NULL);
INF("scan fallback icons");
/* Save fallback in the right part */
if (cache_fallback_scan(icons, theme->dirs))
{
Eina_Iterator *icons_it;
Eina_Hash_Tuple *tuple;
INF("generated: fallback %i (%i)", theme->changed, eina_hash_population(icons));
icons_it = eina_hash_iterator_tuple_new(icons);
EINA_ITERATOR_FOREACH(icons_it, tuple)
eet_data_write(icon_ef, fallback_edd, tuple->key, tuple->data, 1);
eina_iterator_free(icons_it);
}
eina_hash_free(icons);
eet_data_write(theme_ef, theme_edd, EFREET_CACHE_ICON_FALLBACK, theme, 1);
}
eina_hash_free(icons);
eet_data_write(theme_ef, theme_edd, EFREET_CACHE_ICON_FALLBACK, theme, 1);
icon_theme_free(theme);
eet_data_write(icon_ef, efreet_version_edd(), EFREET_CACHE_VERSION, icon_version, 1);