efreet - save about 240-300k or so of memory used by efreet mime
authorCarsten Haitzler (Rasterman) <raster@rasterman.com>
Tue, 23 Aug 2016 02:59:37 +0000 (11:59 +0900)
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>
Tue, 23 Aug 2016 03:04:06 +0000 (12:04 +0900)
so efreet mime was loading a bunch of mime type info files, parsing
them on startup and allocating memory to store all this mime info -
globs, mimetype strings and more. all a big waste of memory as its
allocated on the heap per process where its the SAME data files loaded
every time.

so make an efreet mime cache file and a tool to create it from mime
files. mmap this file with all the hashes/strings in it so all that
data is mmaped once in memory and shared between all processes and it
is only paged in on demand - as actually read/needed so if your
process doesnt need to know about mime stuff.. it wont touch it anyway.

this saves about 240-300k or so of memory in my tests. this has not
covered the mime MAGIC files which still consume memory and are on the
heap. this is more complex so it will take more time to come up with a
nice file format for the data that is nicely mmaped etc.

@optimize

src/Makefile_Efreet.am
src/bin/efreet/.gitignore
src/bin/efreet/efreet_mime_cache_create.c [new file with mode: 0644]
src/bin/efreet/efreetd_cache.c
src/bin/efreet/efreetd_ipc.c
src/bin/efreet/efreetd_ipc.h
src/examples/elementary/codegen_example_generated.c [deleted file]
src/examples/elementary/codegen_example_generated.h [deleted file]
src/lib/efreet/efreet_cache.c
src/lib/efreet/efreet_mime.c
src/lib/efreet/efreet_private.h

index 32d4330..fe969f9 100644 (file)
@@ -90,7 +90,8 @@ bin_efreet_efreetd_DEPENDENCIES = @USE_EFREET_INTERNAL_LIBS@
 efreetinternal_bindir=$(libdir)/efreet/$(MODULE_ARCH)
 efreetinternal_bin_PROGRAMS = \
 bin/efreet/efreet_desktop_cache_create \
-bin/efreet/efreet_icon_cache_create
+bin/efreet/efreet_icon_cache_create \
+bin/efreet/efreet_mime_cache_create
 
 bin_efreet_efreet_desktop_cache_create_CPPFLAGS = -I$(top_builddir)/src/lib/efl $(EFREET_COMMON_CPPFLAGS)
 bin_efreet_efreet_desktop_cache_create_LDADD = $(USE_EFREET_BIN_LIBS)
@@ -102,6 +103,11 @@ bin_efreet_efreet_icon_cache_create_LDADD = $(USE_EFREET_BIN_LIBS)
 bin_efreet_efreet_icon_cache_create_DEPENDENCIES = @USE_EFREET_INTERNAL_LIBS@
 bin_efreet_efreet_icon_cache_create_SOURCES = bin/efreet/efreet_icon_cache_create.c
 
+bin_efreet_efreet_mime_cache_create_CPPFLAGS = -I$(top_builddir)/src/lib/efl $(EFREET_COMMON_CPPFLAGS)
+bin_efreet_efreet_mime_cache_create_LDADD = $(USE_EFREET_BIN_LIBS)
+bin_efreet_efreet_mime_cache_create_DEPENDENCIES = @USE_EFREET_INTERNAL_LIBS@
+bin_efreet_efreet_mime_cache_create_SOURCES = bin/efreet/efreet_mime_cache_create.c
+
 ### Unit tests
 
 if EFL_ENABLE_TESTS
index 76fc576..f6ff3d0 100644 (file)
@@ -1,3 +1,4 @@
 /efreet_desktop_cache_create
 /efreet_icon_cache_create
 /efreetd
