raster pushed a commit to branch master.

http://git.enlightenment.org/core/enlightenment.git/commit/?id=c28e58284a4a93520c1f5e949c2c5219d475d75e

commit c28e58284a4a93520c1f5e949c2c5219d475d75e
Author: Carsten Haitzler (Rasterman) <ras...@rasterman.com>
Date:   Tue Feb 24 18:36:31 2015 +0900

    efm - make dir listing far faster - no file magic content and dont sync
    
    this speed sup dir listing in efm drastically. first the e fm back end
    uses an io thread that just spools through everything fast and sends
    it over the mainloop to then send by ipc to e.
    
    and on the e side we no longer use the heavy file internal magic using
    api calls that wander all over a file for magic numbers - this is
    insanely slow and brings listing to a crawl.
---
 src/bin/e_fm.c          |  13 +-
 src/bin/e_fm/e_fm_ipc.c | 306 ++++++++++++++++--------------------------------
 src/bin/e_fm_op.h       |   2 +-
 3 files changed, 110 insertions(+), 211 deletions(-)

diff --git a/src/bin/e_fm.c b/src/bin/e_fm.c
index 5c8c1b0..7b82826 100644
--- a/src/bin/e_fm.c
+++ b/src/bin/e_fm.c
@@ -4584,6 +4584,15 @@ _e_fm2_icon_geom_adjust(E_Fm2_Icon *ic, int saved_x, int 
saved_y, int saved_w __
    ic->y = y;
 }
 
+static const char *
+_mime_get(const char *path)
+{
+   const char *mime = efreet_mime_special_type_get(path);
+   if (!mime) mime = efreet_mime_globs_type_get(path);
+   if (!mime) mime = efreet_mime_fallback_type_get(path);
+   return mime;
+}
+
 static int
 _e_fm2_icon_fill(E_Fm2_Icon *ic, E_Fm2_Finfo *finf)
 {
@@ -4614,7 +4623,7 @@ _e_fm2_icon_fill(E_Fm2_Icon *ic, E_Fm2_Finfo *finf)
      }
    else if (ic->info.real_link)
      {
-        mime = efreet_mime_type_get(ic->info.real_link);
+        mime = _mime_get(ic->info.real_link);
         if (!mime)
           /* XXX REMOVE/DEPRECATE ME LATER */
           mime = e_fm_mime_filename_get(ic->info.file);
@@ -4623,7 +4632,7 @@ _e_fm2_icon_fill(E_Fm2_Icon *ic, E_Fm2_Finfo *finf)
 
    if (!ic->info.mime)
      {
-        mime = efreet_mime_type_get(buf);
+        mime = _mime_get(buf);
         if (!mime)
           /* XXX REMOVE/DEPRECATE ME LATER */
           mime = e_fm_mime_filename_get(ic->info.file);
diff --git a/src/bin/e_fm/e_fm_ipc.c b/src/bin/e_fm/e_fm_ipc.c
index 4a3f0ac..8348afd 100644
--- a/src/bin/e_fm/e_fm_ipc.c
+++ b/src/bin/e_fm/e_fm_ipc.c
@@ -42,9 +42,6 @@
 #undef E_TYPEDEFS
 #include "e_fm_main.h"
 #include "e_fm_shared_codec.h"
-#define DEF_SYNC_NUM             8
-#define DEF_ROUND_TRIP           0.05
-#define DEF_ROUND_TRIP_TOLERANCE 0.01
 #define DEF_MOD_BACKOFF          0.2
 
 #ifndef strdupa
@@ -65,14 +62,12 @@ struct _E_Dir
    int                 mon_ref;
    E_Dir              *mon_real;
    Eina_List          *fq;
-   Ecore_Idler        *idler;
-   int                 dot_order;
-   int                 sync;
-   double              sync_time;
-   int                 sync_num;
+   Eina_Iterator      *lister_iterator;
+   Ecore_Thread       *lister_thread;
    Eina_List          *recent_mods;
    Ecore_Timer        *recent_clean;
-   unsigned char       cleaning : 1;
+   Eina_Bool           cleaning : 1;
+   Eina_Bool           delete_me : 1;
 };
 
 struct _E_Fop
@@ -122,7 +117,6 @@ Ecore_Ipc_Server *_e_fm_ipc_server = NULL;
 
 static Eina_List *_e_dirs = NULL;
 static Eina_List *_e_fops = NULL;
-static int _e_sync_num = 0;
 
 static Eina_List *_e_fm_ipc_slaves = NULL;
 static Eina_List *_e_fm_tasks = NULL;
@@ -159,11 +153,8 @@ static void        _e_fm_ipc_file_add(E_Dir *ed, const 
char *path, int listing);
 static void        _e_fm_ipc_file_del(E_Dir *ed, const char *path);
 static void        _e_fm_ipc_file_mod(E_Dir *ed, const char *path);
 static void        _e_fm_ipc_file_mon_dir_del(E_Dir *ed, const char *path);
-static void        _e_fm_ipc_file_mon_list_sync(E_Dir *ed);
 
-static Eina_Bool   _e_fm_ipc_cb_file_mon_list_idler(void *data);
 static Eina_Bool   _e_fm_ipc_cb_fop_trash_idler(void *data);
-static char       *_e_str_list_remove(Eina_List **list, const char *str, int 
len);
 static void        _e_fm_ipc_reorder(const char *file, const char *dst, const 
char *relative, int after);
 static void        _e_fm_ipc_dir_del(E_Dir *ed);
 
@@ -242,6 +233,86 @@ _e_fm_ipc_monitor_start(int id, const char *path)
 }
 
 static void
