Author: tack
Date: Sun Mar 26 23:53:53 2006
New Revision: 1357

Added:
   trunk/beacon/src/inotify/
   trunk/beacon/src/inotify/__init__.py
   trunk/beacon/src/inotify/fallback-inotify-syscalls.h
   trunk/beacon/src/inotify/fallback-inotify.h
   trunk/beacon/src/inotify/inotify.c
   trunk/beacon/test/
   trunk/beacon/test/inotify.py
Removed:
   trunk/beacon/src/inotify.py
Modified:
   trunk/beacon/setup.py

Log:
Add INotify API.


Modified: trunk/beacon/setup.py
==============================================================================
--- trunk/beacon/setup.py       (original)
+++ trunk/beacon/setup.py       Sun Mar 26 23:53:53 2006
@@ -40,28 +40,47 @@
     print 'kaa.base not installed'
     sys.exit(1)
 
-ext = Extension("kaa.beacon.thumbnail.libthumb",
-                ["src/thumbnail/thumbnail.c", "src/thumbnail/png.c" ],
-                config='src/thumbnail/config.h')
+thumb_ext = Extension("kaa.beacon.thumbnail.libthumb",
+                      ["src/thumbnail/thumbnail.c", "src/thumbnail/png.c" ],
+                      config='src/thumbnail/config.h')
 
-if not ext.check_library('imlib2', '1.1.1'):
+if not thumb_ext.check_library('imlib2', '1.1.1'):
     print 'Imlib2 >= 1.1.1 not found'
     print 'Download from http://enlightenment.freedesktop.org/'
     sys.exit(1)
 
-if not ext.check_library('libpng', '1.2.0'):
+if not thumb_ext.check_library('libpng', '1.2.0'):
     print 'libpng >= 1.2.0 not found'
     sys.exit(1)
 
-if ext.check_library('epeg', '0.9'):
+if thumb_ext.check_library('epeg', '0.9'):
     print 'epeg extention enabled'
-    ext.config('#define USE_EPEG')
+    thumb_ext.config('#define USE_EPEG')
 else:
     print 'epeg extention disabled'
 
+
+inotify_ext = Extension("kaa.beacon.inotify._inotify",
+                        ["src/inotify/inotify.c"],
+                        config='src/inotify/config.h')
+
+ext_modules = [ thumb_ext, inotify_ext ]
+
+if not inotify_ext.check_cc(["<sys/inotify.h>"], "inotify_init();"):
+    if not inotify_ext.check_cc(["<sys/syscall.h>"], "syscall(0);"):
+        print "inotify not enabled: doesn't look like a Linux system."
+        ext_modules.remove(inotify_ext)
+    else:
+        print "inotify not supported in glibc; using fallback."
+        inotify_ext.config("#define USE_FALLBACK")
+
+else:
+    print "inotify supported by glibc; good."
+
+
 setup (module      = 'beacon',
        version     = '0.1',
        description = "Media-oriented virtual filesystem",
        scripts     = [ 'bin/kaa-thumb', 'bin/beacon' ],
-       ext_modules = [ ext ]
+       ext_modules = ext_modules
       )

Added: trunk/beacon/src/inotify/__init__.py
==============================================================================
--- (empty file)
+++ trunk/beacon/src/inotify/__init__.py        Sun Mar 26 23:53:53 2006
@@ -0,0 +1,115 @@
+try:
+    from kaa.beacon.inotify import _inotify
+except ImportError:
+    _inotify = None
+
+import kaa
+import os
+import struct
+
+
+class INotify:
+
+    def __init__(self):
+        if not _inotify:
+            self._fd = -1
+            raise SystemError, "INotify support not compiled."
+
+        self.signals = {
+            # Master signal: this signal gets emitted on all events.
+            "event": kaa.notifier.Signal()
+        }
+
+        self._watches = {}
+        self._read_buffer = ""
+
+        self._fd = _inotify.init()
+        if self._fd < 0:
+            raise SystemError, "INotify support not detected on this system."
+
+        self._mon = kaa.notifier.WeakSocketDispatcher(self._handle_data)
+        self._mon.register(self._fd)
+
+
+    def __del__(self):
+        if self._fd >= 0:
+            os.close(self._fd)
+            self._mon.unregister()
+
+
+    def watch(self, path, mask = None):
+        """
+        Adds a watch to the given path.  The default mask is anything that
+        causes a change (new file, deleted file, modified file, or attribute
+        change on the file).  This function returns a Signal that the caller
+        can then connect to.  Any time there is a notification, the signal
+        will get emitted.  Callbacks connected to the signal must accept 2
+        arguments: notify mask and filename.
+        """
+        if mask == None:
+            mask = INotify.WATCH_MASK
+
+        wd = _inotify.add_watch(self._fd, path, mask)
+        if wd < 0:
+            raise IOError, "Failed to add watch on '%s'" % path
+
+        signal = kaa.notifier.Signal()
+        self._watches[wd] = [signal, os.path.realpath(path)]
+        return signal
+
+
+    def ignore(self, path):
+        """
+        Removes a watch on the given path.
+        """
+        path = os.path.realpath(path)
+        for wd in self._watches:
+            if path == self._watches[wd][1]:
+                _inotify.rm_watch(self._fd, wd)
+                del self._watches[wd]
+                return True
+
+        return False
+
+    def _handle_data(self):
+        data = os.read(self._fd, 32768)
+        self._read_buffer += data
+
+        while True:
+            if len(self._read_buffer) < 16:
+                break
+
+            wd, mask, cookie, size = struct.unpack("LLLL", 
self._read_buffer[0:16])
+            if size:
+                name = self._read_buffer[16:16+size]
+            else:
+                name = None
+
+            self._read_buffer = self._read_buffer[16+size:]
+            if wd not in self._watches:
+                continue
+
+            path = self._watches[wd][1]
+            if name:
+                path = os.path.join(path, name)
+
+            self._watches[wd][0].emit(mask, path)
+            self.signals["event"].emit(mask, path)
+
+            if mask & INotify.DELETE_SELF:
+                # Self got deleted, so remove the watch data.
+                del self._watches[wd]
+
+
+if _inotify:
+    # Copy constants from _inotify to INotify
+    for attr in dir(_inotify):
+        if attr[0].isupper():
+            setattr(INotify, attr, getattr(_inotify, attr))
+
+    INotify.WATCH_MASK = INotify.MODIFY | INotify.ATTRIB | INotify.DELETE | \
+                         INotify.CREATE | INotify.DELETE_SELF | 
INotify.UNMOUNT | \
+                         INotify.MOVE
+
+    INotify.CHANGE     = INotify.MODIFY | INotify.ATTRIB
+    

Added: trunk/beacon/src/inotify/fallback-inotify-syscalls.h
==============================================================================
--- (empty file)
+++ trunk/beacon/src/inotify/fallback-inotify-syscalls.h        Sun Mar 26 
23:53:53 2006
@@ -0,0 +1,61 @@
+#ifndef _LINUX_INOTIFY_SYSCALLS_H
+#define _LINUX_INOTIFY_SYSCALLS_H
+
+#include <sys/syscall.h>
+
+#if defined(__i386__)
+# define __NR_inotify_init     291
+# define __NR_inotify_add_watch        292
+# define __NR_inotify_rm_watch 293
+#elif defined(__x86_64__)
+# define __NR_inotify_init     253
+# define __NR_inotify_add_watch        254
+# define __NR_inotify_rm_watch 255
+#elif defined(__powerpc__) || defined(__powerpc64__)
+# define __NR_inotify_init     275
+# define __NR_inotify_add_watch        276
+# define __NR_inotify_rm_watch 277
+#elif defined (__ia64__)
+# define __NR_inotify_init     1277
+# define __NR_inotify_add_watch        1278
+# define __NR_inotify_rm_watch 1279
+#elif defined (__s390__)
+# define __NR_inotify_init     284
+# define __NR_inotify_add_watch        285
+# define __NR_inotify_rm_watch 286
+#elif defined (__alpha__)
+# define __NR_inotify_init     444
+# define __NR_inotify_add_watch        445
+# define __NR_inotify_rm_watch 446
+#elif defined (__sparc__) || defined (__sparc64__)
+# define __NR_inotify_init     151
+# define __NR_inotify_add_watch        152
+# define __NR_inotify_rm_watch 156
+#elif defined (__arm__)
+# define __NR_inotify_init     316
+# define __NR_inotify_add_watch        317
+# define __NR_inotify_rm_watch 318
+#elif defined (__sh__)
+# define __NR_inotify_init     290
+# define __NR_inotify_add_watch        291
+# define __NR_inotify_rm_watch 292
+#else
+# error "Unsupported architecture!"
+#endif
+
+static inline int inotify_init (void)
+{
+       return syscall (__NR_inotify_init);
+}
+
+static inline int inotify_add_watch (int fd, const char *name, __u32 mask)
+{
+       return syscall (__NR_inotify_add_watch, fd, name, mask);
+}
+
+static inline int inotify_rm_watch (int fd, __u32 wd)
+{
+       return syscall (__NR_inotify_rm_watch, fd, wd);
+}
+
+#endif /* _LINUX_INOTIFY_SYSCALLS_H */

Added: trunk/beacon/src/inotify/fallback-inotify.h
==============================================================================
--- (empty file)
+++ trunk/beacon/src/inotify/fallback-inotify.h Sun Mar 26 23:53:53 2006
@@ -0,0 +1,109 @@
+/*
+ * Inode based directory notification for Linux
+ *
+ * Copyright (C) 2005 John McCutchan
+ */
+
+#ifndef _LINUX_INOTIFY_H
+#define _LINUX_INOTIFY_H
+
+#include <linux/types.h>
+
+/*
+ * struct inotify_event - structure read from the inotify device for each event
+ *
+ * When you are watching a directory, you will receive the filename for events
+ * such as IN_CREATE, IN_DELETE, IN_OPEN, IN_CLOSE, ..., relative to the wd.
+ */
+struct inotify_event {
+       __s32           wd;             /* watch descriptor */
+       __u32           mask;           /* watch mask */
+       __u32           cookie;         /* cookie to synchronize two events */
+       __u32           len;            /* length (including nulls) of name */
+       char            name[0];        /* stub for possible name */
+};
+
+/* the following are legal, implemented events that user-space can watch for */
+#define IN_ACCESS              0x00000001      /* File was accessed */
+#define IN_MODIFY              0x00000002      /* File was modified */
+#define IN_ATTRIB              0x00000004      /* Metadata changed */
+#define IN_CLOSE_WRITE         0x00000008      /* Writtable file was closed */
+#define IN_CLOSE_NOWRITE       0x00000010      /* Unwrittable file closed */
+#define IN_OPEN                        0x00000020      /* File was opened */
+#define IN_MOVED_FROM          0x00000040      /* File was moved from X */
+#define IN_MOVED_TO            0x00000080      /* File was moved to Y */
+#define IN_CREATE              0x00000100      /* Subfile was created */
+#define IN_DELETE              0x00000200      /* Subfile was deleted */
+#define IN_DELETE_SELF         0x00000400      /* Self was deleted */
+#define IN_MOVE_SELF     0x00000800 /* Self was moved.  */
+
+/* the following are legal events.  they are sent as needed to any watch */
+#define IN_UNMOUNT             0x00002000      /* Backing fs was unmounted */
+#define IN_Q_OVERFLOW          0x00004000      /* Event queued overflowed */
+#define IN_IGNORED             0x00008000      /* File was ignored */
+
+/* helper events */
+#define IN_CLOSE               (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE) /* close */
+#define IN_MOVE                        (IN_MOVED_FROM | IN_MOVED_TO) /* moves 
*/
+
+/* special flags */
+#define IN_ISDIR               0x40000000      /* event occurred against dir */
+#define IN_ONESHOT             0x80000000      /* only send event once */
+
+/*
+ * All of the events - we build the list by hand so that we can add flags in
+ * the future and not break backward compatibility.  Apps will get only the
+ * events that they originally wanted.  Be sure to add new events here!
+ */
+#define IN_ALL_EVENTS  (IN_ACCESS | IN_MODIFY | IN_ATTRIB | IN_CLOSE_WRITE | \
+                        IN_CLOSE_NOWRITE | IN_OPEN | IN_MOVED_FROM | \
+                        IN_MOVED_TO | IN_DELETE | IN_CREATE | IN_DELETE_SELF)
+
+#ifdef __KERNEL__
+
+#include <linux/dcache.h>
+#include <linux/fs.h>
+#include <linux/config.h>
+
+#ifdef CONFIG_INOTIFY
+
+extern void inotify_inode_queue_event(struct inode *, __u32, __u32,
+                                     const char *);
+extern void inotify_dentry_parent_queue_event(struct dentry *, __u32, __u32,
+                                             const char *);
+extern void inotify_unmount_inodes(struct list_head *);
+extern void inotify_inode_is_dead(struct inode *);
+extern u32 inotify_get_cookie(void);
+
+#else
+
+static inline void inotify_inode_queue_event(struct inode *inode,
+                                            __u32 mask, __u32 cookie,
+                                            const char *filename)
+{
+}
+
+static inline void inotify_dentry_parent_queue_event(struct dentry *dentry,
+                                                    __u32 mask, __u32 cookie,
+                                                    const char *filename)
+{
+}
+
+static inline void inotify_unmount_inodes(struct list_head *list)
+{
+}
+
+static inline void inotify_inode_is_dead(struct inode *inode)
+{
+}
+
+static inline u32 inotify_get_cookie(void)
+{
+       return 0;
+}
+
+#endif /* CONFIG_INOTIFY */
+
+#endif /* __KERNEL __ */
+
+#endif /* _LINUX_INOTIFY_H */

