diff --git a/legacy/eio/src/lib/eio_poll.c b/legacy/eio/src/lib/eio_poll.c index 005cfb3445..9e050add46 100644 --- a/legacy/eio/src/lib/eio_poll.c +++ b/legacy/eio/src/lib/eio_poll.c @@ -20,15 +20,29 @@ #include "eio_private.h" #include "Eio.h" +typedef struct _Eio_Monitor_Stat Eio_Monitor_Stat; +struct _Eio_Monitor_Stat +{ + Eina_Stat buffer; + int version; +}; + struct _Eio_Monitor_Backend { Eio_Monitor *parent; + Eina_Stat self; + Eina_Hash *children; + Ecore_Timer *timer; Ecore_Idler *idler; Ecore_Thread *work; + int version; + Eina_Bool delete_me : 1; + Eina_Bool initialised : 1; + Eina_Bool destroyed : 1; }; static Eina_Bool _eio_monitor_fallback_timer_cb(void *data); @@ -56,11 +70,155 @@ void eio_monitor_backend_del(Eio_Monitor *monitor) static void _eio_monitor_fallback_heavy_cb(void *data, Ecore_Thread *thread) { - /* FIXME : copy ecore_file_monitor_poll here */ + Eio_Monitor_Backend *backend = data; + Eina_Iterator *it; + Eina_Stat *est; + Eina_File_Direct_Info *info; + struct stat st; + /* FIXME : copy ecore_file_monitor_poll here */ + + if (!backend->initialised) + est = &backend->self; + else + est = alloca(sizeof (Eina_Stat)); + + if (!backend->parent) + return ; + + if (stat(backend->parent->path, &st)) + { + if (backend->initialised && !backend->destroyed) + { + ecore_thread_main_loop_begin(); + _eio_monitor_send(backend->parent, backend->parent->path, EIO_MONITOR_SELF_DELETED); + ecore_thread_main_loop_end(); + backend->destroyed = EINA_TRUE; + } + return ; + } + + backend->destroyed = EINA_FALSE; + + est->dev = st.st_dev; + est->ino = st.st_ino; + est->mode = st.st_mode; + est->nlink = st.st_nlink; + est->uid = st.st_uid; + est->gid = st.st_gid; + est->rdev = st.st_rdev; + est->size = st.st_size; + est->blksize = st.st_blksize; + est->blocks = st.st_blocks; + est->atime = st.st_atime; + est->mtime = st.st_mtime; + est->ctime = st.st_ctime; +#ifdef _STAT_VER_LINUX +# if (defined __USE_MISC && defined st_mtime) + est->atimensec = st.st_atim.tv_nsec; + est->mtimensec = st.st_mtim.tv_nsec; + est->ctimensec = st.st_ctim.tv_nsec; +# else + est->atimensec = st.st_atimensec; + est->mtimensec = st.st_mtimensec; + est->ctimensec = st.st_ctimensec; +# endif +#else + est->atimensec = 0; + est->mtimensec = 0; + est->ctimensec = 0; +#endif + + if (memcmp(est, &backend->self, sizeof (Eina_Stat)) != 0) + { + ecore_thread_main_loop_begin(); + _eio_monitor_send(backend->parent, backend->parent->path, EIO_MONITOR_SELF_DELETED); + ecore_thread_main_loop_end(); + } + + it = eina_file_direct_ls(backend->parent->path); + EINA_ITERATOR_FOREACH(it, info) + { + Eio_Monitor_Stat *cmp; + Eio_Monitor_Stat buffer; + + if (!backend->initialised) + cmp = calloc(1, sizeof (Eio_Monitor_Stat)); + else + cmp = &buffer; + + if (eina_file_statat(eina_iterator_container_get(it), info, &cmp->buffer)) + { + if (!backend->initialised) free(cmp); + continue ; + } + + if (!backend->initialised) + { + eina_hash_add(backend->children, info->path + info->name_start, cmp); + } + else + { + cmp = eina_hash_find(backend->children, info->path + info->name_start); + if (!cmp) + { + /* New file or new directory added */ + ecore_thread_main_loop_begin(); + _eio_monitor_send(backend->parent, info->path + info->name_start, + info->type != EINA_FILE_DIR ? EIO_MONITOR_FILE_CREATED : EIO_MONITOR_DIRECTORY_CREATED); + ecore_thread_main_loop_end(); + + cmp = malloc(sizeof (Eio_Monitor_Stat)); + memcpy(cmp, &buffer, sizeof (Eina_Stat)); + + eina_hash_add(backend->children, info->path + info->name_start, cmp); + } + else if (memcmp(cmp, &buffer, sizeof (Eina_Stat)) != 0) + { + /* file has been modified */ + ecore_thread_main_loop_begin(); + _eio_monitor_send(backend->parent, info->path + info->name_start, + info->type != EINA_FILE_DIR ? EIO_MONITOR_FILE_MODIFIED : EIO_MONITOR_DIRECTORY_MODIFIED); + ecore_thread_main_loop_end(); + + memcpy(cmp, &buffer, sizeof (Eina_Stat)); + } + } + + cmp->version = backend->version; + if (ecore_thread_check(thread)) goto out; + } + out: + eina_iterator_free(it); + + if (backend->initialised && !ecore_thread_check(thread)) + { + Eina_Hash_Tuple *tuple; + + it = eina_hash_iterator_tuple_new(backend->children); + ecore_thread_main_loop_begin(); + + EINA_ITERATOR_FOREACH(it, tuple) + { + Eio_Monitor_Stat *cmp = tuple->data; + + if (cmp->version != backend->version) + { + _eio_monitor_send(backend->parent, tuple->key, + eio_file_is_dir(&cmp->buffer) ? EIO_MONITOR_DIRECTORY_DELETED : EIO_MONITOR_FILE_DELETED); + eina_hash_del(backend->children, tuple->key, tuple->data); + } + } + + ecore_thread_main_loop_end(); + eina_iterator_free(it); + } + + backend->version++; + backend->initialised = EINA_TRUE; } static void -_eio_monitor_fallback_end_cb(void *data, Ecore_Thread *thread) +_eio_monitor_fallback_end_cb(void *data, Ecore_Thread *thread __UNUSED__) { Eio_Monitor_Backend *backend = data; @@ -69,7 +227,7 @@ _eio_monitor_fallback_end_cb(void *data, Ecore_Thread *thread) } static void -_eio_monitor_fallback_cancel_cb(void *data, Ecore_Thread *thread) +_eio_monitor_fallback_cancel_cb(void *data, Ecore_Thread *thread __UNUSED__) { Eio_Monitor_Backend *backend = data; @@ -126,9 +284,13 @@ eio_monitor_fallback_add(Eio_Monitor *monitor) backend = calloc(1, sizeof (Eio_Monitor_Backend)); if (!backend) return ; + backend->children = eina_hash_string_superfast_new(free); backend->parent = monitor; monitor->backend = backend; - backend->timer = ecore_timer_add(60.0, _eio_monitor_fallback_timer_cb, backend); + backend->work = ecore_thread_run(_eio_monitor_fallback_heavy_cb, + _eio_monitor_fallback_end_cb, + _eio_monitor_fallback_cancel_cb, + backend); } void