+_e_fm_ipc_cb_list_result(void *data, Ecore_Thread *thread EINA_UNUSED, void 
*msg_data)
+{
+   E_Dir *ed = data;
+   Eina_List *files = msg_data;
+   const char *s;
+
+   if (!files) _e_fm_ipc_file_add(ed, "", 2);
+   else
+     {
+        EINA_LIST_FREE(files, s)
+          {
+             _e_fm_ipc_file_add(ed, s, 2);
+             eina_stringshare_del(s);
+          }
+     }
+}
+
+static void
+_e_fm_ipc_cb_list(void *data, Ecore_Thread *thread)
+{
+   E_Dir *ed = data;
+   Eina_List *files = NULL;
+   int i, total = 0;
+   Eina_File_Direct_Info *info;
+   Eina_Iterator *it = ed->lister_iterator;
+   char buf[4096];
+   const char *s;
+
+   if (!strcmp(ed->dir, "/")) snprintf(buf, sizeof(buf), "/.order");
+   else snprintf(buf, sizeof(buf), "%s/.order", ed->dir);
+   if (ecore_file_exists(buf))
+     {
+        s = eina_stringshare_add(buf);
+        files = eina_list_append(files, s);
+     }
+   i = 0;
+   EINA_ITERATOR_FOREACH(it, info)
+     {
+        if (!strcmp(info->path + info->name_start, ".order")) continue;
+        if (ecore_thread_check(thread))
+          {
+             EINA_LIST_FREE(files, s) eina_stringshare_del(s);
+             break;
+          }
+        s = eina_stringshare_add(info->path);
+        files = eina_list_append(files, s);
+        total++;
+        i++;
+        if (i >= 16)
+          {
+             i = 0;
+             ecore_thread_feedback(thread, files);
+             files = NULL;
+          }
+     }
+   if (files) ecore_thread_feedback(thread, files);
+   if (total == 0) ecore_thread_feedback(thread, NULL);
+}
+
+static void
+_e_fm_ipc_cb_list_end(void *data, Ecore_Thread *thread EINA_UNUSED)
+{
+   E_Dir *ed = data;
+   ed->lister_thread = NULL;
+   eina_iterator_free(ed->lister_iterator);
+   ed->lister_iterator = NULL;
+   if (ed->delete_me) _e_fm_ipc_dir_del(ed);
+}
+
+static void
+_e_fm_ipc_cb_list_cancel(void *data, Ecore_Thread *thread EINA_UNUSED)
+{
+   E_Dir *ed = data;
+   ed->lister_thread = NULL;
+   eina_iterator_free(ed->lister_iterator);
+   ed->lister_iterator = NULL;
+   if (ed->delete_me) _e_fm_ipc_dir_del(ed);
+}
+
+static void
 _e_fm_ipc_monitor_start_try(E_Fm_Task *task)
 {
    E_Dir *ed, *ped = NULL;
@@ -271,14 +342,11 @@ _e_fm_ipc_monitor_start_try(E_Fm_Task *task)
      }
    else
      {
-        Eina_File_Direct_Info *info;
-        Eina_List *files = NULL;
-        char *dot_order = NULL;
-
         /* create a new dir entry */
         ed = calloc(1, sizeof(E_Dir));
         ed->id = task->id;
         ed->dir = eina_stringshare_add(task->src);
+        ed->lister_iterator = it;
         if (!ped)
           {
              /* if no previous monitoring dir exists - this one
@@ -294,94 +362,11 @@ _e_fm_ipc_monitor_start_try(E_Fm_Task *task)
           }
         _e_dirs = eina_list_append(_e_dirs, ed);
 
-        /* read everything except a .order, . and .. */
-        EINA_ITERATOR_FOREACH(it, info)
-          {
-             if (!strcmp(info->path + info->name_start, ".order"))
-               {
-                  dot_order = strdup(info->path);
-                  continue;
-               }
-             files = eina_list_append(files, eina_stringshare_add(info->path + 
info->name_start));
-          }
-        eina_iterator_free(it);
-
-        /* if there was a .order - we need to parse it */
-        if (dot_order)
-          {
-             Eina_File *f;
-
-             f = eina_file_open(dot_order, EINA_FALSE);
-             if (f)
-               {
-                  Eina_List *f2 = NULL;
-                  char *map;
-
-                  /* This piece of code should really become generic and work 
like an iterator.
-                   * I plan to add this feature in eina, but that would be for 
next generation of E,
-                   * not E17.
-                   */
-                  map = eina_file_map_all(f, EINA_FILE_SEQUENTIAL);
-                  if (map)
-                    {
-                       const char *current = map;
-                       const char *found;
-                       size_t length = eina_file_size_get(f);
-
-                       /* inset files in order if the existed in file
-                        * list before */
-                       while ((found = memchr(current, '\n', length)))
-                         {
-                            if (found - current > 1)
-                              {
-                                 char *s = _e_str_list_remove(&files, current, 
found - current - 1);
-                                 if (s) f2 = eina_list_append(f2, s);
-                              }
-                            length -= found - current - 1;
-                            current = found + 1;
-                         }
-
-                       if (found == NULL && length > 0)
-                         {
-                            char *s = _e_str_list_remove(&files, current, 
length);
-                            if (s) f2 = eina_list_append(f2, s);
-                         }
-
-                       /* append whats left */
-                       files = eina_list_merge(f2, files);
-
-                       eina_file_map_free(f, map);
-                    }
-
-                  eina_file_close(f);
-               }
-          }
-        ed->fq = files;
-        /* FIXME: if .order file- load it, sort all items int it
-         * that are in files then just append whatever is left in
-         * alphabetical order
-         */
-        /* FIXME: maybe one day we can sort files here and handle
-         * .order file stuff here - but not today
-         */
-        /* note that we had a .order at all */
-        ed->dot_order = dot_order ? EINA_TRUE : EINA_FALSE;
-        if (dot_order)
-          {
-             /* if we did - tell the E about this FIRST - it will
-              * decide what to do if it first sees a .order or not */
-             if (eina_list_count(files) == 1)
-               _e_fm_ipc_file_add(ed, dot_order, 2);
-             else
-               _e_fm_ipc_file_add(ed, dot_order, 1);
-          }
-        /* send empty file - indicate empty dir */
-        if (!files) _e_fm_ipc_file_add(ed, "", 2);
-        /* and in an idler - list files, statting them etc. */
-        ed->idler = ecore_idler_add(_e_fm_ipc_cb_file_mon_list_idler, ed);
-        ed->sync_num = DEF_SYNC_NUM;
-
-        free(dot_order);
+        ed->lister_thread = ecore_thread_feedback_run(_e_fm_ipc_cb_list,
+                                                      _e_fm_ipc_cb_list_result,
+                                                      _e_fm_ipc_cb_list_end,
+                                                      _e_fm_ipc_cb_list_cancel,
+                                                      ed, EINA_TRUE);
      }
 }
 
