cedric pushed a commit to branch master.

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

commit d00deaaef332967d86a2dee829ffb38a28163a42
Author: Cedric BAIL <ced...@osg.samsung.com>
Date:   Tue Sep 22 00:13:34 2015 +0200

    eio: add kevent backend.
    
    Summary: Implement basic kqueue/kevent backend for eio. When it comes to 
tracking directory changes, this backend falls back to the polling one.
    
    Test Plan: Ran Enlightenment for several days and some other EFL apps 
without any issue.
    
    Reviewers: cedric
    
    Reviewed By: cedric
    
    Subscribers: cedric
    
    Projects: #e_on_freebsd, #efl
    
    Differential Revision: https://phab.enlightenment.org/D2983
    
    Signed-off-by: Cedric BAIL <ced...@osg.samsung.com>
---
 configure.ac                     |   7 ++
 src/Makefile_Eio.am              |   4 +
 src/lib/eio/eio_monitor_kevent.c | 207 +++++++++++++++++++++++++++++++++++++++
 src/lib/eio/eio_monitor_poll.c   |   3 +-
 4 files changed, 220 insertions(+), 1 deletion(-)

diff --git a/configure.ac b/configure.ac
index ab6a061..3ca1316 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4086,6 +4086,13 @@ AC_DEFINE_IF([HAVE_NOTIFY_COCOA],
    [File monitoring with fsevent notification])
 AM_CONDITIONAL([HAVE_NOTIFY_COCOA], [test "x${have_darwin}" = "xyes"])
 
+AC_CHECK_FUNC([kevent])
+have_notify_kevent="${ac_cv_func_kevent}"
+AC_DEFINE_IF([HAVE_NOTIFY_KEVENT],
+   [test "x${have_notify_kevent}" = "xyes"], [1],
+   [File monitoring with kqueue/kevent mechanism])
+AM_CONDITIONAL([HAVE_NOTIFY_KEVENT], [test "x${have_notify_kevent}" = "xyes"])
+
 
 EFL_LIB_END([Eio])
 dnl TODO: remove these ifdefs from code!
diff --git a/src/Makefile_Eio.am b/src/Makefile_Eio.am
index a41af55..62882da 100644
--- a/src/Makefile_Eio.am
+++ b/src/Makefile_Eio.am
@@ -43,6 +43,10 @@ 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
+else
+if HAVE_NOTIFY_KEVENT
+lib_eio_libeio_la_SOURCES += lib/eio/eio_monitor_kevent.c
+endif
 endif
 endif
 endif
