Commit 9865c655 authored by Jason Madden's avatar Jason Madden

implement libuv stat watcher.

parent 5adec8d6
......@@ -90,10 +90,12 @@ class AbstractWatcherType(type):
LazyOnClass.lazy(cls_dict, _watcher_is_active)
watcher_struct_pattern = (cls_dict.get('_watcher_struct_pattern')
or _mro_get('_watcher_struct_pattern', bases, False)
or 'struct %s')
watcher_struct_name = watcher_struct_pattern % (watcher_type,)
watcher_struct_name = cls_dict.get('_watcher_struct_name')
if not watcher_struct_name:
watcher_struct_pattern = (cls_dict.get('_watcher_struct_pattern')
or _mro_get('_watcher_struct_pattern', bases, False)
or 'struct %s')
watcher_struct_name = watcher_struct_pattern % (watcher_type,)
def _watcher_struct_pointer_type(self):
return self._FFI.typeof(watcher_struct_name + ' *')
......@@ -148,12 +150,7 @@ class watcher(object):
self._handle = type(self).new_handle(self)
self._watcher = type(self).new(self._watcher_struct_pointer_type)
# XXX: Must GC the _watche in libuv: uv_close()
try:
self._watcher.data = self._handle
except AttributeError:
import pdb; pdb.set_trace()
raise
self._watcher.data = self._handle
def _watcher_ffi_set_priority(self, priority):
pass
......@@ -216,9 +213,13 @@ class watcher(object):
result += " args=%r" % (self.args, )
if self.callback is None and self.args is None:
result += " stopped"
result += " handle=%s" % (self._watcher.data)
result += " handle=%s" % (self._watcher_handle)
return result + ">"
@property
def _watcher_handle(self):
return self._watcher.data
def _format(self):
return ''
......
......@@ -156,7 +156,7 @@ typedef struct {
uv_timespec_t st_birthtim;
} uv_stat_t;
typedef void (*uv_fs_poll_cb)(uv_fs_poll_t* handle, int status, const uv_stat_t* prev, const uv_stat_t* curr);
typedef void (*uv_fs_poll_cb)(void* handle, int status, const uv_stat_t* prev, const uv_stat_t* curr);
// loop functions
uv_loop_t *uv_default_loop();
......@@ -267,9 +267,9 @@ int uv_fs_event_getpath(uv_fs_event_t*, char* buffer, size_t* size);
// handles can’t.
//
// This is a closer match to libev.
int uv_fs_poll_init(uv_loop_t*, uv_fs_poll_t*);
int uv_fs_poll_start(uv_fs_poll_t*, uv_fs_poll_cb, const char* path, unsigned int);
int uv_fs_poll_stop(uv_fs_poll_t*);
int uv_fs_poll_init(void*, void*);
int uv_fs_poll_start(void*, uv_fs_poll_cb, const char* path, unsigned int);
int uv_fs_poll_stop(void*);
......
......@@ -69,9 +69,13 @@ static void _gevent_fs_poll_callback3(void* handlep, int status, const uv_stat_t
// if given, copy them into our structure, where they can be reached
// from python, just like libev's watcher does, before calling
// the callback.
if(status < 0) {
return;
}
// The callback is invoked with status < 0 if path does not exist
// or is inaccessible. The watcher is not stopped but your
// callback is not called again until something changes (e.g. when
// the file is created or the error reason changes).
// In that case the fields will be 0 in curr/prev.
gevent_fs_poll_t* handle = (gevent_fs_poll_t*)handlep;
assert(status == 0);
......
......@@ -153,3 +153,42 @@ class timer(_base.TimerMixin, watcher):
self.start(callback, *args, **kw)
finally:
del self._again
class stat(_base.StatMixin, watcher):
_watcher_type = 'fs_poll'
_watcher_struct_name = 'gevent_fs_poll_t'
_watcher_callback_name = '_gevent_fs_poll_callback3'
def _watcher_create(self, ref):
self._handle = type(self).new_handle(self)
self._watcher = type(self).new(self._watcher_struct_pointer_type)
self._watcher.handle.data = self._handle
def _watcher_ffi_init(self, args):
self._watcher_init(self.loop._ptr, self._watcher)
MIN_STAT_INTERVAL = 0.1074891 # match libev; 0.0 is default
def _watcher_ffi_start(self):
# libev changes this when the watcher is started
if self._interval < self.MIN_STAT_INTERVAL:
self._interval = self.MIN_STAT_INTERVAL
self._watcher_start(self._watcher, self._watcher_callback,
self._cpath,
int(self._interval * 1000))
@property
def _watcher_handle(self):
return self._watcher.handle.data
@property
def attr(self):
if not self._watcher.curr.st_nlink:
return
return self._watcher.curr
@property
def prev(self):
if not self._watcher.prev.st_nlink:
return
return self._watcher.prev
......@@ -70,7 +70,7 @@ try:
check_attr('attr', False)
check_attr('prev', False)
# The watcher interval changed after it started; -1 is illegal
assert watcher.interval != -1
assert watcher.interval != -1, watcher.interval
greenlet.join()
gevent.spawn_later(DELAY, os.unlink, filename)
......
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