@@ -696,36 +681,6 @@ _e_fm_ipc_cb_server_data(void *data __UNUSED__, int type 
__UNUSED__, void *event
         ecore_main_loop_quit();
         break;
 
-      case E_FM_OP_MONITOR_SYNC: /* mon list sync */
-      {
-         Eina_List *l;
-         E_Dir *ed;
-         double sync_time;
-
-         EINA_LIST_FOREACH(_e_dirs, l, ed)
-           {
-              if (ed->fq)
-                {
-                   if (ed->sync == e->response)
-                     {
-                        sync_time = ecore_time_get() - ed->sync_time;
-                        /* try keep round trips to round trip tolerance */
-                        if
-                        (sync_time < (DEF_ROUND_TRIP - 
DEF_ROUND_TRIP_TOLERANCE))
-                          ed->sync_num += 1;
-                        else if
-                        (sync_time > (DEF_ROUND_TRIP + 
DEF_ROUND_TRIP_TOLERANCE))
-                          ed->sync_num -= 1;
-                        /* always sync at least 1 file */
-                        if (ed->sync_num < 1) ed->sync_num = 1;
-                        ed->idler = 
ecore_idler_add(_e_fm_ipc_cb_file_mon_list_idler, ed);
-                        break;
-                     }
-                }
-           }
-      }
-      break;
-
       case E_FM_OP_ABORT: // abort copy/move/delete operation by user
       {
          E_Fm_Slave *slave = _e_fm_ipc_slave_get(e->ref);
@@ -1198,58 +1153,6 @@ _e_fm_ipc_file_mon_dir_del(E_Dir *ed, const char *path)
                          0, ed->id, 0, (void *)path, strlen(path) + 1);
 }
 