diff --git a/src/lib/eio/eio_monitor_kevent.c b/src/lib/eio/eio_monitor_kevent.c
new file mode 100644
index 0000000..753726b
--- /dev/null
+++ b/src/lib/eio/eio_monitor_kevent.c
@@ -0,0 +1,207 @@
+/* EIO - EFL data type library
+ * Copyright (C) 2011 Enlightenment Developers:
+ *           Cedric Bail <cedric.b...@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"
+
+#include <sys/types.h>
+#include <sys/event.h>
+#include <sys/stat.h>
+
+/*============================================================================*
+ *                                  Local                                     *
+ 
*============================================================================*/
+
+/**
+ * @cond LOCAL
+ */
+
+#define KEVENT_NUM_EVENTS 5
+
+struct _Eio_Monitor_Backend
+{
+   Eio_Monitor *parent;
+
+   int fd;
+};
+
+static Ecore_Fd_Handler *_kqueue_fd = NULL;
+static Eina_Hash *_kevent_monitors = NULL;
+
+static void
+_eio_kevent_del(void *data)
+{
+   Eio_Monitor_Backend *emb = data;
+
+   if (emb->fd)
+      close(emb->fd);
+
+   free(emb);
+}
+
+static Eina_Bool
+_eio_kevent_handler(void *data EINA_UNUSED, Ecore_Fd_Handler *fdh)
+{
+   Eio_Monitor_Backend *backend;
+   struct kevent evs[KEVENT_NUM_EVENTS];
+   int event_code = 0;
+
+   int res = kevent(ecore_main_fd_handler_fd_get(fdh), 0, 0, evs, 
KEVENT_NUM_EVENTS, 0);
+
+   for(int i=0; i<res; ++i)
+     {
+        backend = eina_hash_find(_kevent_monitors, &evs[i].ident);
+        if(evs[i].fflags & NOTE_DELETE)
+          {
+             event_code = EIO_MONITOR_SELF_DELETED;
+             _eio_monitor_send(backend->parent, backend->parent->path, 
event_code);
+          }
+        if(evs[i].fflags & NOTE_WRITE || evs[i].fflags & NOTE_ATTRIB)
+          {
+             event_code = EIO_MONITOR_FILE_MODIFIED;
+             _eio_monitor_send(backend->parent, backend->parent->path, 
event_code);
+          }
+     }
+   
+   return ECORE_CALLBACK_RENEW;
+}
+
+/**
+ * @endcond
+ */
+
+
+/*============================================================================*
+ *                                 Global                                     *
+ 
*============================================================================*/
+
+/**
+ * @cond LOCAL
+ */
+
+/**
+ * @endcond
+ */
+
+void eio_monitor_backend_init(void)
+{
+   int fd;
+
+   if (_kqueue_fd > 0) return; // already initialized
+
+   fd = kqueue();
+   if (fd < 0) return;
+
+   _kqueue_fd = ecore_main_fd_handler_add(fd, ECORE_FD_READ, 
_eio_kevent_handler, NULL, NULL, NULL);
+   if (!_kqueue_fd)
+     {
+        close(fd);
+        return;
+     }
+
+   _kevent_monitors = eina_hash_int32_new(_eio_kevent_del);
+}
+
+void eio_monitor_backend_shutdown(void)
+{
+   int fd;
+
+   if (!_kqueue_fd) return;
+
+   eina_hash_free(_kevent_monitors);
+   
+   fd = ecore_main_fd_handler_fd_get(_kqueue_fd);
+   ecore_main_fd_handler_del(_kqueue_fd);
+   _kqueue_fd = NULL;
+   
+   if (fd < 0)
+     return;
+
+   close(fd);
+}
+
+void eio_monitor_backend_add(Eio_Monitor *monitor)
+{
+   struct kevent e;
+   struct stat st;
+   Eio_Monitor_Backend* backend;
+   int fd, res = 0;
+
+   if (!_kqueue_fd)
+     {
+        eio_monitor_fallback_add(monitor);
+        return;
+     }
+
+   backend = calloc(1, sizeof (Eio_Monitor_Backend));
+   if (!backend) return;
+   
+   res = stat(monitor->path, &st);
+   if (res) goto error;
+
+   if (S_ISDIR(st.st_mode)) // let poller handle directories
+     {
+        eio_monitor_fallback_add(monitor);
+        goto error;
+     }
+
+   fd = open(monitor->path, O_RDONLY);
+   if (fd < 0) goto error;
+
+   backend->fd = fd;
+   backend->parent = monitor;
+   monitor->backend = backend;
+
+   eina_hash_direct_add(_kevent_monitors, &backend->fd, backend);
+
+   EV_SET(&e, fd, EVFILT_VNODE, EV_ADD | EV_CLEAR,
+          NOTE_DELETE | NOTE_WRITE | NOTE_ATTRIB, 0, NULL);
+   res = kevent(ecore_main_fd_handler_fd_get(_kqueue_fd), &e, 1, 0, 0, 0);
+   if (res)
+     {
+        eina_hash_del(_kevent_monitors, &backend->fd, backend);
+        eio_monitor_fallback_add(monitor);
+     }
+
+   return;
+   
+error:
+   free(backend);
+}
+
+void eio_monitor_backend_del(Eio_Monitor *monitor)
+{
+   Eio_Monitor_Backend *backend;
+   
+   if (monitor->fallback)
+     {
+        eio_monitor_fallback_del(monitor);
+        return;
+     }
+
+   backend = monitor->backend;
+   monitor->backend = NULL;
+
+   eina_hash_del(_kevent_monitors, &backend->fd, backend);
+}
+
+
+/*============================================================================*
+ *                                   API                                      *
+ 
*============================================================================*/
diff --git a/src/lib/eio/eio_monitor_poll.c b/src/lib/eio/eio_monitor_poll.c
index cb9daf9..6b7b5a8 100644
--- a/src/lib/eio/eio_monitor_poll.c
+++ b/src/lib/eio/eio_monitor_poll.c
@@ -270,7 +270,8 @@ _eio_monitor_fallback_timer_cb(void *data)
  * @cond LOCAL
  */
 
-#if !defined HAVE_SYS_INOTIFY_H && !defined HAVE_NOTIFY_WIN32 && !defined 
HAVE_NOTIFY_COCOA
+#if !defined HAVE_SYS_INOTIFY_H && !defined HAVE_NOTIFY_WIN32 && !defined 
HAVE_NOTIFY_COCOA \
+    && !defined HAVE_NOTIFY_KEVENT
 void eio_monitor_backend_init(void)
 {
 }

-- 


Reply via email to