Commit 9935d9f1 authored by Denis Bilenko's avatar Denis Bilenko

add 'stat' watchers

parent 50cef915
......@@ -2,7 +2,7 @@
static void gevent_callback_##WATCHER_LC(struct ev_loop *, void *, int);
#define DEFINE_CALLBACKS \
#define DEFINE_CALLBACKS0 \
DEFINE_CALLBACK(io, IO); \
DEFINE_CALLBACK(timer, Timer); \
DEFINE_CALLBACK(signal, Signal); \
......@@ -10,7 +10,20 @@
DEFINE_CALLBACK(prepare, Prepare); \
DEFINE_CALLBACK(fork, Fork); \
DEFINE_CALLBACK(async, Async); \
DEFINE_CALLBACK(child, Child);
DEFINE_CALLBACK(stat, Stat);
#if EV_CHILD_ENABLE
#define DEFINE_CALLBACKS \
DEFINE_CALLBACKS0 \
DEFINE_CALLBACK(child, Child)
#else
#define DEFINE_CALLBACKS DEFINE_CALLBACKS0
#endif
DEFINE_CALLBACKS
......
......@@ -27,6 +27,7 @@ cdef extern from "callbacks.h":
void gevent_callback_fork(libev.ev_loop, void*, int)
void gevent_callback_async(libev.ev_loop, void*, int)
void gevent_callback_child(libev.ev_loop, void*, int)
void gevent_callback_stat(libev.ev_loop, void*, int)
void gevent_signal_check(libev.ev_loop, void*, int)
void gevent_periodic_signal_check(libev.ev_loop, void*, int)
......@@ -36,6 +37,9 @@ cdef extern from *:
int FIONREAD
int errno
cdef extern from "stathelper.c":
object _pystat_fromstructstat(void*)
UNDEF = libev.EV_UNDEF
NONE = libev.EV_NONE
......@@ -434,6 +438,9 @@ cdef public class loop [object PyGeventLoopObject, type PyGeventLoop_Type]:
#endif
def stat(self, bytes path, float interval=0.0, ref=True):
return stat(self, path, interval, ref)
def callback(self):
return callback(self)
......@@ -881,6 +888,40 @@ cdef public class child(watcher) [object PyGeventChildObject, type PyGeventChild
#endif
cdef public class stat(watcher) [object PyGeventStatObject, type PyGeventStat_Type]:
WATCHER(stat)
cdef readonly bytes path
def __init__(self, loop loop, bytes path, float interval=0.0, ref=True):
self.path = path
libev.ev_stat_init(&self._watcher, <void *>gevent_callback_stat, <char*>self.path, interval)
self.loop = loop
if ref:
self._flags = 0
else:
self._flags = 4
property attr:
def __get__(self):
if not self._watcher.attr.st_nlink:
return
return _pystat_fromstructstat(&self._watcher.attr)
property prev:
def __get__(self):
if not self._watcher.prev.st_nlink:
return
return _pystat_fromstructstat(&self._watcher.prev)
property interval:
def __get__(self):
return self._watcher.interval
cdef public class callback(watcher) [object PyGeventCallbackObject, type PyGeventCallback_Type]:
"""Pseudo-watcher used to execute a callback in the loop as soon as possible."""
......
......@@ -87,6 +87,14 @@ cdef extern from "libev.h":
int rpid
int rstatus
struct stat:
int st_nlink
struct ev_stat:
stat attr
stat prev
double interval
int ev_version_major()
int ev_version_minor()
......@@ -138,6 +146,10 @@ cdef extern from "libev.h":
void ev_child_start(ev_loop*, ev_child*)
void ev_child_stop(ev_loop*, ev_child*)
void ev_stat_init(ev_stat*, void* callback, char*, double)
void ev_stat_start(ev_loop*, ev_stat*)
void ev_stat_stop(ev_loop*, ev_stat*)
ev_loop* ev_default_loop(unsigned int flags)
ev_loop* ev_loop_new(unsigned int flags)
void ev_loop_destroy(ev_loop*)
......
/* copied from Python-2.7.2/Modules/posixmodule.c */
#include "structseq.h"
#define STRUCT_STAT struct stat
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
#define ST_BLKSIZE_IDX 13
#else
#define ST_BLKSIZE_IDX 12
#endif
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
#define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)
#else
#define ST_BLOCKS_IDX ST_BLKSIZE_IDX
#endif
#ifdef HAVE_STRUCT_STAT_ST_RDEV
#define ST_RDEV_IDX (ST_BLOCKS_IDX+1)
#else
#define ST_RDEV_IDX ST_BLOCKS_IDX
#endif
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
#define ST_FLAGS_IDX (ST_RDEV_IDX+1)
#else
#define ST_FLAGS_IDX ST_RDEV_IDX
#endif
#ifdef HAVE_STRUCT_STAT_ST_GEN
#define ST_GEN_IDX (ST_FLAGS_IDX+1)
#else
#define ST_GEN_IDX ST_FLAGS_IDX
#endif
#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
#define ST_BIRTHTIME_IDX (ST_GEN_IDX+1)
#else
#define ST_BIRTHTIME_IDX ST_GEN_IDX
#endif
static PyObject* posixmodule = NULL;
static PyTypeObject* pStatResultType = NULL;
static PyObject* import_posixmodule(void)
{
if (!posixmodule) {
posixmodule = PyImport_ImportModule("posix");
}
return posixmodule;
}
static PyObject* import_StatResultType(void)
{
PyObject* p = NULL;
if (!pStatResultType) {
PyObject* module;
module = import_posixmodule();
if (module) {
p = PyObject_GetAttrString(module, "stat_result");
}
}
return p;
}
static void
fill_time(PyObject *v, int index, time_t sec, unsigned long nsec)
{
PyObject *fval,*ival;
#if SIZEOF_TIME_T > SIZEOF_LONG
ival = PyLong_FromLongLong((PY_LONG_LONG)sec);
#else
ival = PyInt_FromLong((long)sec);
#endif
if (!ival)
return;
fval = PyFloat_FromDouble(sec + 1e-9*nsec);
PyStructSequence_SET_ITEM(v, index, ival);
PyStructSequence_SET_ITEM(v, index+3, fval);
}
/* pack a system stat C structure into the Python stat tuple
(used by posix_stat() and posix_fstat()) */
static PyObject*
_pystat_fromstructstat(STRUCT_STAT *st)
{
unsigned long ansec, mnsec, cnsec;
PyTypeObject* StatResultType = (PyTypeObject*)import_StatResultType();
PyObject *v = PyStructSequence_New(StatResultType);
if (v == NULL)
return NULL;
PyStructSequence_SET_ITEM(v, 0, PyInt_FromLong((long)st->st_mode));
#ifdef HAVE_LARGEFILE_SUPPORT
PyStructSequence_SET_ITEM(v, 1,
PyLong_FromLongLong((PY_LONG_LONG)st->st_ino));
#else
PyStructSequence_SET_ITEM(v, 1, PyInt_FromLong((long)st->st_ino));
#endif
#if defined(HAVE_LONG_LONG) && !defined(MS_WINDOWS)
PyStructSequence_SET_ITEM(v, 2,
PyLong_FromLongLong((PY_LONG_LONG)st->st_dev));
#else
PyStructSequence_SET_ITEM(v, 2, PyInt_FromLong((long)st->st_dev));
#endif
PyStructSequence_SET_ITEM(v, 3, PyInt_FromLong((long)st->st_nlink));
PyStructSequence_SET_ITEM(v, 4, PyInt_FromLong((long)st->st_uid));
PyStructSequence_SET_ITEM(v, 5, PyInt_FromLong((long)st->st_gid));
#ifdef HAVE_LARGEFILE_SUPPORT
PyStructSequence_SET_ITEM(v, 6,
PyLong_FromLongLong((PY_LONG_LONG)st->st_size));
#else
PyStructSequence_SET_ITEM(v, 6, PyInt_FromLong(st->st_size));
#endif
#if defined(HAVE_STAT_TV_NSEC)
ansec = st->st_atim.tv_nsec;
mnsec = st->st_mtim.tv_nsec;
cnsec = st->st_ctim.tv_nsec;
#elif defined(HAVE_STAT_TV_NSEC2)
ansec = st->st_atimespec.tv_nsec;
mnsec = st->st_mtimespec.tv_nsec;
cnsec = st->st_ctimespec.tv_nsec;
#elif defined(HAVE_STAT_NSEC)
ansec = st->st_atime_nsec;
mnsec = st->st_mtime_nsec;
cnsec = st->st_ctime_nsec;
#else
ansec = mnsec = cnsec = 0;
#endif
fill_time(v, 7, st->st_atime, ansec);
fill_time(v, 8, st->st_mtime, mnsec);
fill_time(v, 9, st->st_ctime, cnsec);
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX,
PyInt_FromLong((long)st->st_blksize));
#endif
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
PyStructSequence_SET_ITEM(v, ST_BLOCKS_IDX,
PyInt_FromLong((long)st->st_blocks));
#endif
#ifdef HAVE_STRUCT_STAT_ST_RDEV
PyStructSequence_SET_ITEM(v, ST_RDEV_IDX,
PyInt_FromLong((long)st->st_rdev));
#endif
#ifdef HAVE_STRUCT_STAT_ST_GEN
PyStructSequence_SET_ITEM(v, ST_GEN_IDX,
PyInt_FromLong((long)st->st_gen));
#endif
#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
{
PyObject *val;
unsigned long bsec,bnsec;
bsec = (long)st->st_birthtime;
#ifdef HAVE_STAT_TV_NSEC2
bnsec = st->st_birthtimespec.tv_nsec;
#else
bnsec = 0;
#endif
val = PyFloat_FromDouble(bsec + 1e-9*bnsec);
PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX,
val);
}
#endif
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX,
PyInt_FromLong((long)st->st_flags));
#endif
if (PyErr_Occurred()) {
Py_DECREF(v);
return NULL;
}
return v;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment