eio: add Eio_Monitor API.

Not yet working. Need to handle message, add fallback and windows support.


SVN revision: 58907
This commit is contained in:
Cedric BAIL 2011-04-25 17:04:46 +00:00
parent 25959fb6ed
commit b558cbc07e
10 changed files with 651 additions and 8 deletions

View File

@ -57,6 +57,19 @@ AC_SUBST(release_info)
VMAJ=v_maj
AC_SUBST(VMAJ)
# options
want_inotify="no"
want_notify_win32="no"
case "$host_os" in
mingw* | cegcc*)
want_notify_win32="yes"
;;
*)
want_inotify="yes"
;;
esac
dnl we just have set the version info, then:
AC_SUBST(version_info)
@ -145,6 +158,8 @@ AC_SUBST(EFL_EIO_BUILD)
### Checks for library functions
AC_CHECK_FUNCS([fchmod chown getpwnam getgrnam])
### Check for splice system call
have_splice="no"
AC_TRY_LINK(
[
@ -163,6 +178,17 @@ if test "x${have_splice}" = "xyes" ; then
AC_DEFINE([EFL_HAVE_SPLICE], [1], [Define to mention that splice syscall is supported])
fi
### Check for inotify specificity
have_inotify="no"
have_notify_win32="no"
EIO_CHECK_INOTIFY([${want_inotify}], [have_inotify="yes"], [have_inotify="no"])
EIO_CHECK_NOTIFY_WIN32([${want_notify_win32}], [have_notify_win32="yes"], [have_notify_win32="no"])
AM_CONDITIONAL([EIO_HAVE_INOTIFY], [test "x$have_inotify" = "xyes"])
AM_CONDITIONAL([EIO_HAVE_WINCHANGE], [test "x$have_notify_win32" = "xyes"])
## Report
AC_OUTPUT([
eio.pc
eio.spec
@ -184,6 +210,8 @@ echo
echo "Configuration Options Summary:"
echo
echo " Thread Support.......: ${have_threads}"
echo " Inotify..............: ${have_inotify}"
echo " Windows notification.: ${have_notify_win32}"
echo
echo " Documentation........: ${build_doc}"
echo

View File

@ -0,0 +1,86 @@
dnl use: EIO_CHECK_INOTIFY(default-enabled[, ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
AC_DEFUN([EIO_CHECK_INOTIFY],
[
_eio_want_inotify=$1
_eio_have_inotify="no"
dnl We need to check if the right inotify version is accessible
_eio_want_inotify="yes"
AC_ARG_ENABLE(inotify,
[AC_HELP_STRING([--disable-inotify], [disable inotify])],
[
if test "x${enableval}" = "xyes" ; then
_eio_want_inotify="yes"
else
_eio_want_inotify="no"
fi
])
AC_MSG_CHECKING(whether inotify is to be used for filemonitoring)
AC_MSG_RESULT($_eio_want_inotify)
dnl It is hard to find a good test on how to check the correct
dnl inotify version. They changed the headers a lot.
dnl in kernel 2.6.13 __NR_inotify_init was added to the defined syscalls
dnl in asm/unistd.h and IN_MOVE_SELF was added to linux/inotify.h
dnl so with this check you need a very new kernel and kernel-headers!
if test "x${_eio_want_inotify}" = "xyes" ; then
AC_CHECK_LIB([c], [inotify_init],
[
AC_DEFINE(HAVE_INOTIFY, 1, [ File monitoring with Inotify ])
AC_DEFINE(HAVE_SYS_INOTIFY, 1, [ File monitoring with Inotify - sys/inotify.h ])
_eio_have_inotify="yes"
],
[
AC_TRY_COMPILE(
[
#include <asm/unistd.h>
#include <linux/inotify.h>
],
[int a = __NR_inotify_init; int b = IN_MOVE_SELF;],
[
AC_DEFINE([HAVE_INOTIFY], [1], [ File monitoring with Inotify ])
_eio_have_inotify="yes"
],
[_eio_have_inotify="no"])
])
fi
if test "x$_eio_have_inotify" = "xyes" ; then
m4_default([$2], [:])
else
m4_default([$3], [:])
fi
])
dnl use: EIO_CHECK_NOTIFY_WIN32(default-enabled[, ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
AC_DEFUN([EIO_CHECK_NOTIFY_WIN32],
[
_eio_want_notify_win32=$1
_eio_have_notify_win32="no"
AC_ARG_ENABLE(notify-win32,
[AC_HELP_STRING([--disable-notify-win32], [disable Windows notification])],
[
if test "x${enableval}" = "xyes" ; then
_eio_want_notify_win32="yes"
else
_eio_want_notify_win32="no"
fi
])
AC_MSG_CHECKING(whether Windows notification is to be used for filemonitoring)
AC_MSG_RESULT(${_eio_want_notify_win32})
if test "x${_eio_want_notify_win32}" = "xyes" ; then
AC_DEFINE([HAVE_NOTIFY_WIN32], [1], [ File monitoring with Windows notification ])
_eio_have_notify_win32="yes"
fi
if test "x${_eio_have_notify_win32}" = "xyes" ; then
m4_default([$2], [:])
else
m4_default([$3], [:])
fi
])

View File

@ -252,6 +252,52 @@ static inline long long eio_file_size(const struct stat *stat);
static inline Eina_Bool eio_file_is_dir(const struct stat *stat);
static inline Eina_Bool eio_file_is_lnk(const struct stat *stat);
/**
* @}
*/
/**
*
*/
/**
* @defgroup Eio_Monitor Eio file and directory monitoring API
*
* @brief This function help monitoring change in a directory or on a file.
*
* This function use the best available method to monitor change on a directory
* or file. It send ecore event when needed and does refcount of all monitored
* path to avoid heavy ressource consuption.
*
* @{
*/
EAPI extern int EIO_MONITOR_FILE_CREATED; /**< Notify creation of a new file in a watched directory */
EAPI extern int EIO_MONITOR_FILE_DELETED; /**< Notify destruction of a watched file or in a watched directory */
EAPI extern int EIO_MONITOR_FILE_MODIFIED; /**< Notify modification of a file in a watched directory */
EAPI extern int EIO_MONITOR_FILE_START; /**< Notify starting to watch on a file */
EAPI extern int EIO_MONITOR_FILE_STOP; /**< Notify that Eio stopped watching on a file (because of all watcher beeing deleted or the file itself has been deleted */
EAPI extern int EIO_MONITOR_DIRECTORY_CREATED; /**< Notify creation of a new directory in a watched directory */
EAPI extern int EIO_MONITOR_DIRECTORY_DELETED; /**< Notify destruction of a watched directory or in a watched directory */
EAPI extern int EIO_MONITOR_DIRECTORY_MODIFIED; /**< Notify modification of a directory in a watched directory */
EAPI extern int EIO_MONITOR_DIRECTORY_START; /**< Notify the starting processus of watching a directory */
EAPI extern int EIO_MONITOR_DIRECTORY_STOP; /**< Notify that Eio stopped watching on a directory (due to destruction of the directory or due to all watcher beeing deleted */
EAPI extern int EIO_MONITOR_ERROR; /**< Notify that during operation the pointed monitor failed and will no longer work. eio_monitor_del is required on it. */
typedef struct _Eio_Monitor Eio_Monitor;
typedef struct _Eio_Monitor_Error Eio_Monitor_Error;
struct _Eio_Monitor_Error
{
Eio_Monitor *monitor;
int error;
};
EAPI Eio_Monitor *eio_monitor_add(const char *path);
EAPI Eio_Monitor *eio_monitor_stringshared_add(const char *path);
EAPI void eio_monitor_del(Eio_Monitor *monitor);
EAPI const char *eio_monitor_path_get(Eio_Monitor *monitor);
/**
* @}
*/

View File

@ -13,7 +13,17 @@ libeio_la_SOURCES = \
eio_file.c \
eio_main.c \
eio_single.c \
eio_dir.c
eio_dir.c \
eio_monitor.c \
eio_poll.c
if EIO_HAVE_INOTIFY
libeio_la_SOURCES += eio_inotify.c
else
if EIO_HAVE_WINCHANGE
libeio_la_SOURCES += eio_winchange.c
endif
endif
libeio_la_LIBADD = @EIO_LIBS@
libeio_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -version-info @version_info@ @release_info@

View File

@ -0,0 +1,131 @@
/* EIO - EFL data type library
* Copyright (C) 2011 Enlightenment Developers:
* Cedric Bail <cedric.bail@free.fr>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library;
* if not, see <http://www.gnu.org/licenses/>.
*/
#include "eio_private.h"
#include "Eio.h"
#ifdef HAVE_SYS_INOTIFY
# include <sys/inotify.h>
#else
# include <asm/unistd.h>
# include <linux/inotify.h>
#endif
struct _Eio_Monitor_Backend
{
Eio_Monitor *parent;
int hwnd;
};
static Ecore_Fd_Handler *_inotify_fdh = NULL;
static Eina_Hash *_inotify_monitors = NULL;
static void
_eio_inotify_del(void *data)
{
Eio_Monitor_Backend *emb = data;
int fd;
if (emb->hwnd)
{
fd = ecore_main_fd_handler_fd_get(_inotify_fdh);
inotify_rm_watch(fd, emb->hwnd);
emb->hwnd = 0;
}
free(emb);
}
static Eina_Bool
_eio_inotify_handler(void *data, Ecore_Fd_Handler *fdh)
{
return EINA_TRUE;
}
void eio_monitor_backend_init(void)
{
int fd;
fd = inotify_init();
if (fd < 0)
return ;
_inotify_fdh = ecore_main_fd_handler_add(fd, ECORE_FD_READ, _eio_inotify_handler, NULL, NULL, NULL);
if (!_inotify_fdh)
{
close(fd);
return ;
}
_inotify_monitors = eina_hash_int32_new(_eio_inotify_del);
}
void eio_monitor_backend_shutdown(void)
{
int fd;
if (!_inotify_fdh) return ;
eina_hash_free(_inotify_monitors);
fd = ecore_main_fd_handler_fd_get(_inotify_fdh);
ecore_main_fd_handler_del(_inotify_fdh);
_inotify_fdh = NULL;
close(fd);
}
void eio_monitor_backend_add(Eio_Monitor *monitor)
{
Eio_Monitor_Backend *backend;
int mask =
IN_ATTRIB |
IN_CLOSE_WRITE |
IN_MOVED_FROM |
IN_MOVED_TO |
IN_DELETE |
IN_CREATE |
IN_MODIFY |
IN_DELETE_SELF |
IN_MOVE_SELF |
IN_UNMOUNT;
if (!_inotify_fdh)
eio_monitor_fallback_add(monitor);
backend = calloc(1, sizeof (Eio_Monitor_Backend));
if (!backend) return eio_monitor_fallback_add(monitor);
backend->parent = monitor;
backend->hwnd = inotify_add_watch(ecore_main_fd_handler_fd_get(_inotify_fdh), monitor->path, mask);
if (!backend->hwnd)
return eio_monitor_fallback_add(monitor);
}
void eio_monitor_backend_del(Eio_Monitor *monitor)
{
if (!_inotify_fdh)
eio_monitor_fallback_del(monitor);
if (!monitor->backend) return ;
eina_hash_del(_inotify_monitors, &monitor->backend->hwnd, monitor->backend);
monitor->backend = NULL;
}

View File

@ -58,7 +58,7 @@ struct _Eio_Alloc_Pool
static int _eio_count = 0;
static Eio_Alloc_Pool progress = { 0, NULL, EIO_MUTEX_INITIALIZER };
static Eio_Alloc_Pool progress_pool = { 0, NULL, EIO_MUTEX_INITIALIZER };
static Eio_Alloc_Pool direct_info = { 0, NULL, EIO_MUTEX_INITIALIZER };
static void *
@ -109,7 +109,7 @@ _eio_pool_free(Eio_Alloc_Pool *pool, void *data)
Eio_Progress *
eio_progress_malloc(void)
{
return _eio_pool_malloc(&progress, sizeof (Eio_Progress));
return _eio_pool_malloc(&progress_pool, sizeof (Eio_Progress));
}
void
@ -118,7 +118,7 @@ eio_progress_free(Eio_Progress *data)
eina_stringshare_del(data->source);
eina_stringshare_del(data->dest);
_eio_pool_free(&progress, data);
_eio_pool_free(&progress_pool, data);
}
void
@ -183,9 +183,11 @@ eio_init(void)
eina_init();
ecore_init();
EIO_MUTEX_INIT(progress);
EIO_MUTEX_INIT(progress_pool);
EIO_MUTEX_INIT(direct_info);
eio_monitor_init();
return _eio_count;
}
@ -204,12 +206,12 @@ eio_shutdown(void)
if (_eio_count > 0) return _eio_count;
EIO_MUTEX_DESTROY(direct_info);
EIO_MUTEX_DESTROY(progress);
EIO_MUTEX_DESTROY(progress_pool);
/* Cleanup pool */
EINA_TRASH_CLEAN(&progress.trash, pg)
EINA_TRASH_CLEAN(&progress_pool.trash, pg)
free(pg);
progress.count = 0;
progress_pool.count = 0;
EINA_TRASH_CLEAN(&direct_info.trash, info)
free(info);

View File

@ -0,0 +1,206 @@
/* EIO - EFL data type library
* Copyright (C) 2011 Enlightenment Developers:
* Cedric Bail <cedric.bail@free.fr>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library;
* if not, see <http://www.gnu.org/licenses/>.
*/
#include "eio_private.h"
#include "Eio.h"
EAPI int EIO_MONITOR_ERROR;
EAPI int EIO_MONITOR_FILE_CREATED;
EAPI int EIO_MONITOR_FILE_DELETED;
EAPI int EIO_MONITOR_FILE_MODIFIED;
EAPI int EIO_MONITOR_FILE_START;
EAPI int EIO_MONITOR_FILE_STOP;
EAPI int EIO_MONITOR_DIRECTORY_CREATED;
EAPI int EIO_MONITOR_DIRECTORY_DELETED;
EAPI int EIO_MONITOR_DIRECTORY_MODIFIED;
EAPI int EIO_MONITOR_DIRECTORY_START;
EAPI int EIO_MONITOR_DIRECTORY_STOP;
static Eina_Hash *_eio_monitors = NULL;
static pid_t _monitor_pid = -1;
static void
_eio_monitor_del(void *data)
{
Eio_Monitor *monitor = data;
if (monitor->exist) eio_file_cancel(monitor->exist);
if (!monitor->fallback)
eio_monitor_backend_del(monitor);
else
eio_monitor_fallback_del(monitor);
if (monitor->refcount > 0)
return ;
eina_stringshare_del(monitor->path);
free(monitor);
}
static void
_eio_monitor_cleanup_cb(void *user_data, __UNUSED__ void *func_data)
{
Eio_Monitor_Error *ev = user_data;
ev->monitor->refcount--;
_eio_monitor_del(ev->monitor);
free(ev);
}
static void
_eio_monitor_stat_cb(void *data, __UNUSED__ Eio_File *handler, __UNUSED__ const struct stat *st)
{
Eio_Monitor *monitor = data;
monitor->exist = NULL;
monitor->refcount--;
if (monitor->refcount > 0)
{
eio_monitor_backend_add(monitor);
}
else
{
eina_hash_del(_eio_monitors, monitor->path, monitor);
}
}
static void
_eio_monitor_error_cb(void *data, Eio_File *handler, int error)
{
Eio_Monitor_Error *ev;
Eio_Monitor *monitor = data;
monitor->error = error;
monitor->exist = NULL;
monitor->refcount--;
if (monitor->refcount == 0) goto on_empty;
ev = calloc(1, sizeof (Eio_Monitor_Error));
if (!ev) return ;
ev->monitor = monitor;
ev->monitor->refcount++;
ev->error = error;
ecore_event_add(EIO_MONITOR_ERROR, ev, _eio_monitor_cleanup_cb, NULL);
on_empty:
eina_hash_del(_eio_monitors, monitor->path, monitor);
}
void
eio_monitor_init(void)
{
EIO_MONITOR_ERROR = ecore_event_type_new();
EIO_MONITOR_FILE_CREATED = ecore_event_type_new();
EIO_MONITOR_FILE_DELETED = ecore_event_type_new();
EIO_MONITOR_FILE_MODIFIED = ecore_event_type_new();
EIO_MONITOR_FILE_START = ecore_event_type_new();
EIO_MONITOR_FILE_STOP = ecore_event_type_new();
EIO_MONITOR_DIRECTORY_CREATED = ecore_event_type_new();
EIO_MONITOR_DIRECTORY_DELETED = ecore_event_type_new();
EIO_MONITOR_DIRECTORY_MODIFIED = ecore_event_type_new();
EIO_MONITOR_DIRECTORY_START = ecore_event_type_new();
EIO_MONITOR_DIRECTORY_STOP = ecore_event_type_new();
eio_monitor_backend_init();
eio_monitor_fallback_init();
_eio_monitors = eina_hash_stringshared_new(_eio_monitor_del);
_monitor_pid = getpid();
}
void
eio_monitor_shutdown(void)
{
eina_hash_free(_eio_monitors);
eio_monitor_backend_shutdown();
eio_monitor_fallback_shutdown();
_monitor_pid = -1;
}
EAPI Eio_Monitor *
eio_monitor_add(const char *path)
{
const char *tmp;
tmp = eina_stringshare_add(path);
return eio_monitor_stringshared_add(path);
}
EAPI Eio_Monitor *
eio_monitor_stringshared_add(const char *path)
{
Eio_Monitor *monitor;
if (_monitor_pid == -1) return NULL;
if (_monitor_pid != getpid())
{
eio_monitor_shutdown();
eio_monitor_init();
}
monitor = eina_hash_find(_eio_monitors, path);
if (!monitor)
{
monitor = malloc(sizeof (Eio_Monitor));
if (!monitor) return NULL;
monitor->backend = NULL; // This is needed to avoid race condition
monitor->path = eina_stringshare_ref(path);
monitor->fallback = EINA_FALSE;
monitor->refcount = 1;
monitor->exist = eio_file_direct_stat(monitor->path,
_eio_monitor_stat_cb,
_eio_monitor_error_cb,
monitor);
eina_hash_direct_add(_eio_monitors, path, monitor);
}
monitor->refcount++;
return monitor;
}
EAPI void
eio_monitor_del(Eio_Monitor *monitor)
{
monitor->refcount--;
if (monitor->refcount > 0) return ;
eina_hash_del(_eio_monitors, monitor->path, monitor);
}
EAPI const char *
eio_monitor_path_get(Eio_Monitor *monitor)
{
return monitor->path;
}

View File

@ -0,0 +1,65 @@
/* EIO - EFL data type library
* Copyright (C) 2011 Enlightenment Developers:
* Cedric Bail <cedric.bail@free.fr>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library;
* if not, see <http://www.gnu.org/licenses/>.
*/
#include "eio_private.h"
#include "Eio.h"
struct _Eio_Monitor_Backend
{
};
#if !defined HAVE_INOTIFY && !defined HAVE_NOTIFY_WIN32
void eio_monitor_backend_init(void)
{
}
void eio_monitor_backend_shutdown(void)
{
}
void eio_monitor_backend_add(Eio_Monitor *monitor)
{
eio_monitor_fallback_add(monitor);
}
void eio_monitor_backend_del(Eio_Monitor *monitor)
{
eio_monitor_fallback_del(monitor);
}
#endif
void
eio_monitor_fallback_init(void)
{
}
void
eio_monitor_fallback_shutdown(void)
{
}
void
eio_monitor_fallback_add(Eio_Monitor *monitor)
{
}
void
eio_monitor_fallback_del(Eio_Monitor *monitor)
{
}

View File

@ -59,6 +59,7 @@ typedef struct _Eio_File_Stat Eio_File_Stat;
typedef struct _Eio_File_Progress Eio_File_Progress;
typedef struct _Eio_File_Move Eio_File_Move;
typedef struct _Eio_File_Chown Eio_File_Chown;
typedef struct _Eio_Monitor_Backend Eio_Monitor_Backend;
typedef struct _Eio_Dir_Copy Eio_Dir_Copy;
@ -159,6 +160,19 @@ struct _Eio_File_Chown
const char *group;
};
struct _Eio_Monitor
{
Eio_Monitor_Backend *backend;
Eio_File *exist;
const char *path;
int refcount;
int error;
Eina_Bool fallback : 1;
};
/* Be aware that ecore_thread_run could call cancel_cb if something goes wrong. */
Eina_Bool eio_file_set(Eio_File *common,
Eio_Done_Cb done_cb,
@ -193,4 +207,17 @@ void eio_progress_cb(Eio_Progress *progress, Eio_File_Progress *op);
Eina_Bool eio_file_copy_do(Ecore_Thread *thread, Eio_File_Progress *copy);
void eio_monitor_init(void);
void eio_monitor_backend_init(void);
void eio_monitor_fallback_init(void);
void eio_monitor_shutdown(void);
void eio_monitor_backend_shutdown(void);
void eio_monitor_fallback_shutdown(void);
void eio_monitor_backend_add(Eio_Monitor *monitor);
void eio_monitor_fallback_add(Eio_Monitor *monitor);
void eio_monitor_backend_del(Eio_Monitor *monitor);
void eio_monitor_fallback_del(Eio_Monitor *monitor);
#endif

View File

@ -0,0 +1,42 @@
/* EIO - EFL data type library
* Copyright (C) 2011 Enlightenment Developers:
* Cedric Bail <cedric.bail@free.fr>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library;
* if not, see <http://www.gnu.org/licenses/>.
*/
#include "eio_private.h"
#include "Eio.h"
struct _Eio_Monitor_Backend
{
};
void eio_monitor_backend_init(void)
{
abort();
}
void eio_monitor_backend_shutdown(void)
{
}
void eio_monitor_backend_add(Eio_Monitor *monitor)
{
}
void eio_monitor_backend_del(Eio_Monitor *monitor)
{
}