From 7dbb6fbe664f47c444eeb703c41d71c7979f48ec Mon Sep 17 00:00:00 2001 From: Carsten Haitzler Date: Sat, 24 Sep 2005 17:25:48 +0000 Subject: [PATCH] a start on the eap cache - it can load and save right now but not update once saved. its disabled atm. BUT i have reduced the data needing to be loaded at startup from opening 200 eap files totalling something like 6.5Mb of disk space used (though actual loads will be less - likely), down to loading 1 file of about 7kb and doing a stat or 2 on each file (my next phase is to remove the stat on startup here and cache that info too, and then add in the code to have e slowly run over the cache data and match it up against real life data and see if its still valid or not etc. and write it out as well as make sure new caches are written out whenever eapp dirs change, and then finally make a cmd-line tool to do it per dir) SVN revision: 16922 --- src/bin/e_apps.c | 221 ++++++++++++++++++++++++++++++++-------- src/bin/e_apps.h | 5 + src/bin/e_apps_cache.c | 226 +++++++++++++++++++++++++++++++++++++++++ src/bin/e_apps_cache.h | 41 +++++++- 4 files changed, 446 insertions(+), 47 deletions(-) diff --git a/src/bin/e_apps.c b/src/bin/e_apps.c index 5e6cf7760..88198a875 100644 --- a/src/bin/e_apps.c +++ b/src/bin/e_apps.c @@ -32,8 +32,6 @@ struct _E_App_Callback static void _e_app_free (E_App *a); static void _e_app_fields_fill (E_App *a, const char *path); -static void _e_app_fields_empty (E_App *a); -static Ecore_List *_e_app_dir_file_list_get (E_App *a); static E_App *_e_app_subapp_file_find (E_App *a, const char *file); static void _e_app_change (E_App *a, E_App_Change ch); static int _e_apps_cb_exit (void *data, int type, void *event); @@ -66,6 +64,7 @@ e_app_init(void) char *home; char buf[PATH_MAX]; + e_app_cache_init(); home = e_user_homedir_get(); snprintf(buf, sizeof(buf), "%s/.e/e/applications/trash", home); _e_apps_path_trash = strdup(buf); @@ -114,15 +113,124 @@ e_app_shutdown(void) printf("BUG: References %d %s\n", E_OBJECT(a)->references, a->path); } } + e_app_cache_shutdown(); return 1; } +E_App * +e_app_raw_new(void) +{ + E_App *a; + + a = E_OBJECT_ALLOC(E_App, E_APP_TYPE, _e_app_free); + return a; +} + +static void +_e_app_cache_copy(E_App_Cache *ac, E_App *a) +{ +#define IF_DUP(x) if (ac->x) a->x = strdup(ac->x) + IF_DUP(name); + IF_DUP(generic); + IF_DUP(comment); + IF_DUP(exe); + IF_DUP(win_name); + IF_DUP(win_class); + IF_DUP(win_title); + IF_DUP(win_role); + IF_DUP(icon_class); + a->startup_notify = ac->startup_notify; + a->wait_exit = ac->wait_exit; +} + +static E_App * +_e_app_cache_new(E_App_Cache *ac, char *path, int scan_subdirs) +{ + Evas_List *l; + E_App *a; + char buf[PATH_MAX]; + + a = E_OBJECT_ALLOC(E_App, E_APP_TYPE, _e_app_free); + _e_app_cache_copy(ac, a); + a->path = strdup(path); + a->scanned = 1; + for (l = ac->subapps; l; l = l->next) + { + E_App_Cache *ac2; + E_App *a2; + int is_dir; + + ac2 = l->data; + snprintf(buf, sizeof(buf), "%s/%s", path, ac2->file); + is_dir = ecore_file_is_dir(buf); + if ((is_dir) && (scan_subdirs)) + { + a2 = e_app_new(buf, scan_subdirs); + a2->parent = a; + a->subapps = evas_list_append(a->subapps, a2); + } + else + { + if (ecore_file_exists(buf)) + { + a2 = E_OBJECT_ALLOC(E_App, E_APP_TYPE, _e_app_free); + _e_app_cache_copy(ac2, a2); + if (is_dir) + { + E_FREE(a2->exe); + } + a2->parent = a; + a2->path = strdup(buf); + a->subapps = evas_list_append(a->subapps, a2); + _e_apps = evas_hash_add(_e_apps, a2->path, a2); + _e_apps_list = evas_list_prepend(_e_apps_list, a2); + } + else + { + E_App *a3; + Evas_List *pl; + + pl = _e_apps_repositories; + a2 = NULL; + while ((!a2) && (pl)) + { + snprintf(buf, sizeof(buf), "%s/%s", (char *)pl->data, ac2->file); + a2 = e_app_new(buf, scan_subdirs); + pl = pl->next; + } + if (a2) + { + a3 = E_OBJECT_ALLOC(E_App, E_APP_TYPE, _e_app_free); + if (a3) + { + if (_e_app_copy(a3, a2)) + { + a3->parent = a; + a->subapps = evas_list_append(a->subapps, a3); + a2->references = evas_list_append(a2->references, a3); + } + else + e_object_del(E_OBJECT(a3)); + } + } + } + } + } + + /* FIXME: create timer object to scan this slowly and fixup */ + + // and at the end of the slow scan add this: + // a->monitor = ecore_file_monitor_add(a->path, _e_app_cb_monitor, a); + return a; +} + E_App * e_app_new(const char *path, int scan_subdirs) { E_App *a; char buf[PATH_MAX]; - + E_App_Cache *ac; + a = evas_hash_find(_e_apps, path); if (a) { @@ -131,46 +239,64 @@ e_app_new(const char *path, int scan_subdirs) e_object_ref(E_OBJECT(a)); return a; } - - if (ecore_file_exists(path)) +/* + ac = e_app_cache_load((char *)path); + if (ac) { - a = E_OBJECT_ALLOC(E_App, E_APP_TYPE, _e_app_free); - /* record the path */ - a->path = strdup(path); - - if (ecore_file_is_dir(a->path)) + a = _e_app_cache_new(ac, path, scan_subdirs); + if (a) { - snprintf(buf, sizeof(buf), "%s/.directory.eap", path); - if (ecore_file_exists(buf)) - _e_app_fields_fill(a, buf); - else - a->name = strdup(ecore_file_get_file(a->path)); - if (scan_subdirs) e_app_subdir_scan(a, scan_subdirs); - - a->monitor = ecore_file_monitor_add(a->path, _e_app_cb_monitor, a); + _e_apps = evas_hash_add(_e_apps, a->path, a); + _e_apps_list = evas_list_prepend(_e_apps_list, a); } - else if (_e_app_is_eapp(path)) + e_app_cache_free(ac); + } + else + */ + { + if (ecore_file_exists(path)) { - _e_app_fields_fill(a, path); - - /* no exe field.. not valid. drop it */ - if (!a->exe) + a = E_OBJECT_ALLOC(E_App, E_APP_TYPE, _e_app_free); + /* record the path */ + a->path = strdup(path); + + if (ecore_file_is_dir(a->path)) + { + snprintf(buf, sizeof(buf), "%s/.directory.eap", path); + if (ecore_file_exists(buf)) + e_app_fields_fill(a, buf); + else + a->name = strdup(ecore_file_get_file(a->path)); + if (scan_subdirs) e_app_subdir_scan(a, scan_subdirs); + + a->monitor = ecore_file_monitor_add(a->path, _e_app_cb_monitor, a); + } + else if (_e_app_is_eapp(path)) + { + e_app_fields_fill(a, path); + + /* no exe field.. not valid. drop it */ + if (!a->exe) + goto error; + } + else goto error; } else - goto error; + return NULL; + _e_apps = evas_hash_add(_e_apps, a->path, a); + _e_apps_list = evas_list_prepend(_e_apps_list, a); + + ac = e_app_cache_generate(a); + e_app_cache_save(ac, a->path); + e_app_cache_free(ac); } - else - return NULL; - - _e_apps = evas_hash_add(_e_apps, a->path, a); - _e_apps_list = evas_list_prepend(_e_apps_list, a); return a; error: if (a->monitor) ecore_file_monitor_del(a->monitor); if (a->path) free(a->path); - _e_app_fields_empty(a); + e_app_fields_empty(a); free(a); return NULL; } @@ -198,7 +324,8 @@ e_app_subdir_scan(E_App *a, int scan_subdirs) Ecore_List *files; char *s; char buf[PATH_MAX]; - + E_App_Cache *ac; + E_OBJECT_CHECK(a); E_OBJECT_TYPE_CHECK(a, E_APP_TYPE); if (a->exe) return; @@ -212,7 +339,7 @@ e_app_subdir_scan(E_App *a, int scan_subdirs) return; } a->scanned = 1; - files = _e_app_dir_file_list_get(a); + files = e_app_dir_file_list_get(a); if (files) { while ((s = ecore_list_next(files))) @@ -263,6 +390,10 @@ e_app_subdir_scan(E_App *a, int scan_subdirs) } ecore_list_destroy(files); } + + ac = e_app_cache_generate(a); + e_app_cache_save(ac, a->path); + e_app_cache_free(ac); } int @@ -766,14 +897,14 @@ _e_app_free(E_App *a) ecore_file_monitor_del(a->monitor); _e_apps = evas_hash_del(_e_apps, a->path, a); _e_apps_list = evas_list_remove(_e_apps_list, a); - _e_app_fields_empty(a); + e_app_fields_empty(a); E_FREE(a->path); free(a); } } -static void -_e_app_fields_fill(E_App *a, const char *path) +void +e_app_fields_fill(E_App *a, const char *path) { Eet_File *ef; char buf[PATH_MAX]; @@ -912,8 +1043,8 @@ _e_app_fields_fill(E_App *a, const char *path) eet_close(ef); } -static void -_e_app_fields_empty(E_App *a) +void +e_app_fields_empty(E_App *a) { E_FREE(a->name); E_FREE(a->generic); @@ -926,8 +1057,8 @@ _e_app_fields_empty(E_App *a) E_FREE(a->win_role); } -static Ecore_List * -_e_app_dir_file_list_get(E_App *a) +Ecore_List * +e_app_dir_file_list_get(E_App *a) { Ecore_List *files, *files2; char *file; @@ -1137,13 +1268,13 @@ _e_app_cb_monitor(void *data, Ecore_File_Monitor *em, if ((event == ECORE_FILE_EVENT_CREATED_FILE) || (event == ECORE_FILE_EVENT_MODIFIED)) { - _e_app_fields_empty(app); - _e_app_fields_fill(app, path); + e_app_fields_empty(app); + e_app_fields_fill(app, path); _e_app_change(app, E_APP_CHANGE); } else if (event == ECORE_FILE_EVENT_DELETED_FILE) { - _e_app_fields_empty(app); + e_app_fields_empty(app); app->name = strdup(ecore_file_get_file(app->path)); } else @@ -1162,8 +1293,8 @@ _e_app_cb_monitor(void *data, Ecore_File_Monitor *em, { Evas_List *l; - _e_app_fields_empty(a2); - _e_app_fields_fill(a2, path); + e_app_fields_empty(a2); + e_app_fields_fill(a2, path); _e_app_change(a2, E_APP_CHANGE); for (l = a2->references; l; l = l->next) @@ -1240,7 +1371,7 @@ _e_app_subdir_rescan(E_App *app) char buf[PATH_MAX]; char *s; - files = _e_app_dir_file_list_get(app); + files = e_app_dir_file_list_get(app); if (files) { while ((s = ecore_list_next(files))) diff --git a/src/bin/e_apps.h b/src/bin/e_apps.h index 5aadd02f6..462c49fa5 100644 --- a/src/bin/e_apps.h +++ b/src/bin/e_apps.h @@ -96,6 +96,11 @@ EAPI E_App *e_app_file_find(char *file); EAPI E_App *e_app_name_find(char *name); EAPI E_App *e_app_generic_find(char *generic); EAPI E_App *e_app_exe_find(char *exe); + +EAPI void e_app_fields_fill(E_App *a, const char *path); +EAPI E_App *e_app_raw_new(void); +EAPI Ecore_List *e_app_dir_file_list_get(E_App *a); +EAPI void e_app_fields_empty(E_App *a); #endif #endif diff --git a/src/bin/e_apps_cache.c b/src/bin/e_apps_cache.c index d8b275332..16b3427e4 100644 --- a/src/bin/e_apps_cache.c +++ b/src/bin/e_apps_cache.c @@ -2,3 +2,229 @@ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 */ #include "e.h" + +#define NEWD(str, typ) \ + eet_data_descriptor_new(str, sizeof(typ), \ + (void *(*) (void *))evas_list_next, \ + (void *(*) (void *, void *))evas_list_append, \ + (void *(*) (void *))evas_list_data, \ + (void *(*) (void *))evas_list_free, \ + (void (*) (void *, int (*) (void *, const char *, void *, void *), void *))evas_hash_foreach, \ + (void *(*) (void *, const char *, void *))evas_hash_add, \ + (void (*) (void *))evas_hash_free) + +#define FREED(eed) \ + if (eed) \ + { \ + eet_data_descriptor_free((eed)); \ + (eed) = NULL; \ + } +#define NEWI(str, it, type) \ + EET_DATA_DESCRIPTOR_ADD_BASIC(_e_app_cache_edd, E_App_Cache, str, it, type) +#define NEWL(str, it, type) \ + EET_DATA_DESCRIPTOR_ADD_LIST(_e_app_cache_edd, E_App_Cache, str, it, type) + +static void _e_eapp_cache_fill(E_App_Cache *ac, E_App *a); + +static Eet_Data_Descriptor *_e_app_cache_edd = NULL; + +int +e_app_cache_init(void) +{ + _e_app_cache_edd = NEWD("E_App_Cache", E_App_Cache); + NEWI("nm", name, EET_T_STRING); + NEWI("gn", generic, EET_T_STRING); + NEWI("cm", comment, EET_T_STRING); + NEWI("ex", exe, EET_T_STRING); + NEWI("fl", file, EET_T_STRING); + NEWI("fm", file_mod_time, EET_T_ULONG_LONG); + NEWI("wn", win_name, EET_T_STRING); + NEWI("wc", win_class, EET_T_STRING); + NEWI("wt", win_title, EET_T_STRING); + NEWI("wr", win_role, EET_T_STRING); + NEWI("ic", icon_class, EET_T_STRING); + NEWL("ap", subapps, _e_app_cache_edd); + NEWI("sn", startup_notify, EET_T_UCHAR); + NEWI("wx", wait_exit, EET_T_UCHAR); + return 1; +} + +int +e_app_cache_shutdown(void) +{ + FREED(_e_app_cache_edd); + return 1; +} + +E_App_Cache * +e_app_cache_load(char *path) +{ + Eet_File *ef; + char buf[PATH_MAX]; + E_App_Cache *ac; + + if (!path) return NULL; + snprintf(buf, sizeof(buf), "%s/.eap.cache.cfg", path); + ef = eet_open(buf, EET_FILE_MODE_READ); + if (!ef) return NULL; + ac = eet_data_read(ef, _e_app_cache_edd, "cache"); + eet_close(ef); + return ac; +} + +E_App_Cache * +e_app_cache_generate(E_App *a) +{ + E_App_Cache *ac; + Evas_List *l; + + if (!a) return NULL; + ac = calloc(1, sizeof(E_App_Cache)); + if (!ac) return NULL; + _e_eapp_cache_fill(ac, a); + for (l = a->subapps; l; l = l->next) + { + E_App *a2; + E_App_Cache *ac2; + + a2 = l->data; + ac2 = calloc(1, sizeof(E_App_Cache)); + if (ac2) + { + _e_eapp_cache_fill(ac2, a2); + ac->subapps = evas_list_append(ac->subapps, ac2); + ac->subapps_hash = evas_hash_add(ac->subapps_hash, ac2->file, ac2); + } + } + return ac; +} + +E_App_Cache * +e_app_cache_path_generate(char *path) +{ + E_App_Cache *ac; + E_App *a; + char buf[PATH_MAX]; + Ecore_List *files; + + if (!path) return NULL; + ac = calloc(1, sizeof(E_App_Cache)); + if (!ac) return NULL; + a = e_app_raw_new(); + a->path = strdup(path); + _e_eapp_cache_fill(ac, a); + if (ecore_file_is_dir(a->path)) + { + snprintf(buf, sizeof(buf), "%s/.directory.eap", path); + if (ecore_file_exists(buf)) + e_app_fields_fill(a, buf); + else + a->name = strdup(ecore_file_get_file(a->path)); + + files = e_app_dir_file_list_get(a); + if (files) + { + char *s = NULL; + + while ((s = ecore_list_next(files))) + { + E_App *a2; + E_App_Cache *ac2; + + ac2 = calloc(1, sizeof(E_App_Cache)); + if (ac2) + { + a2 = e_app_raw_new(); + if (a2) + { + snprintf(buf, sizeof(buf), "%s/%s", a->path, s); + a2->path = strdup(buf); + if (ecore_file_is_dir(a2->path)) + { + snprintf(buf, sizeof(buf), "%s/.directory.eap", a2->path); + e_app_fields_fill(a2, buf); + } + else + e_app_fields_fill(a2, a2->path); + _e_eapp_cache_fill(ac2, a2); + e_app_fields_empty(a2); + free(a2); + } + ac->subapps = evas_list_append(ac->subapps, ac2); + ac->subapps_hash = evas_hash_add(ac->subapps_hash, ac2->file, ac2); + } + } + ecore_list_destroy(files); + } + } + e_app_fields_empty(a); + free(a); + + return ac; +} + +void +e_app_cache_free(E_App_Cache *ac) +{ + if (!ac) return; + E_FREE(ac->name); + E_FREE(ac->generic); + E_FREE(ac->comment); + E_FREE(ac->exe); + E_FREE(ac->file); + E_FREE(ac->win_name); + E_FREE(ac->win_class); + E_FREE(ac->win_title); + E_FREE(ac->win_role); + E_FREE(ac->icon_class); + while (ac->subapps) + { + E_App_Cache *ac2; + + ac2 = ac->subapps->data; + ac->subapps = evas_list_remove_list(ac->subapps, ac->subapps); + e_app_cache_free(ac2); + } + evas_hash_free(ac->subapps_hash); + free(ac); +} + + + +int +e_app_cache_save(E_App_Cache *ac, char *path) +{ + Eet_File *ef; + char buf[4096]; + int ret; + + if ((!ac) || (!path)) return 0; + snprintf(buf, sizeof(buf), "%s/.eap.cache.cfg", path); + ef = eet_open(buf, EET_FILE_MODE_WRITE); + if (!ef) return 0; + ret = eet_data_write(ef, _e_app_cache_edd, "cache", ac, 1); + eet_close(ef); + return ret; +} + + + +static void +_e_eapp_cache_fill(E_App_Cache *ac, E_App *a) +{ +#define IF_DUP(x) if (a->x) ac->x = strdup(a->x) + IF_DUP(name); + IF_DUP(generic); + IF_DUP(comment); + IF_DUP(exe); + ac->file = strdup(ecore_file_get_file(a->path)); + ac->file_mod_time = ecore_file_mod_time(a->path); + IF_DUP(win_name); + IF_DUP(win_class); + IF_DUP(win_title); + IF_DUP(win_role); + IF_DUP(icon_class); + ac->startup_notify = a->startup_notify; + ac->wait_exit = a->wait_exit; +} + diff --git a/src/bin/e_apps_cache.h b/src/bin/e_apps_cache.h index 7bb3bba30..328c4276b 100644 --- a/src/bin/e_apps_cache.h +++ b/src/bin/e_apps_cache.h @@ -3,9 +3,46 @@ */ #ifdef E_TYPEDEFS +typedef struct _E_App_Cache E_App_Cache; + #else #ifndef E_APPS_CACHE_H -#define E_APPS_CAHCE_H - +#define E_APPS_CACHE_H + +struct _E_App_Cache +{ + char *name; /* app name */ + char *generic; /* generic app name */ + char *comment; /* a longer description */ + char *exe; /* command to execute, NULL if directory */ + + char *file; /* the .eap filename */ + unsigned long long file_mod_time; /* the last modified time of the file */ + + char *win_name; /* window name */ + char *win_class; /* window class */ + char *win_title; /* window title */ + char *win_role; /* window role */ + + char *icon_class; /* icon_class */ + + Evas_List *subapps; /* if this a directory, a list of more E_App's */ + + unsigned char startup_notify; /* disable while starting etc. */ + unsigned char wait_exit; /* wait for app to exit before execing next */ + + /* these are generated post-load */ + Evas_Hash *subapps_hash; /* a quick lookup hash */ +}; + +EAPI int e_app_cache_init(void); +EAPI int e_app_cache_shutdown(void); + +EAPI E_App_Cache *e_app_cache_load(char *path); +EAPI E_App_Cache *e_app_cache_generate(E_App *a); +EAPI E_App_Cache *e_app_cache_path_generate(char *path); +EAPI void e_app_cache_free(E_App_Cache *ac); +EAPI int e_app_cache_save(E_App_Cache *ac, char *path); + #endif #endif