+/efreet_mime_cache_create
diff --git a/src/bin/efreet/efreet_mime_cache_create.c b/src/bin/efreet/efreet_mime_cache_create.c
new file mode 100644 (file)
index 0000000..8f8b0a1
--- /dev/null
@@ -0,0 +1,453 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/time.h>
+#include <sys/resource.h>
+#endif
+#ifdef _WIN32
+# include <winsock2.h>
+#endif
+#include <libgen.h>
+#include <ctype.h>
+
+#include <Eina.h>
+#include <Eet.h>
+#include <Ecore.h>
+#include <Ecore_File.h>
+
+#ifndef O_BINARY
+# define O_BINARY 0
+#endif
+
+#define EFREET_MODULE_LOG_DOM _efreet_mime_cache_log_dom
+static int _efreet_mime_cache_log_dom = -1;
+static Eina_List *extra_dirs = NULL;
+
+static Eina_Hash  *mimes = NULL;
+static Eina_Hash  *extn_mimes = NULL;
+static Eina_Hash  *glob_mimes = NULL;
+static Eina_List  *mimes_sorted = NULL;
+static Eina_List  *extn_mimes_sorted = NULL;
+static Eina_List  *glob_mimes_sorted = NULL;
+
+#include "Efreet.h"
+#include "efreet_private.h"
+#include "efreet_cache_private.h"
+
+static int
+cache_lock_file(void)
+{
+   char file[PATH_MAX];
+   struct flock fl;
+   int lockfd;
+
+   snprintf(file, sizeof(file), "%s/efreet/mime_data.lock", efreet_cache_home_get());
+   lockfd = open(file, O_CREAT | O_BINARY | O_RDWR, S_IRUSR | S_IWUSR);
+   if (lockfd < 0) return -1;
+   efreet_fsetowner(lockfd);
+
+   memset(&fl, 0, sizeof(struct flock));
+   fl.l_type = F_WRLCK;
+   fl.l_whence = SEEK_SET;
+   if (fcntl(lockfd, F_SETLK, &fl) < 0)
+     {
+        INF("LOCKED! You may want to delete %s if this persists", file);
+        close(lockfd);
+        return -1;
+     }
+
+   return lockfd;
+}
+
+static int
+hash_list_sort_insert_cmp(const char *key1, const char *key2)
+{
+   return strcmp(key1, key2);
+}
+
+static Eina_Bool
+hash_list_sort_each(const Eina_Hash *hash EINA_UNUSED, const void *key, void *value EINA_UNUSED, void *data)
+{
+   Eina_List **list = data;
+   *list = eina_list_sorted_insert(*list,
+                                   EINA_COMPARE_CB(hash_list_sort_insert_cmp),
+                                   key);
+   return EINA_TRUE;
+}
+
+static void
+hash_list_sort(Eina_Hash *hash, Eina_List **list)
+{
+   eina_hash_foreach(hash, hash_list_sort_each, list);
+}
+
+static void
+etc_mime_types_load(const char *file)
+{
+   int len;
+   char buf[4096], buf2[4096], buf3[4096], *p, *p2;
+   const char *mime;
+   FILE *f = fopen(file, "r");
+
+   if (!f) return;
+   while (fgets(buf, sizeof(buf), f))
+     {
+        // remove newline at end of line string if there
+        buf[sizeof(buf) - 1] = 0;
+        len = strlen(buf);
+        if ((len > 0) && (buf[len - 1] == '\n')) buf[len - 1] = 0;
+        // buf: "# comment"
+        // or
+        // buf: "mime/type"
+        // buf: "mime/type   "
+        // buf: "mime/type     ext1"
+        // buf: "mime/type     ext1 ext2"
+        // buf: "mime/type     ext1 ext2 ext3"
+        // ...
+        p = buf;
+        // find first token in line
+        while ((*p) && isspace(*p)) p++;
+        // if comment - skip line
+        if (*p == '#') continue;
+        p2 = p;
+        while ((*p2) && !isspace(*p2)) p2++;
+        // token is between p and p2 (not including p2)
+        strncpy(buf2, p, p2 - p);
+        buf2[p2 - p] = 0;
+        mime = eina_stringshare_add(buf2);
+        // buf2 is now the mime type token
+        eina_hash_del(mimes, buf2, NULL);
+        eina_hash_add(mimes, buf2, mime);
+        // now lookf for all extension tokens;
+        p = p2;
+        // find next token in line
+        while ((*p) && isspace(*p)) p++;
+        while (*p)
+          {
+             // find end of token
+             p2 = p;
+             while ((*p2) && !isspace(*p2)) p2++;
+             // buf3 is now the extension token
+             strncpy(buf3, p, p2 - p);
+             buf3[p2 - p] = 0;
+             eina_hash_del(extn_mimes, buf3, NULL);
+             eina_hash_add(extn_mimes, buf3, mime);
+             // go to next token if any
+             p = p2;
+             while ((*p) && isspace(*p)) p++;
+          }
+     }
+   fclose(f);
+}
+
+static void
+share_mime_globs_load(const char *file)
+{
+   int len;
+   char buf[4096], buf2[4096], buf3[4096], *p, *p2;
+   const char *mime;
+   FILE *f = fopen(file, "r");
+
+   if (!f) return;
+   while (fgets(buf, sizeof(buf), f))
+     {
+        // remove newline at end of line string if there
+        buf[sizeof(buf) - 1] = 0;
+        len = strlen(buf);
+        if ((len > 0) && (buf[len - 1] == '\n')) buf[len - 1] = 0;
+        // buf: "# comment"
+        // or
+        // buf: "mime/type:glob"
+        // ...
+        p = buf;
+        // find first token in line
+        while ((*p) && isspace(*p)) p++;
+        // if comment - skip line
+        if (*p == '#') continue;
+        p2 = p;
+        while ((*p2) && (*p2 != ':')) p2++;
+        // token is between p and p2 (not including p2)
+        strncpy(buf2, p, p2 - p);
+        buf2[p2 - p] = 0;
+        mime = eina_stringshare_add(buf2);
+        // buf2 is now the mime type token
+        eina_hash_del(mimes, buf2, NULL);
+        eina_hash_add(mimes, buf2, mime);
+        // now lookf for all extension tokens;
+        p = p2;
+        // find next token in line
+        while ((*p) && (*p == ':')) p++;
+        // find end of token
+        p2 = p;
+        while ((*p2) && !isspace(*p2)) p2++;
+        // buf3 is now the extension token
+        strncpy(buf3, p, p2 - p);
+        buf3[p2 - p] = 0;
+        // for a shortcut a glob of "*.xxx" is the same as just an ext of "xxx"
+        // so if this is the case then put into the extn mimes not
+        // the globl mimes for speed of lookup later on
+        if ((buf3[0] == '*') && (buf3[1] == '.') &&
+            (!strchr(buf3 + 2, '*')) && (!strchr(buf3 + 2, '?')) &&
+            (!strchr(buf3 + 2, '[')) && (!strchr(buf3 + 2, ']')) &&
+            (!strchr(buf3 + 2, '\\')))
+          {
+             eina_hash_del(extn_mimes, buf3 + 2, NULL);
+             eina_hash_add(extn_mimes, buf3 + 2, mime);
+          }
+        else
+          {
+             eina_hash_del(glob_mimes, buf3, NULL);
+             eina_hash_add(glob_mimes, buf3, mime);
+          }
+     }
+   fclose(f);
+}
+
+static void *
+find_off(const char *str, Eina_List *strlist, Eina_List *offlist)
+{
+   Eina_List *l, *ll;
+   const char *s;
+
+   ll = offlist;
+   EINA_LIST_FOREACH(strlist, l, s)
+     {
+        if (!strcmp(str, s)) return ll->data;
+        ll = ll->next;
+     }
+   return (void *)-1;
+}
+static void
+store_cache(const char *out)
+{
+   char buf[PATH_MAX];
+   FILE *f;
+   size_t mimes_str_len = 0;
+   size_t extn_mimes_str_len = 0;
+   size_t glob_mimes_str_len = 0;
+   size_t str_start;
+   Eina_List *mimes_str_offsets = NULL;
+   Eina_List *extn_mimes_str_offsets = NULL;
+   Eina_List *glob_mimes_str_offsets = NULL;
+   Eina_List *l, *ll;
+   const char *s;
+   void *ptr;
+   unsigned int val;
+
+   snprintf(buf, sizeof(buf), "%s.tmp", out);
+   f = fopen(buf, "wb");
+   if (!f) return;
+   // write file magic - first 16 bytes
+   fwrite("EfrEeT-MiMeS-001", 16, 1, f);
+   // note: all offsets are in bytes from start of file
+   // 
+   // "EfrEeT-MiMeS-001" <- magic 16 byte header
+   // [int] <- size of mimes array in number of entries
+   // [int] <- str byte offset of 1st mime string (sorted)
+   // [int] <- str byte offset of 2nd mime string
+   // ...
+   // [int] <- size of extn_mimes array in number of entries
+   // [int] <- str byte offset of 1st extn string (sorted)
+   // [int] <- str byte offset of 1st mime string
+   // [int] <- str byte offset of 2nd extn string
+   // [int] <- str byte offset of 2nd mine string
+   // ...
+   // [int] <- size of globs array in number of entries
+   // [int] <- str byte offset of 1st glob string (sorted)
+   // [int] <- str byte offset of 1st mime string
+   // [int] <- str byte offset of 2nd glob string
+   // [int] <- str byte offset of 2nd mime string
+   // ...
+   // strine1\0string2\0string3\0string4\0....
+   EINA_LIST_FOREACH(mimes_sorted, l, s)
+     {
+        mimes_str_offsets = eina_list_append(mimes_str_offsets,
+                                             (void *)mimes_str_len);
+        mimes_str_len += strlen(s) + 1;
+     }
+   EINA_LIST_FOREACH(extn_mimes_sorted, l, s)
+     {
+        extn_mimes_str_offsets = eina_list_append(extn_mimes_str_offsets,
+                                                  (void *)extn_mimes_str_len);
+        extn_mimes_str_len += strlen(s) + 1;
+     }
+   EINA_LIST_FOREACH(glob_mimes_sorted, l, s)
+     {
+        glob_mimes_str_offsets = eina_list_append(glob_mimes_str_offsets,
+                                                  (void *)glob_mimes_str_len);
+        glob_mimes_str_len += strlen(s) + 1;
+     }
+
+   str_start = 16 + // magic header
+   sizeof(int) +
+   (eina_list_count(mimes_sorted) * sizeof(int)) +
+   sizeof(int) +
+   (eina_list_count(extn_mimes_sorted) * sizeof(int) * 2) +
+   sizeof(int) +
+   (eina_list_count(glob_mimes_sorted) * sizeof(int) * 2);
+
+   val = eina_list_count(mimes_sorted);
+   fwrite(&val, sizeof(val), 1, f);
+   EINA_LIST_FOREACH(mimes_str_offsets, l, ptr)
+     {
+        val = (int)((long)ptr) + str_start;
+        fwrite(&val, sizeof(val), 1, f);
+     }
+
+   val = eina_list_count(extn_mimes_sorted);
+   fwrite(&val, sizeof(val), 1, f);
+   ll = extn_mimes_sorted;
+   EINA_LIST_FOREACH(extn_mimes_str_offsets, l, ptr)
+     {
+        val = (int)((long)ptr) + str_start + mimes_str_len;
+        fwrite(&val, sizeof(val), 1, f);
+        s = eina_hash_find(extn_mimes, ll->data);
+        ptr = find_off(s, mimes_sorted, mimes_str_offsets);
+        val = (int)((long)ptr) + str_start;
+        fwrite(&val, sizeof(val), 1, f);
+        ll = ll->next;
+     }
+
+   val = eina_list_count(glob_mimes_sorted);
+   fwrite(&val, sizeof(val), 1, f);
+   ll = glob_mimes_sorted;
+   EINA_LIST_FOREACH(glob_mimes_str_offsets, l, ptr)
+     {
+        val = (int)((long)ptr) + str_start + mimes_str_len + extn_mimes_str_len;
+        fwrite(&val, sizeof(val), 1, f);
+        s = eina_hash_find(glob_mimes, ll->data);
+        ptr = find_off(s, mimes_sorted, mimes_str_offsets);
+        val = (int)((long)ptr) + str_start;
+        fwrite(&val, sizeof(val), 1, f);
+        ll = ll->next;
+     }
+   EINA_LIST_FOREACH(mimes_sorted, l, s)
+     {
+        fwrite(s, strlen(s) + 1, 1, f);
+     }
+   EINA_LIST_FOREACH(extn_mimes_sorted, l, s)
+     {
+        fwrite(s, strlen(s) + 1, 1, f);
+     }
+   EINA_LIST_FOREACH(glob_mimes_sorted, l, s)
+     {
+        fwrite(s, strlen(s) + 1, 1, f);
+     }
+   fclose(f);
+   rename(buf, out);
+}
+
+int
+main(int argc, char **argv)
+{
+   char buf[PATH_MAX];
+   const char *s;
+   int i;
+   int ret = -1, lockfd = -1;
+   Eina_List *datadirs, *l;
+
+   if (!eina_init()) goto eina_error;
+   if (!eet_init()) goto eet_error;
+   if (!ecore_init()) goto ecore_error;
+   if (!ecore_file_init()) goto ecore_file_error;
+   if (!efreet_init()) goto efreet_error;
+
+   _efreet_mime_cache_log_dom =
+     eina_log_domain_register("efreet_mime_cache", EFREET_DEFAULT_LOG_COLOR);
+   if (_efreet_mime_cache_log_dom < 0)
+     {
+        EINA_LOG_ERR("Efreet: Could not create a log domain for efreet_mime_cache.");
+        return -1;
+     }
+
+   for (i = 1; i < argc; i++)
+     {
+        if (!strcmp(argv[i], "-v"))
+          eina_log_domain_level_set("efreet_mime_cache", EINA_LOG_LEVEL_DBG);
+        else if ((!strcmp(argv[i], "-h")) ||
+                 (!strcmp(argv[i], "-help")) ||
+                 (!strcmp(argv[i], "--h")) ||
+                 (!strcmp(argv[i], "--help")))
+          {
+             printf("Options:\n");
+             printf("  -v              Verbose mode\n");
+             printf("  -d dir1 dir2    Extra dirs\n");
+             exit(0);
+          }
+        else if (!strcmp(argv[i], "-d"))
+          {
+             while ((i < (argc - 1)) && (argv[(i + 1)][0] != '-'))
+               extra_dirs = eina_list_append(extra_dirs, argv[++i]);
+          }
+     }
+   extra_dirs = eina_list_sort(extra_dirs, -1, EINA_COMPARE_CB(strcmp));
+
+   /* create homedir */
+   snprintf(buf, sizeof(buf), "%s/efreet", efreet_cache_home_get());
+   if (!ecore_file_exists(buf))
+     {
+        if (!ecore_file_mkpath(buf)) goto error;
+        efreet_setowner(buf);
+     }
+
+   /* lock process, so that we only run one copy of this program */
+   lockfd = cache_lock_file();
+   if (lockfd == -1) goto error;
+
+   mimes = eina_hash_string_superfast_new(NULL);
+   extn_mimes = eina_hash_string_superfast_new(NULL);
+   glob_mimes = eina_hash_string_superfast_new(NULL);
+
+   etc_mime_types_load("/etc/mime.types");
+   share_mime_globs_load("/usr/share/mime/globs");
+   datadirs = efreet_data_dirs_get();
+   EINA_LIST_FOREACH(datadirs, l, s)
+     {
+        snprintf(buf, sizeof(buf), "%s/mime/globs", s);
+        share_mime_globs_load(buf);
+     }
+   EINA_LIST_FOREACH(extra_dirs, l, s)
+     {
+        snprintf(buf, sizeof(buf), "%s/mime/globs", s);
+        share_mime_globs_load(buf);
+     }
+   snprintf(buf, sizeof(buf), "%s/mime/globs", efreet_data_home_get());
+   share_mime_globs_load(buf);
+   // XXX: load user files and other dirs etc.
+   // XXX: load globs
+
+   hash_list_sort(mimes, &mimes_sorted);
+   hash_list_sort(extn_mimes, &extn_mimes_sorted);
+   hash_list_sort(glob_mimes, &glob_mimes_sorted);
+
+#ifdef WORDS_BIGENDIAN
+   snprintf(buf, sizeof(buf), "%s/efreet/mime_cache_%s.be.dat",
+            efreet_cache_home_get(), efreet_hostname_get());
+#else
+   snprintf(buf, sizeof(buf), "%s/efreet/mime_cache_%s.le.dat",
+            efreet_cache_home_get(), efreet_hostname_get());
+#endif
+   store_cache(buf);
+
+   ret = 0;
+   close(lockfd);
+error:
+   efreet_shutdown();
+efreet_error:
+   ecore_file_shutdown();
+ecore_file_error:
+   ecore_shutdown();
+ecore_error:
+   eet_shutdown();
+eet_error:
+   eina_list_free(extra_dirs);
+   eina_log_domain_unregister(_efreet_mime_cache_log_dom);
+   eina_shutdown();
+eina_error:
+   return ret;
+}
index fefc852..b1ef5e8 100644 (file)
@@ -71,6 +71,13 @@ static Eet_Data_Descriptor *subdir_dir_edd = NULL;
 static Subdir_Cache        *subdir_cache = NULL;
 static Eina_Bool            subdir_need_save = EINA_FALSE;
 