-static void
-_e_fm_ipc_file_mon_list_sync(E_Dir *ed)
-{
-   _e_sync_num++;
-   if (_e_sync_num == 0) _e_sync_num = 1;
-   ed->sync = _e_sync_num;
-   ed->sync_time = ecore_time_get();
-   ecore_ipc_server_send(_e_fm_ipc_server,
-                         6 /*E_IPC_DOMAIN_FM*/,
-                         E_FM_OP_MONITOR_SYNC,
-                         0, ed->id, ed->sync, NULL, 0);
-}
-
-static Eina_Bool
-_e_fm_ipc_cb_file_mon_list_idler(void *data)
-{
-   E_Dir *ed;
-   int n = 0;
-   char *file, buf[4096];
-
-   ed = data;
-   /* FIXME: spool off files in idlers and handle sync req's */
-   while (ed->fq)
-     {
-        file = eina_list_data_get(ed->fq);
-        if (!((ed->dot_order) && (!strcmp(file, ".order"))))
-          {
-             if (!strcmp(ed->dir, "/"))
-               snprintf(buf, sizeof(buf), "/%s", file);
-             else
-               snprintf(buf, sizeof(buf), "%s/%s", ed->dir, file);
-             _e_fm_ipc_file_add(ed, buf, 1);
-          }
-        eina_stringshare_del(file);
-        ed->fq = eina_list_remove_list(ed->fq, ed->fq);
-        n++;
-        if (n == ed->sync_num)
-          {
-             _e_fm_ipc_file_mon_list_sync(ed);
-             ed->idler = NULL;
-             if (!ed->fq) _e_fm_ipc_file_add(ed, "", 2);
-             return 0;
-          }
-     }
-   ed->sync_num = DEF_SYNC_NUM;
-   ed->sync = 0;
-   ed->sync_time = 0.0;
-   ed->idler = NULL;
-   if (!ed->fq) _e_fm_ipc_file_add(ed, "", 2);
-   return ECORE_CALLBACK_CANCEL;
-}
-
 static Eina_Bool
 _e_fm_ipc_cb_fop_trash_idler(void *data)
 {
@@ -1333,22 +1236,6 @@ _e_fm_ipc_cb_fop_trash_idler(void *data)
    return ECORE_CALLBACK_CANCEL;
 }
 
-static char *
-_e_str_list_remove(Eina_List **list, const char *str, int len)
-{
-   Eina_List *l;
-   char *s;
-
-   EINA_LIST_FOREACH(*list, l, s)
-     if (!strncmp(s, str, len))
-       {
-          *list = eina_list_remove_list(*list, l);
-          return s;
-       }
-
-   return NULL;
-}
-
 static void
 _e_fm_ipc_reorder(const char *file, const char *dst, const char *relative, int 
after)
 {
@@ -1430,17 +1317,20 @@ _e_fm_ipc_dir_del(E_Dir *ed)
    void *data;
    E_Mod *m;
 
+   if (ed->lister_thread)
+     {
+        ed->delete_me = EINA_TRUE;
+        ecore_thread_cancel(ed->lister_thread);
+        return;
+     }
    eina_stringshare_del(ed->dir);
-   if (ed->idler) ecore_idler_del(ed->idler);
-   if (ed->recent_clean)
-     ecore_timer_del(ed->recent_clean);
+   if (ed->recent_clean) ecore_timer_del(ed->recent_clean);
    EINA_LIST_FREE(ed->recent_mods, m)
      {
         eina_stringshare_del(m->path);
         free(m);
      }
-   EINA_LIST_FREE(ed->fq, data)
-     eina_stringshare_del(data);
+   EINA_LIST_FREE(ed->fq, data) eina_stringshare_del(data);
    free(ed);
 }
 
diff --git a/src/bin/e_fm_op.h b/src/bin/e_fm_op.h
index c7f79be..fb07321 100644
--- a/src/bin/e_fm_op.h
+++ b/src/bin/e_fm_op.h
@@ -26,7 +26,7 @@ typedef enum _E_Fm_Op_Type
    E_FM_OP_MKDIR,
    E_FM_OP_TRASH,
    E_FM_OP_MONITOR_START,
-   E_FM_OP_MONITOR_SYNC,
+   E_FM_OP_MONITOR_SYNC, // not used anymore
    E_FM_OP_MONITOR_END,
    E_FM_OP_MOUNT,
    E_FM_OP_UNMOUNT,

-- 


Reply via email to