forked from enlightenment/efl
eio: add OSX implementation of eio_monitor based on FSEvent
this patch adds an implementation of eio_monitor based on FSEvent for OSX. This implentation has some limitations compared to inotify implementation. Folowing events are not detected: - EIO_MONITOR_FILE_CLOSED - EIO_MONITOR_SELF_RENAME - EIO_MONITOR_SELF_DELETED It should be noted that some events that happend before the call to eio_monitor_add can be catched. This is why sleep timers have been added in the test suite. Tests have been added to check uncovered scenarios. some things might still be improved: - self_deleted events for files might be handled by checking the file_name manually - self_deleted events for directories might be handled by setting kFSEventStreamCreateFlagWatchRoot. I've noticed by doing so that a lot more unwanted event are raised Signed-off-by: Cedric BAIL <cedric@osg.samsung.com>
This commit is contained in:
parent
ae4389a7bd
commit
d958afd9fd
67
configure.ac
67
configure.ac
|
@ -417,19 +417,8 @@ sys/mman.h \
|
||||||
netinet/in.h \
|
netinet/in.h \
|
||||||
])
|
])
|
||||||
|
|
||||||
have_inotify="${ac_cv_header_sys_inotify_h}"
|
|
||||||
AM_CONDITIONAL([HAVE_INOTIFY], [test "x${have_inotify}" = "xyes"])
|
|
||||||
|
|
||||||
have_notify_win32="${have_win32}"
|
|
||||||
AC_DEFINE_IF([HAVE_NOTIFY_WIN32],
|
|
||||||
[test "x${have_notify_win32}" = "xyes"], [1],
|
|
||||||
[File monitoring with Windows notification])
|
|
||||||
AM_CONDITIONAL([HAVE_NOTIFY_WIN32], [test "x${have_notify_win32}" = "xyes"])
|
|
||||||
|
|
||||||
|
|
||||||
EFL_CHECK_PATH_MAX
|
EFL_CHECK_PATH_MAX
|
||||||
|
|
||||||
|
|
||||||
#### Checks for types
|
#### Checks for types
|
||||||
|
|
||||||
# wchar_t
|
# wchar_t
|
||||||
|
@ -1329,11 +1318,11 @@ AC_ARG_ENABLE([cocoa],
|
||||||
],
|
],
|
||||||
[want_cocoa="no"])
|
[want_cocoa="no"])
|
||||||
|
|
||||||
if test "${want_cocoa}" = "yes"; then
|
if test "${want_cocoa}" = "yes"; then
|
||||||
#test cocoa requirements (objc and Cocoa/Cocoa.h)
|
#test cocoa requirements (objc and Cocoa/Cocoa.h)
|
||||||
cocoa_ldflags=""
|
cocoa_ldflags=""
|
||||||
have_cocoa="no"
|
have_cocoa="no"
|
||||||
m4_ifdef([AC_PROG_OBJC],
|
m4_ifdef([AC_PROG_OBJC],
|
||||||
[
|
[
|
||||||
if test "x${have_gnu_objc}" = "xyes" ; then
|
if test "x${have_gnu_objc}" = "xyes" ; then
|
||||||
AC_LANG_PUSH([Objective C])
|
AC_LANG_PUSH([Objective C])
|
||||||
|
@ -1368,6 +1357,38 @@ window = [[NSWindow alloc]
|
||||||
fi
|
fi
|
||||||
AC_SUBST(cocoa_ldflags)
|
AC_SUBST(cocoa_ldflags)
|
||||||
|
|
||||||
|
if test "x${want_cocoa}" = "xyes"; then
|
||||||
|
#test cocoa requirements (objc and Cocoa/Cocoa.h)
|
||||||
|
cocoa_coreservices_ldflags=""
|
||||||
|
have_cocoa_coreservices="no"
|
||||||
|
m4_ifdef([AC_PROG_OBJC],
|
||||||
|
[
|
||||||
|
if test "x${have_gnu_objc}" = "xyes" ; then
|
||||||
|
AC_LANG_PUSH([Objective C])
|
||||||
|
LIBS_save="$LIBS"
|
||||||
|
LIBS="$LIBS -framework CoreServices"
|
||||||
|
AC_LINK_IFELSE(
|
||||||
|
[AC_LANG_PROGRAM(
|
||||||
|
[[
|
||||||
|
#include <CoreServices/CoreServices.h>
|
||||||
|
]],
|
||||||
|
[[
|
||||||
|
//test function here
|
||||||
|
]])],
|
||||||
|
[
|
||||||
|
have_cocoa_coreservices="yes"
|
||||||
|
cocoa_coreservices_ldflags="-framework CoreServices"
|
||||||
|
],
|
||||||
|
[have_cocoa_coreservices="no"])
|
||||||
|
LIBS="$LIBS_save"
|
||||||
|
AC_MSG_CHECKING([whether Cocoa CoreServices framework is supported])
|
||||||
|
AC_MSG_RESULT([${have_cocoa_coreservices}])
|
||||||
|
AC_LANG_POP([Objective C])
|
||||||
|
fi
|
||||||
|
])
|
||||||
|
fi
|
||||||
|
AC_SUBST(cocoa_coreservices_ldflags)
|
||||||
|
|
||||||
# Drm
|
# Drm
|
||||||
AC_ARG_ENABLE([drm],
|
AC_ARG_ENABLE([drm],
|
||||||
[AS_HELP_STRING([--enable-drm],[enable drm engine. @<:@default=disabled@:>@])],
|
[AS_HELP_STRING([--enable-drm],[enable drm engine. @<:@default=disabled@:>@])],
|
||||||
|
@ -3969,6 +3990,20 @@ EFL_ADD_LIBS([EIO], [-lm])
|
||||||
### Checks for linker characteristics
|
### Checks for linker characteristics
|
||||||
|
|
||||||
### Checks for library functions
|
### Checks for library functions
|
||||||
|
have_inotify="${ac_cv_header_sys_inotify_h}"
|
||||||
|
AM_CONDITIONAL([HAVE_INOTIFY], [test "x${have_inotify}" = "xyes"])
|
||||||
|
|
||||||
|
have_notify_win32="${have_win32}"
|
||||||
|
AC_DEFINE_IF([HAVE_NOTIFY_WIN32],
|
||||||
|
[test "x${have_notify_win32}" = "xyes"], [1],
|
||||||
|
[File monitoring with Windows notification])
|
||||||
|
AM_CONDITIONAL([HAVE_NOTIFY_WIN32], [test "x${have_notify_win32}" = "xyes"])
|
||||||
|
|
||||||
|
AC_DEFINE_IF([HAVE_NOTIFY_COCOA],
|
||||||
|
[test "x${have_darwin}" = "xyes"], [1],
|
||||||
|
[File monitoring with fsevent notification])
|
||||||
|
AM_CONDITIONAL([HAVE_NOTIFY_COCOA], [test "x${have_darwin}" = "xyes"])
|
||||||
|
|
||||||
|
|
||||||
EFL_LIB_END([Eio])
|
EFL_LIB_END([Eio])
|
||||||
dnl TODO: remove these ifdefs from code!
|
dnl TODO: remove these ifdefs from code!
|
||||||
|
|
|
@ -23,6 +23,10 @@ lib_eio_libeio_la_SOURCES += lib/eio/eio_monitor_inotify.c
|
||||||
else
|
else
|
||||||
if HAVE_NOTIFY_WIN32
|
if HAVE_NOTIFY_WIN32
|
||||||
lib_eio_libeio_la_SOURCES += lib/eio/eio_monitor_win32.c
|
lib_eio_libeio_la_SOURCES += lib/eio/eio_monitor_win32.c
|
||||||
|
else
|
||||||
|
if HAVE_NOTIFY_COCOA
|
||||||
|
lib_eio_libeio_la_SOURCES += lib/eio/eio_monitor_cocoa.c
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@ -30,6 +34,9 @@ lib_eio_libeio_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl @EIO_CFLAGS@
|
||||||
lib_eio_libeio_la_LIBADD = @EIO_LIBS@
|
lib_eio_libeio_la_LIBADD = @EIO_LIBS@
|
||||||
lib_eio_libeio_la_DEPENDENCIES = @EIO_INTERNAL_LIBS@
|
lib_eio_libeio_la_DEPENDENCIES = @EIO_INTERNAL_LIBS@
|
||||||
lib_eio_libeio_la_LDFLAGS = @EFL_LTLIBRARY_FLAGS@
|
lib_eio_libeio_la_LDFLAGS = @EFL_LTLIBRARY_FLAGS@
|
||||||
|
if HAVE_NOTIFY_COCOA
|
||||||
|
lib_eio_libeio_la_LDFLAGS += -framework CoreServices
|
||||||
|
endif
|
||||||
|
|
||||||
if EFL_ENABLE_TESTS
|
if EFL_ENABLE_TESTS
|
||||||
|
|
||||||
|
|
|
@ -1219,13 +1219,13 @@ EAPI Eio_File *eio_eet_write_cipher(Eet_File *ef,
|
||||||
EAPI extern int EIO_MONITOR_FILE_CREATED; /**< A new file was created in a watched directory */
|
EAPI extern int EIO_MONITOR_FILE_CREATED; /**< A new file was created in a watched directory */
|
||||||
EAPI extern int EIO_MONITOR_FILE_DELETED; /**< A watched file was deleted, or a file in a watched directory was deleted */
|
EAPI extern int EIO_MONITOR_FILE_DELETED; /**< A watched file was deleted, or a file in a watched directory was deleted */
|
||||||
EAPI extern int EIO_MONITOR_FILE_MODIFIED; /**< A file was modified in a watched directory */
|
EAPI extern int EIO_MONITOR_FILE_MODIFIED; /**< A file was modified in a watched directory */
|
||||||
EAPI extern int EIO_MONITOR_FILE_CLOSED; /**< A file was closed in a watched directory. This event is never sent on Windows */
|
EAPI extern int EIO_MONITOR_FILE_CLOSED; /**< A file was closed in a watched directory. This event is never sent on Windows and OSX */
|
||||||
EAPI extern int EIO_MONITOR_DIRECTORY_CREATED; /**< A new directory was created in a watched directory */
|
EAPI extern int EIO_MONITOR_DIRECTORY_CREATED; /**< A new directory was created in a watched directory */
|
||||||
EAPI extern int EIO_MONITOR_DIRECTORY_DELETED; /**< A directory has been deleted: this can be either a watched directory or one of its subdirectories */
|
EAPI extern int EIO_MONITOR_DIRECTORY_DELETED; /**< A directory has been deleted: this can be either a watched directory or one of its subdirectories */
|
||||||
EAPI extern int EIO_MONITOR_DIRECTORY_MODIFIED; /**< A directory has been modified in a watched directory */
|
EAPI extern int EIO_MONITOR_DIRECTORY_MODIFIED; /**< A directory has been modified in a watched directory */
|
||||||
EAPI extern int EIO_MONITOR_DIRECTORY_CLOSED; /**< A directory has been closed in a watched directory. This event is never sent on Windows */
|
EAPI extern int EIO_MONITOR_DIRECTORY_CLOSED; /**< A directory has been closed in a watched directory. This event is never sent on Windows and OSX */
|
||||||
EAPI extern int EIO_MONITOR_SELF_RENAME; /**< The monitored path has been renamed, an error could happen just after if the renamed path doesn't exist */
|
EAPI extern int EIO_MONITOR_SELF_RENAME; /**< The monitored path has been renamed, an error could happen just after if the renamed path doesn't exist. This event is never sent on OSX */
|
||||||
EAPI extern int EIO_MONITOR_SELF_DELETED; /**< The monitored path has been removed */
|
EAPI extern int EIO_MONITOR_SELF_DELETED; /**< The monitored path has been removed. This event is never sent on OSX */
|
||||||
EAPI extern int EIO_MONITOR_ERROR; /**< During operation the monitor failed and will no longer work. eio_monitor_del must be called on it. */
|
EAPI extern int EIO_MONITOR_ERROR; /**< During operation the monitor failed and will no longer work. eio_monitor_del must be called on it. */
|
||||||
|
|
||||||
typedef struct _Eio_Monitor Eio_Monitor;
|
typedef struct _Eio_Monitor Eio_Monitor;
|
||||||
|
|
|
@ -0,0 +1,405 @@
|
||||||
|
/* EIO - EFL data type library
|
||||||
|
* Copyright (C) 2015 Enlightenment Developers:
|
||||||
|
* Pierre Lamot <pierre.lamot@openwide.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"
|
||||||
|
|
||||||
|
#import <CoreServices/CoreServices.h>
|
||||||
|
|
||||||
|
static CFTimeInterval _latency = 0.1;
|
||||||
|
|
||||||
|
/*============================================================================*
|
||||||
|
* Local *
|
||||||
|
*============================================================================*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @cond LOCAL
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct _Eio_Monitor_Backend
|
||||||
|
{
|
||||||
|
Eio_Monitor *parent;
|
||||||
|
///the monitored path
|
||||||
|
char *mon_path;
|
||||||
|
///the actual file path
|
||||||
|
char *real_path;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct _FSEvent_Info FSEvent_Info;
|
||||||
|
|
||||||
|
struct _FSEvent_Info {
|
||||||
|
char *path;
|
||||||
|
FSEventStreamEventFlags flags;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct _Eio_FSEvent_Table Eio_FSEvent_Table;
|
||||||
|
|
||||||
|
struct _Eio_FSEvent_Table
|
||||||
|
{
|
||||||
|
int mask;
|
||||||
|
int *ev_file_code;
|
||||||
|
int *ev_dir_code;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define EIO_FSEVENT_LINE(FSe, Ef, Ed) \
|
||||||
|
{ kFSEventStreamEventFlag##FSe, &EIO_MONITOR_##Ef, &EIO_MONITOR_##Ed }
|
||||||
|
|
||||||
|
static const Eio_FSEvent_Table match[] = {
|
||||||
|
EIO_FSEVENT_LINE(ItemChangeOwner, FILE_MODIFIED, DIRECTORY_MODIFIED),
|
||||||
|
EIO_FSEVENT_LINE(ItemInodeMetaMod, FILE_MODIFIED, DIRECTORY_MODIFIED),
|
||||||
|
EIO_FSEVENT_LINE(ItemXattrMod, FILE_MODIFIED, DIRECTORY_MODIFIED),
|
||||||
|
EIO_FSEVENT_LINE(ItemModified, FILE_MODIFIED, DIRECTORY_MODIFIED),
|
||||||
|
EIO_FSEVENT_LINE(ItemRemoved, FILE_DELETED, DIRECTORY_DELETED),
|
||||||
|
EIO_FSEVENT_LINE(ItemCreated, FILE_CREATED, DIRECTORY_CREATED),
|
||||||
|
EIO_FSEVENT_LINE(RootChanged, SELF_DELETED, SELF_DELETED)
|
||||||
|
};
|
||||||
|
|
||||||
|
static FSEventStreamRef _stream = NULL;
|
||||||
|
static Eina_Hash *_fsevent_monitors = NULL;
|
||||||
|
static CFMutableArrayRef _paths_to_watch = NULL;
|
||||||
|
static dispatch_queue_t _dispatch_queue;
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_handle_fsevent_with_monitor(const Eina_Hash *hash EINA_UNUSED,
|
||||||
|
const void *key EINA_UNUSED,
|
||||||
|
void *data,
|
||||||
|
void *fdata)
|
||||||
|
{
|
||||||
|
FSEvent_Info *event_info = (FSEvent_Info*)fdata;
|
||||||
|
Eio_Monitor_Backend *backend = (Eio_Monitor_Backend*)data;
|
||||||
|
FSEventStreamEventFlags flags = event_info->flags;
|
||||||
|
unsigned int i;
|
||||||
|
Eina_Bool is_dir;
|
||||||
|
unsigned int length, tmp_length;
|
||||||
|
|
||||||
|
char *tmp = NULL;
|
||||||
|
|
||||||
|
if (backend->parent->delete_me)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (!eina_str_has_prefix(event_info->path, backend->real_path))
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
length = strlen(event_info->path) - strlen(backend->real_path);
|
||||||
|
if (length == 0)
|
||||||
|
{
|
||||||
|
tmp = strdup(backend->parent->path);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tmp_length =
|
||||||
|
eina_stringshare_strlen(backend->parent->path) + length + 2;
|
||||||
|
|
||||||
|
tmp = malloc(sizeof(char) * tmp_length);
|
||||||
|
snprintf(tmp, tmp_length, "%s/%s",
|
||||||
|
backend->parent->path,
|
||||||
|
&(event_info->path[strlen(backend->real_path) + 1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
is_dir = !!(flags & kFSEventStreamEventFlagItemIsDir);
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof (match) / sizeof (Eio_FSEvent_Table); ++i)
|
||||||
|
if (match[i].mask & flags)
|
||||||
|
{
|
||||||
|
DBG("send event from %s with event %X\n", event_info->path, flags);
|
||||||
|
_eio_monitor_send(backend->parent,
|
||||||
|
tmp,
|
||||||
|
is_dir ? *match[i].ev_dir_code : *match[i].ev_file_code);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(tmp);
|
||||||
|
//we have found the right event, no need to continue
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
_main_loop_send_event(void *data)
|
||||||
|
{
|
||||||
|
FSEvent_Info *info = (FSEvent_Info*)data;
|
||||||
|
|
||||||
|
if (!_stream)
|
||||||
|
{
|
||||||
|
//this can happen, when eio_shutdown is called
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((info->flags & kFSEventStreamEventFlagKernelDropped) != 0)
|
||||||
|
{
|
||||||
|
_eio_monitor_send(NULL, "", EIO_MONITOR_ERROR);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
eina_hash_foreach(_fsevent_monitors,
|
||||||
|
_handle_fsevent_with_monitor,
|
||||||
|
info);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
free(info->path);
|
||||||
|
free(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
_eio_fsevent_cb(ConstFSEventStreamRef stream_ref EINA_UNUSED,
|
||||||
|
void *ctx EINA_UNUSED,
|
||||||
|
size_t count,
|
||||||
|
void *event_paths,
|
||||||
|
const FSEventStreamEventFlags event_flags[],
|
||||||
|
const FSEventStreamEventId event_ids[] EINA_UNUSED
|
||||||
|
)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
FSEvent_Info *event_info;
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
event_info = malloc(sizeof(FSEvent_Info));
|
||||||
|
event_info->path = strdup(((char**)event_paths)[i]);
|
||||||
|
event_info->flags = event_flags[i];
|
||||||
|
|
||||||
|
ecore_main_loop_thread_safe_call_async(_main_loop_send_event,
|
||||||
|
event_info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_eio_fsevent_del(void *data)
|
||||||
|
{
|
||||||
|
Eio_Monitor_Backend *backend = (Eio_Monitor_Backend *)data;
|
||||||
|
free(backend);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_eio_get_monitor_path(const char *path, char **monpath, char **fullpath)
|
||||||
|
{
|
||||||
|
char realPath[PATH_MAX];
|
||||||
|
char *realPathOk;
|
||||||
|
char *dname = NULL;
|
||||||
|
char *fname = NULL;
|
||||||
|
struct stat sb;
|
||||||
|
|
||||||
|
realPathOk = realpath(path, realPath);
|
||||||
|
if (realPathOk == NULL)
|
||||||
|
{
|
||||||
|
dname = dirname((char*)path);
|
||||||
|
if (strcmp(dname, ".") == 0)
|
||||||
|
{
|
||||||
|
realPathOk = realpath("./", realPath);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
realPathOk = realpath(dname, realPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (realPathOk == NULL)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stat(realPath, &sb) < 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (S_ISDIR(sb.st_mode))
|
||||||
|
{
|
||||||
|
if (fullpath)
|
||||||
|
*fullpath = strdup(realPath);
|
||||||
|
if (monpath)
|
||||||
|
*monpath = strdup(realPath);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//not a directory, monitor parent
|
||||||
|
if (fullpath)
|
||||||
|
*fullpath = strdup(realPath);
|
||||||
|
dname = dirname(realPath);
|
||||||
|
if (monpath)
|
||||||
|
*monpath = strdup(dname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @endcond
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*============================================================================*
|
||||||
|
* Global *
|
||||||
|
*============================================================================*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @cond LOCAL
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @endcond
|
||||||
|
*/
|
||||||
|
|
||||||
|
void eio_monitor_backend_init(void)
|
||||||
|
{
|
||||||
|
_dispatch_queue = dispatch_queue_create("org.elf.fseventqueue", NULL);
|
||||||
|
_fsevent_monitors = eina_hash_string_small_new(_eio_fsevent_del);
|
||||||
|
_paths_to_watch = CFArrayCreateMutable(kCFAllocatorDefault,
|
||||||
|
0,
|
||||||
|
&kCFTypeArrayCallBacks);
|
||||||
|
}
|
||||||
|
|
||||||
|
void eio_monitor_backend_shutdown(void)
|
||||||
|
{
|
||||||
|
if (_stream)
|
||||||
|
{
|
||||||
|
FSEventStreamStop(_stream);
|
||||||
|
FSEventStreamInvalidate(_stream);
|
||||||
|
FSEventStreamRelease(_stream);
|
||||||
|
_stream = NULL;
|
||||||
|
}
|
||||||
|
dispatch_release(_dispatch_queue);
|
||||||
|
eina_hash_free(_fsevent_monitors);
|
||||||
|
CFRelease(_paths_to_watch);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void eio_monitor_backend_add(Eio_Monitor *monitor)
|
||||||
|
{
|
||||||
|
Eio_Monitor_Backend *backend;
|
||||||
|
|
||||||
|
FSEventStreamEventId eventid;
|
||||||
|
|
||||||
|
CFStringRef path = NULL;
|
||||||
|
|
||||||
|
//the path we should monitor
|
||||||
|
char *monitor_path = NULL;
|
||||||
|
//the real file path
|
||||||
|
char *real_path = NULL;
|
||||||
|
|
||||||
|
_eio_get_monitor_path(monitor->path, &monitor_path, &real_path);
|
||||||
|
|
||||||
|
backend = calloc(1, sizeof (Eio_Monitor_Backend));
|
||||||
|
if (!backend)
|
||||||
|
{
|
||||||
|
free(monitor_path);
|
||||||
|
eio_monitor_fallback_add(monitor);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
path = CFStringCreateWithCString(NULL,
|
||||||
|
monitor_path,
|
||||||
|
kCFStringEncodingUTF8);
|
||||||
|
|
||||||
|
CFArrayAppendValue(_paths_to_watch, path);
|
||||||
|
|
||||||
|
if (_stream)
|
||||||
|
{
|
||||||
|
eventid = FSEventStreamGetLatestEventId(_stream);
|
||||||
|
FSEventStreamRelease(_stream);
|
||||||
|
_stream = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
eventid = kFSEventStreamEventIdSinceNow;
|
||||||
|
}
|
||||||
|
|
||||||
|
_stream = FSEventStreamCreate(NULL,
|
||||||
|
_eio_fsevent_cb,
|
||||||
|
NULL,
|
||||||
|
_paths_to_watch,
|
||||||
|
eventid,
|
||||||
|
_latency,
|
||||||
|
kFSEventStreamCreateFlagFileEvents
|
||||||
|
| kFSEventStreamCreateFlagNoDefer
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!_stream)
|
||||||
|
{
|
||||||
|
eio_monitor_fallback_add(monitor);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
backend->parent = monitor;
|
||||||
|
backend->mon_path = monitor_path;
|
||||||
|
backend->real_path = real_path;
|
||||||
|
monitor->backend = backend;
|
||||||
|
|
||||||
|
eina_hash_direct_add(_fsevent_monitors, monitor->path, backend);
|
||||||
|
|
||||||
|
FSEventStreamSetDispatchQueue(_stream, _dispatch_queue);
|
||||||
|
FSEventStreamStart(_stream);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void eio_monitor_backend_del(Eio_Monitor *monitor)
|
||||||
|
{
|
||||||
|
Eio_Monitor_Backend *backend;
|
||||||
|
CFStringRef path = NULL;
|
||||||
|
FSEventStreamEventId eventid;
|
||||||
|
char *monitor_path;
|
||||||
|
|
||||||
|
if (!_stream)
|
||||||
|
{
|
||||||
|
eio_monitor_fallback_del(monitor);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_eio_get_monitor_path(monitor->path, &monitor_path, NULL);
|
||||||
|
|
||||||
|
eventid = FSEventStreamGetLatestEventId(_stream);
|
||||||
|
FSEventStreamRelease(_stream);
|
||||||
|
_stream = NULL;
|
||||||
|
|
||||||
|
path = CFStringCreateWithCString(NULL,
|
||||||
|
monitor_path,
|
||||||
|
kCFStringEncodingUTF8);
|
||||||
|
|
||||||
|
CFIndex idx =
|
||||||
|
CFArrayGetFirstIndexOfValue(_paths_to_watch,
|
||||||
|
CFRangeMake(0,
|
||||||
|
CFArrayGetCount(_paths_to_watch)
|
||||||
|
),
|
||||||
|
path);
|
||||||
|
|
||||||
|
if (idx != -1)
|
||||||
|
{
|
||||||
|
CFArrayRemoveValueAtIndex(_paths_to_watch, idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
_stream = FSEventStreamCreate(NULL,
|
||||||
|
_eio_fsevent_cb,
|
||||||
|
NULL,
|
||||||
|
_paths_to_watch,
|
||||||
|
eventid,
|
||||||
|
_latency,
|
||||||
|
kFSEventStreamCreateFlagFileEvents
|
||||||
|
| kFSEventStreamCreateFlagNoDefer
|
||||||
|
);
|
||||||
|
backend = monitor->backend;
|
||||||
|
monitor->backend = NULL;
|
||||||
|
if (!backend) return;
|
||||||
|
|
||||||
|
eina_hash_del(_fsevent_monitors, monitor->path, backend);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*============================================================================*
|
||||||
|
* API *
|
||||||
|
*============================================================================*/
|
|
@ -270,7 +270,7 @@ _eio_monitor_fallback_timer_cb(void *data)
|
||||||
* @cond LOCAL
|
* @cond LOCAL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if !defined HAVE_SYS_INOTIFY_H && !defined HAVE_NOTIFY_WIN32
|
#if !defined HAVE_SYS_INOTIFY_H && !defined HAVE_NOTIFY_WIN32 && !defined HAVE_NOTIFY_COCOA
|
||||||
void eio_monitor_backend_init(void)
|
void eio_monitor_backend_init(void)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,9 +17,9 @@
|
||||||
#define TEST_TIMEOUT_SEC 10
|
#define TEST_TIMEOUT_SEC 10
|
||||||
#define TEST_OPERATION_DELAY 0.5
|
#define TEST_OPERATION_DELAY 0.5
|
||||||
|
|
||||||
static Ecore_Timer * test_timeout_timer;
|
static Ecore_Timer *test_timeout_timer;
|
||||||
|
|
||||||
static Eina_Bool _test_timeout_cb(void* data EINA_UNUSED)
|
static Eina_Bool _test_timeout_cb(void *data EINA_UNUSED)
|
||||||
{
|
{
|
||||||
ck_abort_msg("test timeout");
|
ck_abort_msg("test timeout");
|
||||||
ecore_main_loop_quit();
|
ecore_main_loop_quit();
|
||||||
|
@ -35,16 +35,26 @@ static void _cancel_timeout()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Eina_Bool _test_timeout_expected(void *data EINA_UNUSED)
|
||||||
|
{
|
||||||
|
if (test_timeout_timer != NULL)
|
||||||
|
{
|
||||||
|
_cancel_timeout();
|
||||||
|
}
|
||||||
|
ecore_main_loop_quit();
|
||||||
|
return ECORE_CALLBACK_CANCEL;
|
||||||
|
}
|
||||||
|
|
||||||
///////////////// file and directory operations
|
///////////////// file and directory operations
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char* src;
|
const char *src;
|
||||||
const char* dst;
|
const char *dst;
|
||||||
} RenameOperation;
|
} RenameOperation;
|
||||||
|
|
||||||
static Eina_Bool _delete_directory(void* data)
|
static Eina_Bool _delete_directory(void *data)
|
||||||
{
|
{
|
||||||
const char* dirname = (const char*)data;
|
const char *dirname = (const char*)data;
|
||||||
if (ecore_file_is_dir(dirname))
|
if (ecore_file_is_dir(dirname))
|
||||||
{
|
{
|
||||||
ecore_file_recursive_rm(dirname);
|
ecore_file_recursive_rm(dirname);
|
||||||
|
@ -52,40 +62,40 @@ static Eina_Bool _delete_directory(void* data)
|
||||||
return ECORE_CALLBACK_CANCEL;
|
return ECORE_CALLBACK_CANCEL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Eina_Bool _create_directory(void* data)
|
static Eina_Bool _create_directory(void *data)
|
||||||
{
|
{
|
||||||
const char* dirname = (const char*)data;
|
const char *dirname = (const char*)data;
|
||||||
ecore_file_mkpath(dirname);
|
ecore_file_mkpath(dirname);
|
||||||
return ECORE_CALLBACK_CANCEL;
|
return ECORE_CALLBACK_CANCEL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static Eina_Bool _create_file(void* data)
|
static Eina_Bool _create_file(void *data)
|
||||||
{
|
{
|
||||||
FILE* fd = fopen((const char*)data, "w+");
|
FILE *fd = fopen((const char*)data, "w+");
|
||||||
ck_assert_ptr_ne(fd, NULL);
|
ck_assert_ptr_ne(fd, NULL);
|
||||||
fprintf(fd, "test test");
|
fprintf(fd, "test test");
|
||||||
fclose(fd);
|
fclose(fd);
|
||||||
return ECORE_CALLBACK_CANCEL;
|
return ECORE_CALLBACK_CANCEL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Eina_Bool _delete_file(void* data)
|
static Eina_Bool _delete_file(void *data)
|
||||||
{
|
{
|
||||||
Eina_Bool file_removed = ecore_file_remove((const char*)data);
|
Eina_Bool file_removed = ecore_file_remove((const char*)data);
|
||||||
ck_assert(file_removed);
|
ck_assert(file_removed);
|
||||||
return ECORE_CALLBACK_CANCEL;
|
return ECORE_CALLBACK_CANCEL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Eina_Bool _modify_file(void* data)
|
static Eina_Bool _modify_file(void *data)
|
||||||
{
|
{
|
||||||
FILE* fd = fopen((const char*)data, "a");
|
FILE *fd = fopen((const char*)data, "a");
|
||||||
ck_assert_ptr_ne(fd, NULL);
|
ck_assert_ptr_ne(fd, NULL);
|
||||||
fprintf(fd, "appened");
|
fprintf(fd, "appened");
|
||||||
fclose(fd);
|
fclose(fd);
|
||||||
return ECORE_CALLBACK_CANCEL;
|
return ECORE_CALLBACK_CANCEL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Eina_Bool _modify_attrib_file(void* data)
|
static Eina_Bool _modify_attrib_file(void *data)
|
||||||
{
|
{
|
||||||
int ret = chmod((const char*)data, 0666);
|
int ret = chmod((const char*)data, 0666);
|
||||||
ck_assert_int_eq(ret, 0);
|
ck_assert_int_eq(ret, 0);
|
||||||
|
@ -94,16 +104,17 @@ static Eina_Bool _modify_attrib_file(void* data)
|
||||||
|
|
||||||
/////// helper functions
|
/////// helper functions
|
||||||
|
|
||||||
static void _check_event_path(void* data, void* event)
|
static Eina_Bool _check_event_path(void *data, void *event)
|
||||||
{
|
{
|
||||||
const char* expected_path = ecore_file_realpath((const char*)data);
|
const char *expected_path = (const char*)data;
|
||||||
const char* actual_path = ecore_file_realpath(((Eio_Monitor_Event*)event)->filename);
|
const char *actual_path = ((Eio_Monitor_Event*)event)->filename;
|
||||||
ck_assert_str_eq(actual_path, expected_path);
|
ck_assert_str_eq((const char*)data, ((Eio_Monitor_Event*)event)->filename);
|
||||||
|
return EINA_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Eina_Tmpstr* _common_init()
|
static Eina_Tmpstr *_common_init()
|
||||||
{
|
{
|
||||||
Eina_Tmpstr* dirname;
|
Eina_Tmpstr *dirname;
|
||||||
fail_if(eio_init() != 1);
|
fail_if(eio_init() != 1);
|
||||||
ecore_file_init();
|
ecore_file_init();
|
||||||
|
|
||||||
|
@ -114,7 +125,7 @@ static Eina_Tmpstr* _common_init()
|
||||||
return dirname;
|
return dirname;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _common_shutdown(Eina_Tmpstr* dirname)
|
static void _common_shutdown(Eina_Tmpstr *dirname)
|
||||||
{
|
{
|
||||||
_delete_directory((void*)dirname);
|
_delete_directory((void*)dirname);
|
||||||
ecore_file_shutdown();
|
ecore_file_shutdown();
|
||||||
|
@ -124,21 +135,26 @@ static void _common_shutdown(Eina_Tmpstr* dirname)
|
||||||
|
|
||||||
/////// tests monitoring a directory
|
/////// tests monitoring a directory
|
||||||
|
|
||||||
static void _file_created_cb(void* data, int type, void* event)
|
static void _file_created_cb(void *data, int type, void *event)
|
||||||
{
|
{
|
||||||
ck_assert_int_eq(type, (int)EIO_MONITOR_FILE_CREATED);
|
ck_assert_int_eq(type, (int)EIO_MONITOR_FILE_CREATED);
|
||||||
_check_event_path(data, event);
|
if (_check_event_path(data, event))
|
||||||
_cancel_timeout();
|
{
|
||||||
ecore_main_loop_quit();
|
_cancel_timeout();
|
||||||
|
ecore_main_loop_quit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
START_TEST(eio_test_monitor_directory_file_created_notify)
|
START_TEST(eio_test_monitor_directory_file_created_notify)
|
||||||
{
|
{
|
||||||
Eina_Tmpstr* dirname = _common_init();
|
Eina_Tmpstr *dirname = _common_init();
|
||||||
Eina_Stringshare* filename;
|
Eina_Stringshare *filename;
|
||||||
|
|
||||||
filename = eina_stringshare_printf("%s/filecreated", dirname);
|
filename = eina_stringshare_printf("%s/eio_test_monitor_directory_file_created_notify", dirname);
|
||||||
|
|
||||||
|
//sleep to avoid catching event generated by above manipulations
|
||||||
|
usleep(500000);
|
||||||
|
|
||||||
//monitor directory
|
//monitor directory
|
||||||
eio_monitor_add(dirname);
|
eio_monitor_add(dirname);
|
||||||
|
@ -152,22 +168,27 @@ START_TEST(eio_test_monitor_directory_file_created_notify)
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
static void _file_deleted_cb(void* data, int type, void* event)
|
static void _file_deleted_cb(void *data, int type, void *event)
|
||||||
{
|
{
|
||||||
ck_assert_int_eq(type, (int)EIO_MONITOR_FILE_DELETED);
|
ck_assert_int_eq(type, (int)EIO_MONITOR_FILE_DELETED);
|
||||||
_check_event_path(data, event);
|
if (_check_event_path(data, event))
|
||||||
_cancel_timeout();
|
{
|
||||||
ecore_main_loop_quit();
|
_cancel_timeout();
|
||||||
|
ecore_main_loop_quit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
START_TEST(eio_test_monitor_directory_file_deleted_notify)
|
START_TEST(eio_test_monitor_directory_file_deleted_notify)
|
||||||
{
|
{
|
||||||
Eina_Tmpstr* dirname = _common_init();
|
Eina_Tmpstr *dirname = _common_init();
|
||||||
Eina_Stringshare* filename;
|
Eina_Stringshare *filename;
|
||||||
|
|
||||||
filename = eina_stringshare_printf("%s/filecreated", dirname);
|
filename = eina_stringshare_printf("%s/eio_test_monitor_directory_file_deleted_notify", dirname);
|
||||||
_create_file((void*)filename);
|
_create_file((void*)filename);
|
||||||
|
|
||||||
|
//sleep to avoid catching event generated by above manipulations
|
||||||
|
usleep(500000);
|
||||||
|
|
||||||
//monitor directory
|
//monitor directory
|
||||||
eio_monitor_add(dirname);
|
eio_monitor_add(dirname);
|
||||||
ecore_event_handler_add(EIO_MONITOR_FILE_DELETED, (Ecore_Event_Handler_Cb)_file_deleted_cb, filename);
|
ecore_event_handler_add(EIO_MONITOR_FILE_DELETED, (Ecore_Event_Handler_Cb)_file_deleted_cb, filename);
|
||||||
|
@ -180,22 +201,27 @@ START_TEST(eio_test_monitor_directory_file_deleted_notify)
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
static void _file_modified_cb(void* data, int type, void* event)
|
static void _file_modified_cb(void *data, int type, void *event)
|
||||||
{
|
{
|
||||||
ck_assert_int_eq(type, (int)EIO_MONITOR_FILE_MODIFIED);
|
ck_assert_int_eq(type, (int)EIO_MONITOR_FILE_MODIFIED);
|
||||||
_check_event_path(data, event);
|
if(_check_event_path(data, event))
|
||||||
_cancel_timeout();
|
{
|
||||||
ecore_main_loop_quit();
|
_cancel_timeout();
|
||||||
|
ecore_main_loop_quit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
START_TEST(eio_test_monitor_directory_file_modified_notify)
|
START_TEST(eio_test_monitor_directory_file_modified_notify)
|
||||||
{
|
{
|
||||||
Eina_Tmpstr* dirname = _common_init();
|
Eina_Tmpstr *dirname = _common_init();
|
||||||
Eina_Stringshare* filename;
|
Eina_Stringshare *filename;
|
||||||
|
|
||||||
filename = eina_stringshare_printf("%s/filecreated", dirname);
|
filename = eina_stringshare_printf("%s/eio_test_monitor_directory_file_modified_notify", dirname);
|
||||||
_create_file((void*)filename);
|
_create_file((void*)filename);
|
||||||
|
|
||||||
|
//sleep to avoid catching event generated by above manipulations
|
||||||
|
usleep(500000);
|
||||||
|
|
||||||
//monitor directory
|
//monitor directory
|
||||||
eio_monitor_add(dirname);
|
eio_monitor_add(dirname);
|
||||||
ecore_event_handler_add(EIO_MONITOR_FILE_MODIFIED, (Ecore_Event_Handler_Cb)_file_modified_cb, filename);
|
ecore_event_handler_add(EIO_MONITOR_FILE_MODIFIED, (Ecore_Event_Handler_Cb)_file_modified_cb, filename);
|
||||||
|
@ -209,22 +235,27 @@ START_TEST(eio_test_monitor_directory_file_modified_notify)
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
static void _file_closed_cb(void* data, int type, void* event)
|
static void _file_closed_cb(void *data, int type, void *event)
|
||||||
{
|
{
|
||||||
ck_assert_int_eq(type, (int)EIO_MONITOR_FILE_CLOSED);
|
ck_assert_int_eq(type, (int)EIO_MONITOR_FILE_CLOSED);
|
||||||
_check_event_path(data, event);
|
if (_check_event_path(data, event))
|
||||||
_cancel_timeout();
|
{
|
||||||
ecore_main_loop_quit();
|
_cancel_timeout();
|
||||||
|
ecore_main_loop_quit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
START_TEST(eio_test_monitor_directory_file_closed_notify)
|
START_TEST(eio_test_monitor_directory_file_closed_notify)
|
||||||
{
|
{
|
||||||
Eina_Tmpstr* dirname = _common_init();
|
Eina_Tmpstr *dirname = _common_init();
|
||||||
Eina_Stringshare* filename;
|
Eina_Stringshare *filename;
|
||||||
|
|
||||||
filename = eina_stringshare_printf("%s/filecreated", dirname);
|
filename = eina_stringshare_printf("%s/eio_test_monitor_directory_file_closed_notify", dirname);
|
||||||
_create_file((void*)filename);
|
_create_file((void*)filename);
|
||||||
|
|
||||||
|
//sleep to avoid catching event generated by above manipulations
|
||||||
|
usleep(500000);
|
||||||
|
|
||||||
//monitor directory
|
//monitor directory
|
||||||
eio_monitor_add(dirname);
|
eio_monitor_add(dirname);
|
||||||
ecore_event_handler_add(EIO_MONITOR_FILE_CLOSED, (Ecore_Event_Handler_Cb)_file_closed_cb, filename);
|
ecore_event_handler_add(EIO_MONITOR_FILE_CLOSED, (Ecore_Event_Handler_Cb)_file_closed_cb, filename);
|
||||||
|
@ -236,20 +267,25 @@ START_TEST(eio_test_monitor_directory_file_closed_notify)
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
static void _directory_created_cb(void* data, int type, void* event)
|
static void _directory_created_cb(void *data, int type, void *event)
|
||||||
{
|
{
|
||||||
ck_assert_int_eq(type, (int)EIO_MONITOR_DIRECTORY_CREATED);
|
ck_assert_int_eq(type, (int)EIO_MONITOR_DIRECTORY_CREATED);
|
||||||
_check_event_path(data, event);
|
if (_check_event_path(data, event))
|
||||||
_cancel_timeout();
|
{
|
||||||
ecore_main_loop_quit();
|
_cancel_timeout();
|
||||||
|
ecore_main_loop_quit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
START_TEST(eio_test_monitor_directory_directory_created_notify)
|
START_TEST(eio_test_monitor_directory_directory_created_notify)
|
||||||
{
|
{
|
||||||
Eina_Tmpstr* dirname = _common_init();
|
Eina_Tmpstr *dirname = _common_init();
|
||||||
Eina_Stringshare* filename;
|
Eina_Stringshare *filename;
|
||||||
|
|
||||||
filename = eina_stringshare_printf("%s/dircreated", dirname);
|
filename = eina_stringshare_printf("%s/eio_test_monitor_directory_directory_created_notify", dirname);
|
||||||
|
|
||||||
|
//sleep to avoid catching event generated by above manipulations
|
||||||
|
usleep(500000);
|
||||||
|
|
||||||
//monitor directory
|
//monitor directory
|
||||||
eio_monitor_add(dirname);
|
eio_monitor_add(dirname);
|
||||||
|
@ -263,22 +299,27 @@ START_TEST(eio_test_monitor_directory_directory_created_notify)
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
static void _directory_deleted_cb(void* data, int type, void* event)
|
static void _directory_deleted_cb(void *data, int type, void *event)
|
||||||
{
|
{
|
||||||
ck_assert_int_eq(type, (int)EIO_MONITOR_DIRECTORY_DELETED);
|
ck_assert_int_eq(type, (int)EIO_MONITOR_DIRECTORY_DELETED);
|
||||||
_check_event_path(data, event);
|
if (_check_event_path(data, event))
|
||||||
_cancel_timeout();
|
{
|
||||||
ecore_main_loop_quit();
|
_cancel_timeout();
|
||||||
|
ecore_main_loop_quit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
START_TEST(eio_test_monitor_directory_directory_deleted_notify)
|
START_TEST(eio_test_monitor_directory_directory_deleted_notify)
|
||||||
{
|
{
|
||||||
Eina_Tmpstr* dirname = _common_init();
|
Eina_Tmpstr *dirname = _common_init();
|
||||||
Eina_Stringshare* filename;
|
Eina_Stringshare *filename;
|
||||||
|
|
||||||
filename = eina_stringshare_printf("%s/dircreated", dirname);
|
filename = eina_stringshare_printf("%s/eio_test_monitor_directory_directory_deleted_notify", dirname);
|
||||||
_create_directory((void*)filename);
|
_create_directory((void*)filename);
|
||||||
|
|
||||||
|
//sleep to avoid catching event generated by above manipulations
|
||||||
|
usleep(500000);
|
||||||
|
|
||||||
//monitor directory
|
//monitor directory
|
||||||
eio_monitor_add(dirname);
|
eio_monitor_add(dirname);
|
||||||
ecore_event_handler_add(EIO_MONITOR_DIRECTORY_DELETED, (Ecore_Event_Handler_Cb)_directory_deleted_cb, filename);
|
ecore_event_handler_add(EIO_MONITOR_DIRECTORY_DELETED, (Ecore_Event_Handler_Cb)_directory_deleted_cb, filename);
|
||||||
|
@ -291,23 +332,28 @@ START_TEST(eio_test_monitor_directory_directory_deleted_notify)
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
static void _directory_modified_cb(void* data, int type, void* event)
|
static void _directory_modified_cb(void *data, int type, void *event)
|
||||||
{
|
{
|
||||||
ck_assert_int_eq(type, (int)EIO_MONITOR_DIRECTORY_MODIFIED);
|
ck_assert_int_eq(type, (int)EIO_MONITOR_DIRECTORY_MODIFIED);
|
||||||
_check_event_path(data, event);
|
if (_check_event_path(data, event))
|
||||||
_cancel_timeout();
|
{
|
||||||
ecore_main_loop_quit();
|
_cancel_timeout();
|
||||||
|
ecore_main_loop_quit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
START_TEST(eio_test_monitor_directory_directory_modified_notify)
|
START_TEST(eio_test_monitor_directory_directory_modified_notify)
|
||||||
{
|
{
|
||||||
Eina_Tmpstr* dirname = _common_init();
|
Eina_Tmpstr *dirname = _common_init();
|
||||||
Eina_Stringshare* filename;
|
Eina_Stringshare *filename;
|
||||||
|
|
||||||
filename = eina_stringshare_printf("%s/filecreated", dirname);
|
filename = eina_stringshare_printf("%s/eio_test_monitor_directory_directory_modified_notify", dirname);
|
||||||
_create_directory((void*)filename);
|
_create_directory((void*)filename);
|
||||||
|
|
||||||
|
//sleep to avoid catching event generated by above manipulations
|
||||||
|
usleep(500000);
|
||||||
|
|
||||||
//monitor directory
|
//monitor directory
|
||||||
eio_monitor_add(dirname);
|
eio_monitor_add(dirname);
|
||||||
ecore_event_handler_add(EIO_MONITOR_DIRECTORY_MODIFIED, (Ecore_Event_Handler_Cb)_directory_modified_cb, filename);
|
ecore_event_handler_add(EIO_MONITOR_DIRECTORY_MODIFIED, (Ecore_Event_Handler_Cb)_directory_modified_cb, filename);
|
||||||
|
@ -321,18 +367,23 @@ START_TEST(eio_test_monitor_directory_directory_modified_notify)
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
|
||||||
static void _directory_self_deleted_cb(void* data, int type, void* event)
|
static void _directory_self_deleted_cb(void *data, int type, void *event)
|
||||||
{
|
{
|
||||||
ck_assert_int_eq(type, (int)EIO_MONITOR_SELF_DELETED);
|
ck_assert_int_eq(type, (int)EIO_MONITOR_SELF_DELETED);
|
||||||
_check_event_path(data, event);
|
if (_check_event_path(data, event))
|
||||||
_cancel_timeout();
|
{
|
||||||
ecore_main_loop_quit();
|
_cancel_timeout();
|
||||||
|
ecore_main_loop_quit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
START_TEST(eio_test_monitor_directory_directory_self_deleted_notify)
|
START_TEST(eio_test_monitor_directory_directory_self_deleted_notify)
|
||||||
{
|
{
|
||||||
Eina_Tmpstr* dirname = _common_init();
|
Eina_Tmpstr *dirname = _common_init();
|
||||||
|
|
||||||
|
//sleep to avoid catching event generated by above manipulations
|
||||||
|
usleep(500000);
|
||||||
|
|
||||||
//monitor directory
|
//monitor directory
|
||||||
eio_monitor_add(dirname);
|
eio_monitor_add(dirname);
|
||||||
|
@ -350,12 +401,15 @@ END_TEST
|
||||||
|
|
||||||
START_TEST(eio_test_monitor_file_file_modified_notify)
|
START_TEST(eio_test_monitor_file_file_modified_notify)
|
||||||
{
|
{
|
||||||
Eina_Tmpstr* dirname = _common_init();
|
Eina_Tmpstr *dirname = _common_init();
|
||||||
Eina_Stringshare* filename;
|
Eina_Stringshare *filename;
|
||||||
|
|
||||||
filename = eina_stringshare_printf("%s/filecreated", dirname);
|
filename = eina_stringshare_printf("%s/filecreated", dirname);
|
||||||
_create_file((void*)filename);
|
_create_file((void*)filename);
|
||||||
|
|
||||||
|
//sleep to avoid catching event generated by above manipulations
|
||||||
|
usleep(500000);
|
||||||
|
|
||||||
//monitor file
|
//monitor file
|
||||||
eio_monitor_add(filename);
|
eio_monitor_add(filename);
|
||||||
ecore_event_handler_add(EIO_MONITOR_FILE_MODIFIED, (Ecore_Event_Handler_Cb)_file_modified_cb, filename);
|
ecore_event_handler_add(EIO_MONITOR_FILE_MODIFIED, (Ecore_Event_Handler_Cb)_file_modified_cb, filename);
|
||||||
|
@ -371,12 +425,15 @@ END_TEST
|
||||||
|
|
||||||
START_TEST(eio_test_monitor_file_file_attrib_modified_notify)
|
START_TEST(eio_test_monitor_file_file_attrib_modified_notify)
|
||||||
{
|
{
|
||||||
Eina_Tmpstr* dirname = _common_init();
|
Eina_Tmpstr *dirname = _common_init();
|
||||||
Eina_Stringshare* filename;
|
Eina_Stringshare *filename;
|
||||||
|
|
||||||
filename = eina_stringshare_printf("%s/filecreated", dirname);
|
filename = eina_stringshare_printf("%s/eio_test_monitor_file_file_attrib_modified_notify", dirname);
|
||||||
_create_file((void*)filename);
|
_create_file((void*)filename);
|
||||||
|
|
||||||
|
//sleep to avoid catching event generated by above manipulations
|
||||||
|
usleep(500000);
|
||||||
|
|
||||||
//monitor file
|
//monitor file
|
||||||
eio_monitor_add(filename);
|
eio_monitor_add(filename);
|
||||||
ecore_event_handler_add(EIO_MONITOR_FILE_MODIFIED, (Ecore_Event_Handler_Cb)_file_modified_cb, filename);
|
ecore_event_handler_add(EIO_MONITOR_FILE_MODIFIED, (Ecore_Event_Handler_Cb)_file_modified_cb, filename);
|
||||||
|
@ -392,12 +449,15 @@ END_TEST
|
||||||
|
|
||||||
START_TEST(eio_test_monitor_file_file_closed_notify)
|
START_TEST(eio_test_monitor_file_file_closed_notify)
|
||||||
{
|
{
|
||||||
Eina_Tmpstr* dirname = _common_init();
|
Eina_Tmpstr *dirname = _common_init();
|
||||||
Eina_Stringshare* filename;
|
Eina_Stringshare *filename;
|
||||||
|
|
||||||
filename = eina_stringshare_printf("%s/filecreated", dirname);
|
filename = eina_stringshare_printf("%s/eio_test_monitor_file_file_closed_notify", dirname);
|
||||||
_create_file((void*)filename);
|
_create_file((void*)filename);
|
||||||
|
|
||||||
|
//sleep to avoid catching event generated by above manipulations
|
||||||
|
usleep(500000);
|
||||||
|
|
||||||
//monitor file
|
//monitor file
|
||||||
eio_monitor_add(dirname);
|
eio_monitor_add(dirname);
|
||||||
ecore_event_handler_add(EIO_MONITOR_FILE_CLOSED, (Ecore_Event_Handler_Cb)_file_closed_cb, filename);
|
ecore_event_handler_add(EIO_MONITOR_FILE_CLOSED, (Ecore_Event_Handler_Cb)_file_closed_cb, filename);
|
||||||
|
@ -411,12 +471,15 @@ END_TEST
|
||||||
|
|
||||||
START_TEST(eio_test_monitor_file_file_self_deleted_notify)
|
START_TEST(eio_test_monitor_file_file_self_deleted_notify)
|
||||||
{
|
{
|
||||||
Eina_Tmpstr* dirname = _common_init();
|
Eina_Tmpstr *dirname = _common_init();
|
||||||
Eina_Stringshare* filename;
|
Eina_Stringshare *filename;
|
||||||
|
|
||||||
filename = eina_stringshare_printf("%s/filecreated", dirname);
|
filename = eina_stringshare_printf("%s/eio_test_monitor_file_file_self_deleted_notify", dirname);
|
||||||
_create_file((void*)filename);
|
_create_file((void*)filename);
|
||||||
|
|
||||||
|
//sleep to avoid catching event generated by above manipulations
|
||||||
|
usleep(500000);
|
||||||
|
|
||||||
//monitor file
|
//monitor file
|
||||||
eio_monitor_add(filename);
|
eio_monitor_add(filename);
|
||||||
ecore_event_handler_add(EIO_MONITOR_SELF_DELETED, (Ecore_Event_Handler_Cb)_directory_self_deleted_cb, filename);
|
ecore_event_handler_add(EIO_MONITOR_SELF_DELETED, (Ecore_Event_Handler_Cb)_directory_self_deleted_cb, filename);
|
||||||
|
@ -429,24 +492,189 @@ START_TEST(eio_test_monitor_file_file_self_deleted_notify)
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(eio_test_monitor_two_monitors_one_event)
|
||||||
|
{
|
||||||
|
Eina_Tmpstr *dirname = _common_init();
|
||||||
|
Eina_Tmpstr *dirname2;
|
||||||
|
|
||||||
|
Eina_Stringshare *filename;
|
||||||
|
|
||||||
|
eina_file_mkdtemp("checkFileCreationXXXXXX", &dirname2);
|
||||||
|
filename = eina_stringshare_printf("%s/eio_test_monitor_two_monitors_one_event", dirname);
|
||||||
|
|
||||||
|
//sleep to avoid catching event generated by above manipulations
|
||||||
|
usleep(500000);
|
||||||
|
|
||||||
|
//monitor directory
|
||||||
|
eio_monitor_add(dirname);
|
||||||
|
eio_monitor_add(dirname2);
|
||||||
|
ecore_event_handler_add(EIO_MONITOR_FILE_CREATED, (Ecore_Event_Handler_Cb)_file_created_cb, filename);
|
||||||
|
|
||||||
|
ecore_timer_add(TEST_OPERATION_DELAY, _create_file, filename);
|
||||||
|
|
||||||
|
ecore_main_loop_begin();
|
||||||
|
|
||||||
|
_delete_directory((void*)dirname2);
|
||||||
|
_common_shutdown(dirname);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
|
||||||
|
START_TEST(eio_test_monitor_two_monitors_one_removed_one_event)
|
||||||
|
{
|
||||||
|
Eina_Tmpstr *dirname = _common_init();
|
||||||
|
Eina_Tmpstr *dirname2;
|
||||||
|
|
||||||
|
Eina_Stringshare *filename;
|
||||||
|
|
||||||
|
Eio_Monitor *monitor;
|
||||||
|
|
||||||
|
eina_file_mkdtemp("checkFileCreationXXXXXX", &dirname2);
|
||||||
|
filename = eina_stringshare_printf("%s/eio_test_monitor_two_monitors_one_removed", dirname);
|
||||||
|
|
||||||
|
//sleep to avoid catching event generated by above manipulations
|
||||||
|
usleep(500000);
|
||||||
|
|
||||||
|
//monitor directory
|
||||||
|
monitor = eio_monitor_add(dirname2);
|
||||||
|
eio_monitor_add(dirname);
|
||||||
|
eio_monitor_del(monitor);
|
||||||
|
ecore_event_handler_add(EIO_MONITOR_FILE_CREATED, (Ecore_Event_Handler_Cb)_file_created_cb, filename);
|
||||||
|
|
||||||
|
ecore_timer_add(TEST_OPERATION_DELAY, _create_file, filename);
|
||||||
|
|
||||||
|
ecore_main_loop_begin();
|
||||||
|
|
||||||
|
_delete_directory((void*)dirname2);
|
||||||
|
_common_shutdown(dirname);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
static void _unexpected_event_cb(void *data, int type, void *event)
|
||||||
|
{
|
||||||
|
ck_abort_msg("unexpected event");
|
||||||
|
}
|
||||||
|
|
||||||
|
START_TEST(eio_test_monitor_two_monitors_one_removed_no_event)
|
||||||
|
{
|
||||||
|
Eina_Tmpstr *dirname = _common_init();
|
||||||
|
Eina_Tmpstr *dirname2;
|
||||||
|
|
||||||
|
Eina_Stringshare *filename;
|
||||||
|
|
||||||
|
Eio_Monitor *monitor;
|
||||||
|
|
||||||
|
eina_file_mkdtemp("checkFileCreationXXXXXX", &dirname2);
|
||||||
|
filename = eina_stringshare_printf("%s/eio_test_monitor_two_monitors_one_removed", dirname);
|
||||||
|
|
||||||
|
//sleep to avoid catching event generated by above manipulations
|
||||||
|
usleep(500000);
|
||||||
|
|
||||||
|
//monitor directory
|
||||||
|
monitor = eio_monitor_add(dirname);
|
||||||
|
eio_monitor_add(dirname2);
|
||||||
|
eio_monitor_del(monitor);
|
||||||
|
ecore_event_handler_add(EIO_MONITOR_FILE_CREATED, (Ecore_Event_Handler_Cb)_unexpected_event_cb, filename);
|
||||||
|
|
||||||
|
ecore_timer_add(TEST_OPERATION_DELAY, _create_file, filename);
|
||||||
|
ecore_timer_add(TEST_TIMEOUT_SEC - 1, _test_timeout_expected, NULL);
|
||||||
|
|
||||||
|
ecore_main_loop_begin();
|
||||||
|
|
||||||
|
_delete_directory((void*)dirname2);
|
||||||
|
_common_shutdown(dirname);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(eio_test_monitor_two_files_in_same_directory)
|
||||||
|
{
|
||||||
|
Eina_Tmpstr *dirname = _common_init();
|
||||||
|
Eina_Stringshare *filename;
|
||||||
|
Eina_Stringshare *filename2;
|
||||||
|
|
||||||
|
filename = eina_stringshare_printf("%s/eio_test_monitor_two_files_in_same_directory_1", dirname);
|
||||||
|
filename2 = eina_stringshare_printf("%s/eio_test_monitor_two_files_in_same_directory_2", dirname);
|
||||||
|
_create_file((void*)filename);
|
||||||
|
_create_file((void*)filename2);
|
||||||
|
|
||||||
|
//sleep to avoid catching event generated by above manipulations
|
||||||
|
usleep(500000);
|
||||||
|
|
||||||
|
//monitor file
|
||||||
|
eio_monitor_add(filename);
|
||||||
|
eio_monitor_add(filename2);
|
||||||
|
ecore_event_handler_add(EIO_MONITOR_FILE_MODIFIED, (Ecore_Event_Handler_Cb)_file_modified_cb, filename);
|
||||||
|
|
||||||
|
ecore_timer_add(TEST_OPERATION_DELAY, _modify_file, filename);
|
||||||
|
|
||||||
|
ecore_main_loop_begin();
|
||||||
|
|
||||||
|
//cleanup
|
||||||
|
_common_shutdown(dirname);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
|
||||||
|
START_TEST(eio_test_monitor_two_files_in_same_directory_one_removed)
|
||||||
|
{
|
||||||
|
Eina_Tmpstr *dirname = _common_init();
|
||||||
|
Eina_Stringshare *filename;
|
||||||
|
Eina_Stringshare *filename2;
|
||||||
|
Eio_Monitor *monitor;
|
||||||
|
|
||||||
|
filename = eina_stringshare_printf("%s/eio_test_monitor_two_files_in_same_directory_one_removed_1", dirname);
|
||||||
|
filename2 = eina_stringshare_printf("%s/eio_test_monitor_two_files_in_same_directory_one_removed_2", dirname);
|
||||||
|
_create_file((void*)filename);
|
||||||
|
_create_file((void*)filename2);
|
||||||
|
|
||||||
|
//sleep to avoid catching event generated by above manipulations
|
||||||
|
usleep(500000);
|
||||||
|
|
||||||
|
//monitor file
|
||||||
|
monitor = eio_monitor_add(filename);
|
||||||
|
eio_monitor_add(filename2);
|
||||||
|
eio_monitor_del(monitor);
|
||||||
|
|
||||||
|
ecore_event_handler_add(EIO_MONITOR_FILE_MODIFIED, (Ecore_Event_Handler_Cb)_unexpected_event_cb, filename);
|
||||||
|
|
||||||
|
ecore_timer_add(TEST_OPERATION_DELAY, _modify_file, filename);
|
||||||
|
ecore_timer_add(TEST_TIMEOUT_SEC - 1, _test_timeout_expected, NULL);
|
||||||
|
|
||||||
|
ecore_main_loop_begin();
|
||||||
|
|
||||||
|
//cleanup
|
||||||
|
_common_shutdown(dirname);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
|
||||||
void eio_test_monitor(TCase *tc)
|
void eio_test_monitor(TCase *tc)
|
||||||
{
|
{
|
||||||
tcase_add_test(tc, eio_test_monitor_directory_file_created_notify);
|
tcase_add_test(tc, eio_test_monitor_directory_file_created_notify);
|
||||||
tcase_add_test(tc, eio_test_monitor_directory_file_deleted_notify);
|
tcase_add_test(tc, eio_test_monitor_directory_file_deleted_notify);
|
||||||
tcase_add_test(tc, eio_test_monitor_directory_file_modified_notify);
|
tcase_add_test(tc, eio_test_monitor_directory_file_modified_notify);
|
||||||
#ifndef _WIN32
|
#if !defined(_WIN32) && !defined(__MACH__)
|
||||||
tcase_add_test(tc, eio_test_monitor_directory_file_closed_notify);
|
tcase_add_test(tc, eio_test_monitor_directory_file_closed_notify);
|
||||||
#endif
|
#endif
|
||||||
tcase_add_test(tc, eio_test_monitor_directory_directory_created_notify);
|
tcase_add_test(tc, eio_test_monitor_directory_directory_created_notify);
|
||||||
tcase_add_test(tc, eio_test_monitor_directory_directory_deleted_notify);
|
tcase_add_test(tc, eio_test_monitor_directory_directory_deleted_notify);
|
||||||
tcase_add_test(tc, eio_test_monitor_directory_directory_modified_notify);
|
tcase_add_test(tc, eio_test_monitor_directory_directory_modified_notify);
|
||||||
|
#ifndef __MACH__
|
||||||
tcase_add_test(tc, eio_test_monitor_directory_directory_self_deleted_notify);
|
tcase_add_test(tc, eio_test_monitor_directory_directory_self_deleted_notify);
|
||||||
|
#endif
|
||||||
|
|
||||||
tcase_add_test(tc, eio_test_monitor_file_file_modified_notify);
|
tcase_add_test(tc, eio_test_monitor_file_file_modified_notify);
|
||||||
tcase_add_test(tc, eio_test_monitor_file_file_attrib_modified_notify);
|
tcase_add_test(tc, eio_test_monitor_file_file_attrib_modified_notify);
|
||||||
#ifndef _WIN32
|
#if !defined(_WIN32) && !defined(__MACH__)
|
||||||
tcase_add_test(tc, eio_test_monitor_file_file_closed_notify);
|
tcase_add_test(tc, eio_test_monitor_file_file_closed_notify);
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef __MACH__
|
||||||
tcase_add_test(tc, eio_test_monitor_file_file_self_deleted_notify);
|
tcase_add_test(tc, eio_test_monitor_file_file_self_deleted_notify);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
tcase_add_test(tc, eio_test_monitor_two_monitors_one_event);
|
||||||
|
tcase_add_test(tc, eio_test_monitor_two_monitors_one_removed_one_event);
|
||||||
|
tcase_add_test(tc, eio_test_monitor_two_monitors_one_removed_no_event);
|
||||||
|
tcase_add_test(tc, eio_test_monitor_two_files_in_same_directory);
|
||||||
|
tcase_add_test(tc, eio_test_monitor_two_files_in_same_directory_one_removed);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue