eio: finish eio fallback monitor.

NOTE: this make Eio now officially in Alpha stage.
API and ABI should remain stable until the coming release.
Only bug fixes and highly needed api change will make in.


SVN revision: 68479
This commit is contained in:
Cedric BAIL 2012-02-27 20:58:26 +00:00
parent 34c0022210
commit 60132f0727
1 changed files with 166 additions and 4 deletions

View File

@ -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