+static Eina_Hash *mime_monitors = NULL;
+static Ecore_Timer *mime_update_timer = NULL;
+static Ecore_Exe *mime_cache_exe = NULL;
+
+static void mime_cache_init(void);
+static void mime_cache_shutdown(void);
+
 static void
 subdir_cache_dir_free(Subdir_Cache_Dir *cd)
 {
@@ -756,6 +763,10 @@ cache_exe_data_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
         if ((ev->lines) && (*ev->lines->line == 'c')) update = EINA_TRUE;
         send_signal_icon_cache_update(update);
      }
+   else if (ev->exe == mime_cache_exe)
+     {
+        // XXX: ZZZ: handle stdout here from cache updater... if needed
+     }
    return ECORE_CALLBACK_RENEW;
 }
 
@@ -774,6 +785,11 @@ cache_exe_del_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
         icon_cache_exe = NULL;
         if (icon_queue) cache_icon_update(EINA_FALSE);
      }
+   else if (ev->exe == mime_cache_exe)
+     {
+        mime_cache_exe = NULL;
+        send_signal_mime_cache_build();
+     }
    return ECORE_CALLBACK_RENEW;
 }
 
@@ -838,6 +854,111 @@ cache_desktop_exists(void)
    return desktop_exists;
 }
 
+static void
+mime_update_launch(void)
+{
+   char file[PATH_MAX];
+
+   snprintf(file, sizeof(file),
+            "%s/efreet/" MODULE_ARCH "/efreet_mime_cache_create",
+            eina_prefix_lib_get(pfx));
+   mime_cache_exe = ecore_exe_pipe_run(file,
+                                       ECORE_EXE_PIPE_READ |
+                                       ECORE_EXE_PIPE_READ_LINE_BUFFERED,
+                                       NULL);
+}
+
+static Eina_Bool
+mime_update_cache_cb(void *data EINA_UNUSED)
+{
+   mime_update_timer = NULL;
+   if (mime_cache_exe)
+     {
+        ecore_exe_kill(mime_cache_exe);
+        ecore_exe_free(mime_cache_exe);
+     }
+   mime_update_launch();
+   return EINA_FALSE;
+}
+
+static void
+mime_changes_cb(void *data EINA_UNUSED, Ecore_File_Monitor *em EINA_UNUSED,
+                Ecore_File_Event event, const char *path EINA_UNUSED)
+{
+   switch (event)
+     {
+      case ECORE_FILE_EVENT_NONE:
+         /* noop */
+         break;
+
+      case ECORE_FILE_EVENT_CREATED_FILE:
+      case ECORE_FILE_EVENT_DELETED_FILE:
+      case ECORE_FILE_EVENT_MODIFIED:
+      case ECORE_FILE_EVENT_CLOSED:
+      case ECORE_FILE_EVENT_DELETED_DIRECTORY:
+      case ECORE_FILE_EVENT_CREATED_DIRECTORY:
+      case ECORE_FILE_EVENT_DELETED_SELF:
+        mime_cache_shutdown();
+        mime_cache_init();
+        if (mime_update_timer) ecore_timer_del(mime_update_timer);
+        mime_update_timer = ecore_timer_add(0.2, mime_update_cache_cb, NULL);
+        break;
+     }
+}
+
+static void
+mime_cache_init(void)
+{
+   Ecore_File_Monitor *mon;
+   Eina_List *datadirs, *l;
+   const char *s;
+   char buf[PATH_MAX];
+
+   mime_monitors = eina_hash_string_superfast_new(NULL);
+
+   mon = ecore_file_monitor_add("/etc/mime.types", mime_changes_cb, NULL);
+   if (mon) eina_hash_add(mime_monitors, "/etc/mime.types", mon);
+   mon = ecore_file_monitor_add("/usr/share/mime/globs", mime_changes_cb, NULL);
+   if (mon) eina_hash_add(mime_monitors, "/usr/share/mime/globs", mon);
+
+   datadirs = efreet_data_dirs_get();
+   EINA_LIST_FOREACH(datadirs, l, s)
+     {
+        snprintf(buf, sizeof(buf), "%s/mime/globs", s);
+        if (!eina_hash_find(mime_monitors, buf))
+          {
+             mon = ecore_file_monitor_add(buf, mime_changes_cb, NULL);
+             if (mon) eina_hash_add(mime_monitors, buf, mon);
+          }
+     }
+}
+
+static Eina_Bool
+mime_cache_monitor_del(const Eina_Hash *hash EINA_UNUSED,
+                       const void *key EINA_UNUSED, void *value,
+                       void *data EINA_UNUSED)
+{
+   Ecore_File_Monitor *mon = value;
+   ecore_file_monitor_del(mon);
+   return EINA_TRUE;
+}
+
+static void
+mime_cache_shutdown(void)
+{
+   if (mime_update_timer)
+     {
+        ecore_timer_del(mime_update_timer);
+        mime_update_timer = NULL;
+     }
+   if (mime_monitors)
+     {
+        eina_hash_foreach(mime_monitors, mime_cache_monitor_del, NULL);
+        eina_hash_free(mime_monitors);
+        mime_monitors = NULL;
+     }
+}
+
 Eina_Bool
 cache_init(void)
 {
@@ -875,6 +996,8 @@ cache_init(void)
    efreet_cache_update = 0;
    if (!efreet_init()) goto error;
    subdir_cache_init();
+   mime_cache_init();
+   mime_update_launch();
    read_lists();
    /* TODO: Should check if system dirs has changed and handles extra_dirs */
    desktop_system_dirs = efreet_default_dirs_get(efreet_data_home_get(),
@@ -906,6 +1029,7 @@ cache_shutdown(void)
    eina_prefix_free(pfx);
    pfx = NULL;
 
+   mime_cache_shutdown();
    subdir_cache_shutdown();
    efreet_shutdown();
 
index 2c483c5..533a33b 100644 (file)
@@ -190,6 +190,12 @@ send_signal_desktop_cache_build(void)
    _broadcast(ipc, 1 /* desktop cache build */, 1, NULL, 0);
 }
 
+void
+send_signal_mime_cache_build(void)
+{
+   _broadcast(ipc, 4 /* mime cache build */, 1, NULL, 0);
+}
+
 Eina_Bool
 ipc_init(void)
 {
index 6508f8f..e2b3b5a 100644 (file)
@@ -4,6 +4,7 @@
 void send_signal_icon_cache_update(Eina_Bool update);
 void send_signal_desktop_cache_update(Eina_Bool update);
 void send_signal_desktop_cache_build(void);
+void send_signal_mime_cache_build(void);
 
 Eina_Bool ipc_init(void);
 Eina_Bool ipc_shutdown(void);
diff --git a/src/examples/elementary/codegen_example_generated.c b/src/examples/elementary/codegen_example_generated.c
deleted file mode 100644 (file)
index 8ce305e..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-#include "codegen_example_generated.h"
-
-Evas_Object *
-codegen_example_layout_add(Evas_Object *o, Elm_Theme *th, const char *edje_file)
-{
-   Evas_Object *l;
-
-   if (edje_file)
-     elm_theme_extension_add(th, edje_file);
-   else
-     elm_theme_extension_add(th, "./codegen_example.edj");
-
-   l = elm_layout_add(o);
-   if (!l) return NULL;
-
-   if (!elm_layout_theme_set(l, "example", "mylayout", "default"))
-     {
-        evas_object_del(l);
-        return NULL;
-     }
-
-   return l;
-}
-
-void
-codegen_example_title_set(Evas_Object *o, const char *value)
-{
-   elm_layout_text_set(o, "example/title", value);
-}
-
-const char *
-codegen_example_title_get(const Evas_Object *o)
-{
-   return elm_layout_text_get(o, "example/title");
-}
-
-void
-codegen_example_custom_set(Evas_Object *o, Evas_Object *value)
-{
-   elm_layout_content_set(o, "example/custom", value);
-}
-
-Evas_Object *
-codegen_example_custom_unset(Evas_Object *o)
-{
-   return elm_layout_content_unset(o, "example/custom");
-}
-
-Evas_Object *
-codegen_example_custom_get(const Evas_Object *o)
-{
-   return elm_layout_content_get(o, "example/custom");
-}
-
-Eina_Bool
-codegen_example_box_append(Evas_Object *o, Evas_Object *child)
-{
-   return elm_layout_box_append(o, "example/box", child);
-}
-
-Eina_Bool
-codegen_example_box_prepend(Evas_Object *o, Evas_Object *child)
-{
-   return elm_layout_box_prepend(o, "example/box", child);
-}
-
-Eina_Bool
-codegen_example_box_insert_before(Evas_Object *o, Evas_Object *child, const Evas_Object *reference)
-{
-   return elm_layout_box_insert_before(o, "example/box", child, reference);
-}
-
-Eina_Bool
-codegen_example_box_insert_at(Evas_Object *o, Evas_Object *child, unsigned int pos)
-{
-   return elm_layout_box_insert_at(o, "example/box", child, pos);
-}
-
-Evas_Object *
-codegen_example_box_remove(Evas_Object *o, Evas_Object *child)
-{
-   return elm_layout_box_remove(o, "example/box", child);
-}
-
-Eina_Bool
-codegen_example_box_remove_all(Evas_Object *o, Eina_Bool clear)
-{
-   return elm_layout_box_remove_all(o, "example/box", clear);
-}
-
-Eina_Bool
-codegen_example_table_pack(Evas_Object *o, Evas_Object *child, unsigned short col, unsigned short row, unsigned short colspan, unsigned short rowspan)
-{
-   return elm_layout_table_pack(o, "example/table", child, col, row, colspan, rowspan);
-}
-
-Evas_Object *
-codegen_example_table_unpack(Evas_Object *o, Evas_Object *child)
-{
-   return elm_layout_table_unpack(o, "example/table", child);
-}
-
-Eina_Bool
-codegen_example_table_clear(Evas_Object *o, Eina_Bool clear)
-{
-   return elm_layout_table_clear(o, "example/table", clear);
-}
-
-void
-codegen_example_swallow_grow_emit(Evas_Object *o)
-{
-   elm_layout_signal_emit(o, "button,enlarge", "");
-}
-
-void
-codegen_example_swallow_shrink_emit(Evas_Object *o)
-{
-   elm_layout_signal_emit(o, "button,reduce", "");
-}
-
-void
-codegen_example_size_changed_callback_add(Evas_Object *o, Edje_Signal_Cb func, void *data)
-{
-   elm_layout_signal_callback_add(o, "size,changed", "", func, data);
-}
-
-void
-codegen_example_size_changed_callback_del(Evas_Object *o, Edje_Signal_Cb func)
-{
-   elm_layout_signal_callback_del(o, "size,changed", "", func);
-}
-
diff --git a/src/examples/elementary/codegen_example_generated.h b/src/examples/elementary/codegen_example_generated.h
deleted file mode 100644 (file)
index b8fbc4e..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-#ifndef _CODEGEN_EXAMPLE_GENERATED_H
-#define _CODEGEN_EXAMPLE_GENERATED_H
-
-#include <Edje.h>
-#include <Elementary.h>
-#include <Evas.h>
-
-#include <stdlib.h>
-
-/**
- * @brief Creates the layout object and set the theme
- * @param o The parent
- * @param th The theme to add to, or if NULL, the default theme
- * @param edje_file The path to edj, if NULL it's used the path given
- *                  to elementary_codegen
- */
-Evas_Object *codegen_example_layout_add(Evas_Object *o, Elm_Theme *th, const char *edje_file);
-
-/**
- * @brief The example title
- */
-void codegen_example_title_set(Evas_Object *o, const char *value);
-const char *codegen_example_title_get(const Evas_Object *o);
-
-/**
- * @brief The swallow part
- */
-void codegen_example_custom_set(Evas_Object *o, Evas_Object *value);
-Evas_Object *codegen_example_custom_unset(Evas_Object *o);
-Evas_Object *codegen_example_custom_get(const Evas_Object *o);
-
-/**
- * @brief The box part
- */
-Eina_Bool codegen_example_box_append(Evas_Object *o, Evas_Object *child);
-Eina_Bool codegen_example_box_prepend(Evas_Object *o, Evas_Object *child);
-Eina_Bool codegen_example_box_insert_before(Evas_Object *o, Evas_Object *child, const Evas_Object *reference);
-Eina_Bool codegen_example_box_insert_at(Evas_Object *o, Evas_Object *child, unsigned int pos);
-Evas_Object *codegen_example_box_remove(Evas_Object *o, Evas_Object *child);
-Eina_Bool codegen_example_box_remove_all(Evas_Object *o, Eina_Bool clear);
-
-/**
- * @brief The table part
- */
-Eina_Bool codegen_example_table_pack(Evas_Object *o, Evas_Object *child, unsigned short col, unsigned short row, unsigned short colspan, unsigned short rowspan);
-Evas_Object *codegen_example_table_unpack(Evas_Object *o, Evas_Object *child);
-Eina_Bool codegen_example_table_clear(Evas_Object *o, Eina_Bool clear);
-
-/**
- * @brief Executed when the button enlarges
- */
-void codegen_example_swallow_grow_emit(Evas_Object *o);
-
-/**
- * @brief Executed when the button reduces
- */
-void codegen_example_swallow_shrink_emit(Evas_Object *o);
-
-/**
- * @brief Emit the signal size,changed
- */
-void codegen_example_size_changed_callback_add(Evas_Object *o, Edje_Signal_Cb func, void *data);
-void codegen_example_size_changed_callback_del(Evas_Object *o, Edje_Signal_Cb func);
-
-#endif /* _CODEGEN_EXAMPLE_GENERATED_H */
index f8d5e5c..de4ca74 100644 (file)
@@ -203,6 +203,8 @@ _icon_desktop_cache_update_event_add(int event_type)
    ecore_event_add(event_type, ev, icon_cache_update_free, l);
 }
 
+EAPI void (*_efreet_mime_update_func) (void) = NULL;
+
 static Eina_Bool
 _cb_server_data(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
 {
@@ -223,6 +225,10 @@ _cb_server_data(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
      {
         _icon_desktop_cache_update_event_add(EFREET_EVENT_DESKTOP_CACHE_UPDATE);
      }
+   else if (e->major == 4) // mime cache update
+     {
+        if (_efreet_mime_update_func) _efreet_mime_update_func();
+     }
    return ECORE_CALLBACK_DONE;
 }
 
index 87ca8ef..4426b6a 100644 (file)
@@ -32,11 +32,8 @@ static int _efreet_mime_log_dom = -1;
 #include "Efreet_Mime.h"
 #include "efreet_private.h"
 
-static Eina_List *globs = NULL;     /* contains Efreet_Mime_Glob structs */
-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_List *magics = NULL;    // contains Efreet_Mime_Magic structs
+static Eina_Hash *mime_icons = NULL; // contains cache with mime->icons
 static Eina_Inlist *mime_icons_lru = NULL;
 static unsigned int _efreet_mime_init_count = 0;
 
@@ -89,13 +86,6 @@ static enum
  */
 //#define EFREET_MIME_ICONS_DEBUG
 
-typedef struct Efreet_Mime_Glob Efreet_Mime_Glob;
-struct Efreet_Mime_Glob
-{
-   const char *glob;
-   const char *mime;
-};
-
 typedef struct Efreet_Mime_Magic Efreet_Mime_Magic;
 struct Efreet_Mime_Magic
 {
@@ -134,9 +124,6 @@ struct Efreet_Mime_Icon_Entry
    unsigned int size;
 };
 
-static int efreet_mime_glob_remove(const char *glob);
-static void efreet_mime_mime_types_load(const char *file);
-static void efreet_mime_shared_mimeinfo_globs_load(const char *file);
 static void efreet_mime_shared_mimeinfo_magic_load(const char *file);
 static void efreet_mime_shared_mimeinfo_magic_parse(char *data, int size);
 static const char *efreet_mime_magic_check_priority(const char *file,
@@ -145,19 +132,12 @@ static const char *efreet_mime_magic_check_priority(const char *file,
 static int efreet_mime_init_files(void);
 static const char *efreet_mime_special_check(const char *file);
 static const char *efreet_mime_fallback_check(const char *file);
-static void efreet_mime_glob_free(void *data);
 static void efreet_mime_magic_free(void *data);
 static void efreet_mime_magic_entry_free(void *data);
 static int efreet_mime_glob_match(const char *str, const char *glob);
 static int efreet_mime_glob_case_match(char *str, const char *glob);
 static int efreet_mime_endian_check(void);
 
-static void efreet_mime_monitor_add(const char *file);
-static void efreet_mime_cb_update_file(void *data,
-                                       Ecore_File_Monitor *monitor,
-                                       Ecore_File_Event event,
-                                       const char *path);
-
 static void efreet_mime_icons_flush(double now);
 static void efreet_mime_icon_entry_head_free(Efreet_Mime_Icon_Entry_Head *entry);
 static void efreet_mime_icon_entry_add(const char *mime,
@@ -169,6 +149,218 @@ static const char *efreet_mime_icon_entry_find(const char *mime,
                                                unsigned int size);
 static void efreet_mime_icons_debug(void);
 
+
+
+
+
+
+
+
+
+
+
+
+static Eina_File *mimedb = NULL;
+static unsigned char *mimedb_ptr = NULL;
+static size_t mimedb_size = 0;
+
+static void
+_efreet_mimedb_shutdown(void)
+{
+   if (mimedb)
+     {
+        if (mimedb_ptr) eina_file_map_free(mimedb, mimedb_ptr);
+        eina_file_close(mimedb);
+        mimedb = NULL;
+        mimedb_ptr = NULL;
+        mimedb_size = 0;
+     }
+}
+
+static void
+_efreet_mimedb_update(void)
+{
+   char buf[PATH_MAX];
+
+   if (mimedb)
+     {
+        if (mimedb_ptr) eina_file_map_free(mimedb, mimedb_ptr);
+        eina_file_close(mimedb);
+        mimedb = NULL;
+        mimedb_ptr = NULL;
+        mimedb_size = 0;
+     }
+#ifdef WORDS_BIGENDIAN
+   snprintf(buf, sizeof(buf), "%s/efreet/mime_cache_%s.be.dat",
+            efreet_cache_home_get(), efreet_hostname_get());
+#else
+   snprintf(buf, sizeof(buf), "%s/efreet/mime_cache_%s.le.dat",
+            efreet_cache_home_get(), efreet_hostname_get());
+#endif
+   mimedb = eina_file_open(buf, EINA_FALSE);
+   if (mimedb)
+     {
+        mimedb_ptr = eina_file_map_all(mimedb, EINA_FILE_POPULATE);
+        if (mimedb_ptr)
+          {
+             mimedb_size = eina_file_size_get(mimedb);
+             if ((mimedb_size > (16 + 4  + 4  + 4) &&
+                 (!strncmp((char *)mimedb_ptr, "EfrEeT-MiMeS-001", 16))))
+               {
+                  // load ok - magic fine. more sanity checks?
+               }
+             else
+               {
+                  eina_file_map_free(mimedb, mimedb_ptr);
+                  mimedb_ptr = NULL;
+                  eina_file_close(mimedb);
+                  mimedb = NULL;
+                  mimedb_size = 0;
+               }
+          }
+        else
+          {
+             eina_file_close(mimedb);
+             mimedb = NULL;
+          }
+     }
+}
+
+static const char *
+_efreet_mimedb_str_get(unsigned int offset)
+{
+   if (offset < (16 + 4 + 4 + 4)) return NULL;
+   if (offset >= mimedb_size) return NULL;
+   return (const char *)(mimedb_ptr + offset);
+}
+
+static unsigned int
+_efreet_mimedb_uint_get(unsigned int index)
+// index is the unit NUMBER AFTER the header
+{
+   unsigned int *ptr;
+   ptr = ((unsigned int *)(mimedb_ptr + 16)) + index;
+   if ((size_t)(((unsigned char *)ptr) - mimedb_ptr) >= (mimedb_size - 4))
+     return 0;
+   return *ptr;
+}
+
+static unsigned int
+_efreet_mimedb_mime_count(void)
+{
+   return _efreet_mimedb_uint_get(0);
+}
+
+/**** currently unused - here for symmetry and future use
+static const char *
+_efreet_mimedb_mime_get(unsigned int num)
+{
+   unsigned int offset = _efreet_mimedb_uint_get
+     (1 + num);
+   return  _efreet_mimedb_str_get(offset);
+}
+*/
+
+static unsigned int
+_efreet_mimedb_extn_count(void)
+{
+   return _efreet_mimedb_uint_get(1 + _efreet_mimedb_mime_count());
+}
+
+static const char *
+_efreet_mimedb_extn_get(unsigned int num)
+{
+   unsigned int offset = _efreet_mimedb_uint_get
+     (1 + _efreet_mimedb_mime_count() + 1 + (num * 2));
+   return  _efreet_mimedb_str_get(offset);
+}
+
+static const char *
+_efreet_mimedb_extn_mime_get(unsigned int num)
+{
+   unsigned int offset = _efreet_mimedb_uint_get
+     (1 + _efreet_mimedb_mime_count() + 1 + (num * 2) + 1);
+   return  _efreet_mimedb_str_get(offset);
+}
+
+static const char *
+_efreet_mimedb_extn_find(const char *extn)
+{
+   unsigned int i, begin, end;
+   const char *s;
+
+   // binary search keys to get value
+   begin = 0;
+   end = _efreet_mimedb_extn_count();
+   i = (begin + end) / 2;
+   for (;;)
+     {
+        s = _efreet_mimedb_extn_get(i);
+        if (s)
+          {
+             int v = strcmp(extn, s);
+             if (v < 0)
+               {
+                  end = i;
+                  i = (begin + end) / 2;
+                  if ((end - begin) == 0) break;
+               }
+             else if (v > 0)
+               {
+                  if ((end - begin) > 1)
+                    {
+                       begin = i;
+                       i = (begin + end) / 2;
+                       if (i == end) break;
+                    }
+                  else
+                    {
+                       if ((end - begin) == 0) break;
+                       begin = end;
+                       i = end;
+                    }
+               }
+             else if (v == 0)
+               return _efreet_mimedb_extn_mime_get(i);
+          }
+        else
+          {
+             break;
+          }
+     }
+   return NULL;
+}
+
+static unsigned int
+_efreet_mimedb_glob_count(void)
+{
+   return _efreet_mimedb_uint_get
+     (1 + _efreet_mimedb_mime_count() +
+      1 + (_efreet_mimedb_extn_count() * 2));
+}
+
+static const char *
+_efreet_mimedb_glob_get(unsigned int num)
+{
+   unsigned int offset = _efreet_mimedb_uint_get
+     (1 + _efreet_mimedb_mime_count() +
+      1 + (_efreet_mimedb_extn_count() * 2) +
+      1 + (num * 2));
+   return  _efreet_mimedb_str_get(offset);
+}
+
+static const char *
+_efreet_mimedb_glob_mime_get(unsigned int num)
+{
+   unsigned int offset = _efreet_mimedb_uint_get
+     (1 + _efreet_mimedb_mime_count() +
+      1 + (_efreet_mimedb_extn_count() * 2) +
+      1 + (num * 2) + 1);
+   return  _efreet_mimedb_str_get(offset);
+}
+
+/** --------------------------------- **/
+
 EAPI int
 efreet_mime_init(void)
 {
@@ -194,14 +386,15 @@ efreet_mime_init(void)
      }
 
    efreet_mime_endianess = efreet_mime_endian_check();
-
-   monitors = eina_hash_string_superfast_new(EINA_FREE_CB(ecore_file_monitor_del));
-
    efreet_mime_type_cache_clear();
 
+   _efreet_mimedb_update();
+
    if (!efreet_mime_init_files())
      goto unregister_log_domain;
 
+   _efreet_mime_update_func = _efreet_mimedb_update;
+
    return _efreet_mime_init_count;
 
 unregister_log_domain:
@@ -228,6 +421,9 @@ efreet_mime_shutdown(void)
    if (--_efreet_mime_init_count != 0)
      return _efreet_mime_init_count;
 
+   _efreet_mimedb_shutdown();
+   _efreet_mime_update_func = NULL;
+
    efreet_mime_icons_debug();
 
    IF_RELEASE(_mime_inode_symlink);
@@ -241,10 +437,7 @@ efreet_mime_shutdown(void)
    IF_RELEASE(_mime_application_octet_stream);
    IF_RELEASE(_mime_text_plain);
 
-   IF_FREE_LIST(globs, efreet_mime_glob_free);
    IF_FREE_LIST(magics, efreet_mime_magic_free);
-   IF_FREE_HASH(monitors);
-   IF_FREE_HASH(wild);
    IF_FREE_HASH(mime_icons);
    eina_log_domain_unregister(_efreet_mime_log_dom);
    _efreet_mime_log_dom = -1;
@@ -387,11 +580,10 @@ efreet_mime_magic_type_get(const char *file)
 EAPI const char *
 efreet_mime_globs_type_get(const char *file)
 {
-   Eina_List *l;
-   Efreet_Mime_Glob *g;
    char *sl, *p;
-   const char *s;
-   char *ext, *mime;
+   const char *s, *mime;
+   char *ext;
+   unsigned int i, n;
 
    EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL);
 
@@ -406,25 +598,27 @@ efreet_mime_globs_type_get(const char *file)
         while (p)
           {
              p++;
-             if (p && (mime = eina_hash_find(wild, p))) return mime;
+             if (p && (mime = _efreet_mimedb_extn_find(p))) return mime;
              p = strchr(p, '.');
           }
      }
 
-   /* Fallback to the other globs if not found */
-   EINA_LIST_FOREACH(globs, l, g)
+   // Fallback to the other globs if not found
+   n = _efreet_mimedb_glob_count();
+   for (i = 0; i < n; i++)
      {
-        if (efreet_mime_glob_match(file, g->glob))
-          return g->mime;
+        s = _efreet_mimedb_glob_get(i);
+        if (efreet_mime_glob_match(file, s))
+          return _efreet_mimedb_glob_mime_get(i);
      }
-
    ext = alloca(strlen(file) + 1);
    for (s = file, p = ext; *s; s++, p++) *p = tolower(*s);
    *p = 0;
-   EINA_LIST_FOREACH(globs, l, g)
+   for (i = 0; i < n; i++)
      {
-        if (efreet_mime_glob_case_match(ext, g->glob))
-          return g->mime;
+        s = _efreet_mimedb_glob_get(i);
+        if (efreet_mime_glob_case_match(ext, s))
+          return _efreet_mimedb_glob_mime_get(i);
      }
    return NULL;
 }
@@ -457,72 +651,6 @@ efreet_mime_endian_check(void)
 
 /**
  * @internal
- * @param file File to monitor
- * @return Returns no value.
- * @brief Creates a new file monitor if we aren't already monitoring the
- * given file
- */
-static void
-efreet_mime_monitor_add(const char *file)
-{
-   Ecore_File_Monitor *fm = NULL;
-
-   /* if this is already in our hash then we're already monitoring so no
-    * reason to re-monitor */
-   if (eina_hash_find(monitors, file))
-     return;
-
-   if ((fm = ecore_file_monitor_add(file, efreet_mime_cb_update_file, NULL)))
-     {
-        eina_hash_del(monitors, file, NULL);
-        eina_hash_add(monitors, file, fm);
-     }
-}
-
-/**
- * @internal
- * @param datadirs List of XDG data dirs
- * @param datahome Path to XDG data home directory
- * @return Returns no value
- * @brief Read all glob files in XDG data/home dirs.
- * Also reads the /etc/mime.types file.
- */
-static void
-efreet_mime_load_globs(Eina_List *datadirs, const char *datahome)
-{
-   Eina_List *l;
-   char buf[4096];
-   const char *datadir = NULL;
-
-   IF_FREE_HASH(wild);
-   wild = eina_hash_string_superfast_new(EINA_FREE_CB(eina_stringshare_del));
-   while (globs)
-     {
-        efreet_mime_glob_free(eina_list_data_get(globs));
-        globs = eina_list_remove_list(globs, globs);
-     }
-
-   /*
-    * This is here for legacy reasons.  It is mentioned briefly
-    * in the spec and seems to still be quite valid.  It is
-    * loaded first so the globs files will override anything
-    * in here.
-    */
-   efreet_mime_mime_types_load("/etc/mime.types");
-
-   datadir = datahome;
-   snprintf(buf, sizeof(buf), "%s/mime/globs", datadir);
-   efreet_mime_shared_mimeinfo_globs_load(buf);
-
-   EINA_LIST_FOREACH(datadirs, l, datadir)
-     {
-        snprintf(buf, sizeof(buf), "%s/mime/globs", datadir);
-        efreet_mime_shared_mimeinfo_globs_load(buf);
-     }
-}
-
-/**
- * @internal
  * @param datadirs List of XDG data dirs
  * @param datahome Path to XDG data home directory
  * @return Returns no value
@@ -554,39 +682,6 @@ efreet_mime_load_magics(Eina_List *datadirs, const char *datahome)
 
 /**
  * @internal
- * @param data Data pointer passed to monitor_add
- * @param monitor Ecore_File_Monitor associated with this event
- * @param event The type of event
- * @param path Path to the file that was updated
- * @return Returns no value
- * @brief Callback for all file monitors.  Just reloads the appropriate
- * list depending on which file changed.  If it was a magic file
- * only the magic list is updated.  If it was a glob file or /etc/mime.types,
- * the globs are updated.
- */
-static void
-efreet_mime_cb_update_file(void *data EINA_UNUSED,
-                           Ecore_File_Monitor *monitor EINA_UNUSED,
-                           Ecore_File_Event event EINA_UNUSED,
-                           const char *path)
-{
-   Eina_List *datadirs = NULL;
-   const char *datahome = NULL;
-
-   if (!(datahome = efreet_data_home_get()))
-     return;
-
-   if (!(datadirs = efreet_data_dirs_get()))
-     return;
-
-   if (strstr(path, "magic"))
-     efreet_mime_load_magics(datadirs, datahome);
-   else
-     efreet_mime_load_globs(datadirs, datahome);
-}
-
-/**
- * @internal
  * @param datadirs List of XDG data dirs
  * @param datahome Path to XDG data home directory
  * @return Returns 1 on success, 0 on failure
@@ -595,10 +690,8 @@ efreet_mime_cb_update_file(void *data EINA_UNUSED,
 static int
 efreet_mime_init_files(void)
 {
-   Eina_List *l;
    Eina_List *datadirs = NULL;
-   char buf[PATH_MAX];
-   const char *datahome, *datadir = NULL;
+   const char *datahome;
 
    if (!(datahome = efreet_data_home_get()))
      return 0;
@@ -606,32 +699,15 @@ efreet_mime_init_files(void)
    if (!(datadirs = efreet_data_dirs_get()))
      return 0;
 
-   /*
-    * Add our file monitors
-    * We watch the directories so we can watch for new files
-    */
-   datadir = datahome;
-   snprintf(buf, sizeof(buf), "%s/mime", datadir);
-   efreet_mime_monitor_add(buf);
-
-   EINA_LIST_FOREACH(datadirs, l, datadir)
-     {
-        snprintf(buf, sizeof(buf), "%s/mime", datadir);
-        efreet_mime_monitor_add(buf);
-     }
-   efreet_mime_monitor_add("/etc/mime.types");
-
-   /* Load our mime information */
-   efreet_mime_load_globs(datadirs, datahome);
    efreet_mime_load_magics(datadirs, datahome);
 
-   _mime_inode_symlink            = eina_stringshare_add("inode/symlink");
-   _mime_inode_fifo               = eina_stringshare_add("inode/fifo");
-   _mime_inode_chardevice         = eina_stringshare_add("inode/chardevice");
-   _mime_inode_blockdevice        = eina_stringshare_add("inode/blockdevice");
-   _mime_inode_socket             = eina_stringshare_add("inode/socket");
-   _mime_inode_mountpoint         = eina_stringshare_add("inode/mountpoint");
-   _mime_inode_directory          = eina_stringshare_add("inode/directory");
+   _mime_inode_symlink            = eina_stringshare_add("inode/symlink");
+   _mime_inode_fifo               = eina_stringshare_add("inode/fifo");
+   _mime_inode_chardevice         = eina_stringshare_add("inode/chardevice");
+   _mime_inode_blockdevice        = eina_stringshare_add("inode/blockdevice");
+   _mime_inode_socket             = eina_stringshare_add("inode/socket");
+   _mime_inode_mountpoint         = eina_stringshare_add("inode/mountpoint");
+   _mime_inode_directory          = eina_stringshare_add("inode/directory");
    _mime_application_x_executable = eina_stringshare_add("application/x-executable");
    _mime_application_octet_stream = eina_stringshare_add("application/octet-stream");
    _mime_text_plain               = eina_stringshare_add("text/plain");
@@ -781,198 +857,6 @@ efreet_mime_fallback_check(const char *file)
 
 /**
  * @internal
- * @param glob Glob to search for
- * @return Returns 1 on success, 0 on failure
- * @brief Removes a glob from the list
- */
-static int
-efreet_mime_glob_remove(const char *glob)
-{
-   Efreet_Mime_Glob *mime = NULL;
-
-   if ((mime = eina_list_search_unsorted(globs, EINA_COMPARE_CB(strcmp), glob)))
-     {
-        globs = eina_list_remove(globs, mime);
-        IF_RELEASE(mime->glob);
-        IF_RELEASE(mime->mime);
-        FREE(mime);
-        return 1;
-     }
-
-   return 0;
-}
-
-static inline const char *
-efreet_eat_space(const char *head, const Eina_File_Line *ln, Eina_Bool not)
-{
-   if (not)
-     {
-        while (!isspace(*head) && (head < ln->end))
-          head++;
-     }
-   else
-     {
-        while (isspace(*head) && (head < ln->end))
-          head++;
-     }
-
-   return head;
-}
-
-/**
- * @internal
- * @param file mime.types file to load
- * @return Returns no value
- * @brief Loads values from a mime.types style file
- * into the globs list.
- * @note Format:
- * application/msaccess     mdb
- * application/msword       doc dot
- */
-static void
-efreet_mime_mime_types_load(const char *file)
-{
-   const Eina_File_Line *ln;
-   Eina_Iterator *it;
-   Eina_File *f;
-   const char *head_line;
-   const char *word_start;
-   const char *mimetype;
-
-   EINA_SAFETY_ON_NULL_RETURN(file);
-   f = eina_file_open(file, 0);
-   if (!f) return;
-
-   it = eina_file_map_lines(f);
-   if (it)
-     {
-        Eina_Strbuf *ext;
-
-        ext = eina_strbuf_new();
-
-        EINA_ITERATOR_FOREACH(it, ln)
-          {
-             head_line = efreet_eat_space(ln->start, ln, EINA_FALSE);
-             if (head_line == ln->end) continue ;
-
-             if (*head_line == '#') continue ;
-
-             word_start = head_line;
-             head_line = efreet_eat_space(head_line, ln, EINA_TRUE);
-
-             if (head_line == ln->end) continue ;
-             mimetype = eina_stringshare_add_length(word_start, head_line - word_start);
-             do
-               {
-                  head_line = efreet_eat_space(head_line, ln, EINA_FALSE);
-                  if (head_line == ln->end) break ;
-
-                  word_start = head_line;
-                  head_line = efreet_eat_space(head_line, ln, EINA_TRUE);
-
-                  eina_strbuf_append_length(ext, word_start, head_line - word_start);
-
-                  eina_hash_del(wild,
-                                eina_strbuf_string_get(ext),
-                                NULL);
-                  eina_hash_add(wild,
-                                eina_strbuf_string_get(ext),
-                                eina_stringshare_ref(mimetype));
-
-                  eina_strbuf_reset(ext);
-               }
-             while (head_line < ln->end);
-
-             eina_stringshare_del(mimetype);
-          }
-
-        eina_strbuf_free(ext);
-        eina_iterator_free(it);
-     }
-   eina_file_close(f);
-}
-
-/**
- * @internal
- * @param file globs file to load
- * @return Returns no value
- * @brief Loads values from a mime.types style file
- * into the globs list.
- * @note Format:
- * text/vnd.wap.wml:*.wml
- * application/x-7z-compressed:*.7z
- * application/vnd.corel-draw:*.cdr
- * text/spreadsheet:*.sylk
- */
-static void
-efreet_mime_shared_mimeinfo_globs_load(const char *file)
-{
-   FILE *f = NULL;
-   char buf[4096], mimetype[4096], ext[4096], *p, *pp;
-   Efreet_Mime_Glob *mime = NULL;
-
-   f = fopen(file, "rb");
-   if (!f) return;
-
-   while (fgets(buf, sizeof(buf), f))
-     {
-        p = buf;
-        while (isspace(*p) && (*p != 0) && (*p != '\n')) p++;
-
-        if (*p == '#') continue;
-        if ((*p == '\n') || (*p == 0)) continue;
-
-        pp = p;
-        while ((*p != ':') && (*p != 0) && (*p != '\n')) p++;
-
-        if ((*p == '\n') || (*p == 0)) continue;
-        strncpy(mimetype, pp, (p - pp));
-        mimetype[p - pp] = 0;
-        p++;
-        pp = ext;
-
-        while ((*p != 0) && (*p != '\n'))
-          {
-             *pp = *p;
-             pp++;
-             p++;
-          }
-
-        *pp = 0;
-
-        if (ext[0] == '*' && ext[1] == '.')
-          {
-             eina_hash_del(wild, &(ext[2]), NULL);
-             eina_hash_add(wild, &(ext[2]),
-                           (void*)eina_stringshare_add(mimetype));
-          }
-        else
-          {
-             mime = NEW(Efreet_Mime_Glob, 1);
-             if (mime)
-               {
-                  mime->mime = eina_stringshare_add(mimetype);
-                  mime->glob = eina_stringshare_add(ext);
-                  if ((!mime->mime) || (!mime->glob))
-                    {
-                       IF_RELEASE(mime->mime);
-                       IF_RELEASE(mime->glob);
-                       FREE(mime);
-                    }
-                  else
-                    {
-                       efreet_mime_glob_remove(ext);
-                       globs = eina_list_append(globs, mime);
-                    }
-               }
-          }
-     }
-
-   fclose(f);
-}
-
-/**
- * @internal
  * @param in Number to count the digits
  * @return Returns number of digits
  * @brief Calculates and returns the number of digits
@@ -1341,22 +1225,6 @@ efreet_mime_magic_check_priority(const char *file,
  * @internal
  * @param data Data pointer that is being destroyed
  * @return Returns no value
- * @brief Callback for globs destroy
- */
-static void
-efreet_mime_glob_free(void *data)
-{
-   Efreet_Mime_Glob *m = data;
-
-   IF_RELEASE(m->mime);
-   IF_RELEASE(m->glob);
-   IF_FREE(m);
-}
-
-/**
- * @internal
- * @param data Data pointer that is being destroyed
- * @return Returns no value
  * @brief Callback for magics destroy
  */
 static void
index 139754d..47d6dea 100644 (file)
@@ -251,6 +251,8 @@ EAPI void efreet_fsetowner(int fd);
 
 EAPI extern int efreet_cache_update;
 
+EAPI extern void (*_efreet_mime_update_func) (void);
+
 #undef EAPI
 #define EAPI