Added: trunk/beacon/src/inotify/inotify.c
==============================================================================
--- (empty file)
+++ trunk/beacon/src/inotify/inotify.c  Sun Mar 26 23:53:53 2006
@@ -0,0 +1,104 @@
+/*
+ * ----------------------------------------------------------------------------
+ * Inotify module for Python
+ * ----------------------------------------------------------------------------
+ * $Id: inotify.c 1247 2006-03-04 19:35:51Z tack $
+ *
+ * ----------------------------------------------------------------------------
+ * Copyright (C) 2006 Jason Tackaberry <[EMAIL PROTECTED]>
+ *
+ * First Edition: Jason Tackaberry <[EMAIL PROTECTED]>
+ * Maintainer:    Jason Tackaberry <[EMAIL PROTECTED]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MER-
+ * CHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * ----------------------------------------------------------------------------
+ */
+
+#include <Python.h>
+#include "config.h"
+
+#include <inttypes.h>
+
+#ifdef USE_FALLBACK
+#   include "fallback-inotify.h"
+#   include "fallback-inotify-syscalls.h"
+#else
+#   include <sys/inotify.h>
+#endif
+
+PyObject *init(PyObject *self, PyObject *args)
+{
+    int fd = inotify_init();
+    return Py_BuildValue("l", fd);
+}
+
+PyObject *add_watch(PyObject *self, PyObject *args)
+{
+    int fd;
+    uint32_t mask;
+    char *name;
+
+    if (!PyArg_ParseTuple(args, "isi", &fd, &name, &mask))
+        return NULL;
+
+    return Py_BuildValue("l", inotify_add_watch(fd, name, mask));
+}
+
+PyObject *rm_watch(PyObject *self, PyObject *args)
+{
+    int fd;
+    uint32_t wd;
+
+    if (!PyArg_ParseTuple(args, "ii", &fd, &wd))
+        return NULL;
+
+    return Py_BuildValue("l", inotify_rm_watch(fd, wd));
+}
+
+
+PyMethodDef inotify_methods[] = {
+    { "init", init, METH_VARARGS }, 
+    { "add_watch", add_watch, METH_VARARGS }, 
+    { "rm_watch", rm_watch, METH_VARARGS }, 
+    { NULL }
+};
+
+
+void init_inotify()
+{
+    PyObject *m = Py_InitModule("_inotify", inotify_methods);
+    #define add_const(x) PyModule_AddObject(m, #x, PyLong_FromLong(IN_ ## x));
+    add_const(ACCESS);
+    add_const(MODIFY);
+    add_const(ATTRIB);
+    add_const(CLOSE_WRITE);
+    add_const(CLOSE_NOWRITE);
+    add_const(CLOSE);
+    add_const(OPEN);
+    add_const(MOVED_FROM);
+    add_const(MOVED_TO);
+    add_const(MOVE);
+    add_const(CREATE);
+    add_const(DELETE);
+    add_const(DELETE_SELF);
+    add_const(MOVE_SELF);
+    add_const(UNMOUNT);
+    add_const(Q_OVERFLOW);
+    add_const(IGNORED);
+    add_const(ISDIR);
+    add_const(ONESHOT);
+    add_const(ALL_EVENTS);
+}

Added: trunk/beacon/test/inotify.py
==============================================================================
--- (empty file)
+++ trunk/beacon/test/inotify.py        Sun Mar 26 23:53:53 2006
@@ -0,0 +1,16 @@
+from kaa.beacon.inotify import INotify
+import kaa, os
+
+def cb(mask, name):
+    if mask & INotify.CREATE:
+        print name, "created."
+    elif mask & INotify.CHANGE:
+        print name, "changed."
+    elif mask & INotify.DELETE:
+        print name, "deleted"
+
+i = INotify()
+dir = os.path.expanduser("~")
+i.watch(dir).connect(cb)
+print "Now monitoring", dir
+kaa.main()


-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642
_______________________________________________
Freevo-cvslog mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/freevo-cvslog

Reply via email to