a start on the eap cache - it can load and save right now but not update once
authorCarsten Haitzler <raster@rasterman.com>
Sat, 24 Sep 2005 17:25:48 +0000 (17:25 +0000)
committerCarsten Haitzler <raster@rasterman.com>
Sat, 24 Sep 2005 17:25:48 +0000 (17:25 +0000)
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
src/bin/e_apps.h
src/bin/e_apps_cache.c
src/bin/e_apps_cache.h

index 5e6cf77..88198a8 100644 (file)
@@ -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_new(const char *path, int scan_subdirs)
+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)))
index 5aadd02..462c49f 100644 (file)
@@ -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
index d8b2753..16b3427 100644 (file)
@@ -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;
+}
+
index 7bb3bba..328c427 100644 (file)
@@ -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