summaryrefslogtreecommitdiff
path: root/deps
diff options
context:
space:
mode:
authorFedor Indutny <fedor.indutny@gmail.com>2012-06-19 00:57:29 +0400
committerFedor Indutny <fedor.indutny@gmail.com>2012-06-19 01:03:11 +0400
commit057b80611f977789f6c1334fdf3680c105af364e (patch)
tree25a0e770c9c1d089c10b87184e5eedca92974669 /deps
parent30ab1f567d6dda2f1e6d48bd96a9034406b3c2b1 (diff)
downloadnode-new-057b80611f977789f6c1334fdf3680c105af364e.tar.gz
uv: upgrade to 61a6e06e
Diffstat (limited to 'deps')
-rw-r--r--deps/uv/config-mingw.mk4
-rw-r--r--deps/uv/config-unix.mk4
-rw-r--r--deps/uv/include/uv-private/uv-unix.h8
-rw-r--r--deps/uv/include/uv-private/uv-win.h2
-rw-r--r--deps/uv/include/uv.h68
-rw-r--r--deps/uv/src/fs-poll.c235
-rw-r--r--deps/uv/src/unix/core.c13
-rw-r--r--deps/uv/src/unix/linux/syscalls.c2
-rw-r--r--deps/uv/src/unix/sunos.c1
-rw-r--r--deps/uv/src/uv-common.h2
-rw-r--r--deps/uv/src/win/handle-inl.h4
-rw-r--r--deps/uv/src/win/handle.c6
-rw-r--r--deps/uv/src/win/internal.h6
-rw-r--r--deps/uv/test/test-fs-poll.c147
-rw-r--r--deps/uv/test/test-hrtime.c2
-rw-r--r--deps/uv/test/test-list.h4
-rw-r--r--deps/uv/test/test-ref.c10
-rw-r--r--deps/uv/uv.gyp2
18 files changed, 497 insertions, 23 deletions
diff --git a/deps/uv/config-mingw.mk b/deps/uv/config-mingw.mk
index 89bf2df391..9e49ec71b2 100644
--- a/deps/uv/config-mingw.mk
+++ b/deps/uv/config-mingw.mk
@@ -37,8 +37,8 @@ RUNNER_LINKFLAGS=$(LINKFLAGS)
RUNNER_LIBS=-lws2_32 -lpsapi -liphlpapi
RUNNER_SRC=test/runner-win.c
-uv.a: $(WIN_OBJS) src/cares.o src/uv-common.o $(CARES_OBJS)
- $(AR) rcs uv.a $(WIN_OBJS) src/cares.o src/uv-common.o $(CARES_OBJS)
+uv.a: $(WIN_OBJS) src/cares.o src/fs-poll.o src/uv-common.o $(CARES_OBJS)
+ $(AR) rcs uv.a $^
src/%.o: src/%.c include/uv.h include/uv-private/uv-win.h
$(CC) $(CFLAGS) -c $< -o $@
diff --git a/deps/uv/config-unix.mk b/deps/uv/config-unix.mk
index c1ba2d0ad1..7220f108ad 100644
--- a/deps/uv/config-unix.mk
+++ b/deps/uv/config-unix.mk
@@ -129,8 +129,8 @@ endif
RUNNER_LIBS=
RUNNER_SRC=test/runner-unix.c
-uv.a: $(OBJS) src/cares.o src/uv-common.o src/unix/ev/ev.o src/unix/uv-eio.o src/unix/eio/eio.o $(CARES_OBJS)
- $(AR) rcs uv.a $(OBJS) src/cares.o src/uv-common.o src/unix/uv-eio.o src/unix/ev/ev.o src/unix/eio/eio.o $(CARES_OBJS)
+uv.a: $(OBJS) src/cares.o src/fs-poll.o src/uv-common.o src/unix/ev/ev.o src/unix/uv-eio.o src/unix/eio/eio.o $(CARES_OBJS)
+ $(AR) rcs uv.a $^
src/%.o: src/%.c include/uv.h include/uv-private/uv-unix.h
$(CC) $(CSTDFLAG) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
diff --git a/deps/uv/include/uv-private/uv-unix.h b/deps/uv/include/uv-private/uv-unix.h
index 62bb0aa45e..da185e29da 100644
--- a/deps/uv/include/uv-private/uv-unix.h
+++ b/deps/uv/include/uv-private/uv-unix.h
@@ -28,13 +28,17 @@
#include "eio.h"
#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
-#include <pwd.h>
+
#include <termios.h>
+#include <pwd.h>
#include <semaphore.h>
#include <pthread.h>
@@ -55,6 +59,8 @@ typedef int uv_file;
typedef int uv_os_sock_t;
+typedef struct stat uv_statbuf_t;
+
#define UV_ONCE_INIT PTHREAD_ONCE_INIT
typedef pthread_once_t uv_once_t;
diff --git a/deps/uv/include/uv-private/uv-win.h b/deps/uv/include/uv-private/uv-win.h
index 10a8ec0c78..43358da8ec 100644
--- a/deps/uv/include/uv-private/uv-win.h
+++ b/deps/uv/include/uv-private/uv-win.h
@@ -165,6 +165,8 @@ typedef struct uv_buf_t {
typedef int uv_file;
+typedef struct _stati64 uv_statbuf_t;
+
typedef SOCKET uv_os_sock_t;
typedef HANDLE uv_thread_t;
diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h
index 8bd387accf..9b0e76b980 100644
--- a/deps/uv/include/uv.h
+++ b/deps/uv/include/uv.h
@@ -140,6 +140,7 @@ typedef enum {
XX(ASYNC, async) \
XX(CHECK, check) \
XX(FS_EVENT, fs_event) \
+ XX(FS_POLL, fs_poll) \
XX(IDLE, idle) \
XX(NAMED_PIPE, pipe) \
XX(POLL, poll) \
@@ -209,6 +210,7 @@ typedef struct uv_udp_send_s uv_udp_send_t;
typedef struct uv_fs_s uv_fs_t;
/* uv_fs_event_t is a subclass of uv_handle_t. */
typedef struct uv_fs_event_s uv_fs_event_t;
+typedef struct uv_fs_poll_s uv_fs_poll_t;
typedef struct uv_work_s uv_work_t;
@@ -312,6 +314,11 @@ typedef void (*uv_walk_cb)(uv_handle_t* handle, void* arg);
typedef void (*uv_fs_event_cb)(uv_fs_event_t* handle, const char* filename,
int events, int status);
+typedef void (*uv_fs_poll_cb)(uv_fs_poll_t* handle,
+ int status,
+ uv_statbuf_t* prev,
+ uv_statbuf_t* curr);
+
typedef enum {
UV_LEAVE_GROUP = 0,
UV_JOIN_GROUP
@@ -1511,6 +1518,46 @@ struct uv_fs_event_s {
/*
+ * uv_fs_stat() based polling file watcher.
+ */
+struct uv_fs_poll_s {
+ UV_HANDLE_FIELDS
+ /* Private, don't touch. */
+ int busy_polling; /* TODO(bnoordhuis) Fold into flags field. */
+ unsigned int interval;
+ uint64_t start_time;
+ char* path;
+ uv_fs_poll_cb poll_cb;
+ uv_timer_t timer_handle;
+ uv_fs_t* fs_req;
+ uv_statbuf_t statbuf;
+};
+
+UV_EXTERN int uv_fs_poll_init(uv_loop_t* loop, uv_fs_poll_t* handle);
+
+/*
+ * Check the file at `path` for changes every `interval` milliseconds.
+ *
+ * Your callback i invoked with `status == -1` 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).
+ *
+ * When `status == 0`, your callback receives pointers to the old and new
+ * `uv_statbuf_t` structs. They are valid for the duration of the callback
+ * only!
+ *
+ * For maximum portability, use multi-second intervals. Sub-second intervals
+ * will not detect all changes on many file systems.
+ */
+UV_EXTERN int uv_fs_poll_start(uv_fs_poll_t* handle,
+ uv_fs_poll_cb poll_cb,
+ const char* path,
+ unsigned int interval);
+
+UV_EXTERN int uv_fs_poll_stop(uv_fs_poll_t* handle);
+
+/*
* Gets load avg
* See: http://en.wikipedia.org/wiki/Load_(computing)
* (Returns [0,0,0] for windows and cygwin)
@@ -1683,22 +1730,23 @@ union uv_any_req {
struct uv_counters_s {
+ uint64_t async_init;
+ uint64_t check_init;
uint64_t eio_init;
- uint64_t req_init;
+ uint64_t fs_event_init;
+ uint64_t fs_poll_init;
uint64_t handle_init;
- uint64_t stream_init;
- uint64_t tcp_init;
- uint64_t udp_init;
+ uint64_t idle_init;
uint64_t pipe_init;
- uint64_t tty_init;
uint64_t poll_init;
uint64_t prepare_init;
- uint64_t check_init;
- uint64_t idle_init;
- uint64_t async_init;
- uint64_t timer_init;
uint64_t process_init;
- uint64_t fs_event_init;
+ uint64_t req_init;
+ uint64_t stream_init;
+ uint64_t tcp_init;
+ uint64_t timer_init;
+ uint64_t tty_init;
+ uint64_t udp_init;
};
diff --git a/deps/uv/src/fs-poll.c b/deps/uv/src/fs-poll.c
new file mode 100644
index 0000000000..61438f916f
--- /dev/null
+++ b/deps/uv/src/fs-poll.c
@@ -0,0 +1,235 @@
+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "uv.h"
+#include "uv-common.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+static int statbuf_eq(const uv_statbuf_t* a, const uv_statbuf_t* b);
+static void timer_cb(uv_timer_t* timer, int status);
+static void poll_cb(uv_fs_t* req);
+
+
+int uv_fs_poll_init(uv_loop_t* loop, uv_fs_poll_t* handle) {
+ /* TODO(bnoordhuis) Mark fs_req internal. */
+ uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_POLL);
+ loop->counters.fs_poll_init++;
+
+ if (uv_timer_init(loop, &handle->timer_handle))
+ return -1;
+
+ handle->timer_handle.flags |= UV__HANDLE_INTERNAL;
+ uv__handle_unref(&handle->timer_handle);
+
+ return 0;
+}
+
+
+int uv_fs_poll_start(uv_fs_poll_t* handle,
+ uv_fs_poll_cb cb,
+ const char* path,
+ unsigned int interval) {
+ uv_fs_t* req;
+ size_t len;
+
+ if (uv__is_active(handle))
+ return 0;
+
+ len = strlen(path) + 1;
+ req = malloc(sizeof(*req) + len);
+
+ if (req == NULL)
+ return uv__set_artificial_error(handle->loop, UV_ENOMEM);
+
+ req->data = handle;
+ handle->path = memcpy(req + 1, path, len);
+ handle->fs_req = req;
+ handle->poll_cb = cb;
+ handle->interval = interval ? interval : 1;
+ handle->start_time = uv_now(handle->loop);
+ handle->busy_polling = 0;
+ memset(&handle->statbuf, 0, sizeof(handle->statbuf));
+
+ if (uv_fs_stat(handle->loop, handle->fs_req, handle->path, poll_cb))
+ abort();
+
+ uv__handle_start(handle);
+
+ return 0;
+}
+
+
+int uv_fs_poll_stop(uv_fs_poll_t* handle) {
+ if (!uv__is_active(handle))
+ return 0;
+
+ /* Don't free the fs req if it's active. Signal poll_cb that it needs to free
+ * the req by removing the handle backlink.
+ *
+ * TODO(bnoordhuis) Have uv-unix postpone the close callback until the req
+ * finishes so we don't need this pointer / lifecycle hackery. The callback
+ * always runs on the next tick now.
+ */
+ if (handle->fs_req->data)
+ handle->fs_req->data = NULL;
+ else
+ free(handle->fs_req);
+
+ handle->fs_req = NULL;
+ handle->path = NULL;
+
+ uv_timer_stop(&handle->timer_handle);
+ uv__handle_stop(handle);
+
+ return 0;
+}
+
+
+void uv__fs_poll_close(uv_fs_poll_t* handle) {
+ uv_fs_poll_stop(handle);
+ uv_close((uv_handle_t*)&handle->timer_handle, NULL);
+}
+
+
+static void timer_cb(uv_timer_t* timer, int status) {
+ uv_fs_poll_t* handle;
+
+ handle = container_of(timer, uv_fs_poll_t, timer_handle);
+ handle->start_time = uv_now(handle->loop);
+ handle->fs_req->data = handle;
+
+ if (uv_fs_stat(handle->loop, handle->fs_req, handle->path, poll_cb))
+ abort();
+
+ assert(uv__is_active(handle));
+}
+
+
+static void poll_cb(uv_fs_t* req) {
+ uv_statbuf_t* statbuf;
+ uv_fs_poll_t* handle;
+ uint64_t interval;
+
+ handle = req->data;
+
+ if (handle == NULL) /* Handle has been stopped or closed. */
+ goto out;
+
+ assert(req == handle->fs_req);
+
+ if (req->result != 0) {
+ if (handle->busy_polling != -req->errorno) {
+ uv__set_artificial_error(handle->loop, req->errorno);
+ handle->poll_cb(handle, -1, NULL, NULL);
+ handle->busy_polling = -req->errorno;
+ }
+ goto out;
+ }
+
+ statbuf = req->ptr;
+
+ if (handle->busy_polling != 0)
+ if (handle->busy_polling < 0 || !statbuf_eq(&handle->statbuf, statbuf))
+ handle->poll_cb(handle, 0, &handle->statbuf, statbuf);
+
+ handle->statbuf = *statbuf;
+ handle->busy_polling = 1;
+
+out:
+ uv_fs_req_cleanup(req);
+
+ if (req->data == NULL) { /* Handle has been stopped or closed. */
+ free(req);
+ return;
+ }
+
+ req->data = NULL; /* Tell uv_fs_poll_stop() it's safe to free the req. */
+
+ /* Reschedule timer, subtract the delay from doing the stat(). */
+ interval = handle->interval;
+ interval -= (uv_now(handle->loop) - handle->start_time) % interval;
+
+ if (uv_timer_start(&handle->timer_handle, timer_cb, interval, 0))
+ abort();
+}
+
+
+static int statbuf_eq(const uv_statbuf_t* a, const uv_statbuf_t* b) {
+#ifdef _WIN32
+ return a->st_mtime == b->st_mtime
+ && a->st_size == b->st_size
+ && a->st_mode == b->st_mode;
+#else
+
+ /* Jump through a few hoops to get sub-second granularity on Linux. */
+# if __linux__
+# if __USE_MISC /* _BSD_SOURCE || _SVID_SOURCE */
+ if (a->st_ctim.tv_nsec != b->st_ctim.tv_nsec) return 0;
+ if (a->st_mtim.tv_nsec != b->st_mtim.tv_nsec) return 0;
+# else
+ if (a->st_ctimensec != b->st_ctimensec) return 0;
+ if (a->st_mtimensec != b->st_mtimensec) return 0;
+# endif
+# endif
+
+ /* Jump through different hoops on OS X. */
+# if __APPLE__
+# if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
+ if (a->st_ctimespec.tv_nsec != b->st_ctimespec.tv_nsec) return 0;
+ if (a->st_mtimespec.tv_nsec != b->st_mtimespec.tv_nsec) return 0;
+# else
+ if (a->st_ctimensec != b->st_ctimensec) return 0;
+ if (a->st_mtimensec != b->st_mtimensec) return 0;
+# endif
+# endif
+
+ /* TODO(bnoordhuis) Other Unices have st_ctim and friends too, provided
+ * the stars and compiler flags are right...
+ */
+
+ return a->st_ctime == b->st_ctime
+ && a->st_mtime == b->st_mtime
+ && a->st_size == b->st_size
+ && a->st_mode == b->st_mode
+ && a->st_uid == b->st_uid
+ && a->st_gid == b->st_gid
+ && a->st_ino == b->st_ino
+ && a->st_dev == b->st_dev;
+#endif
+}
+
+
+#ifdef _WIN32
+
+#include "win/internal.h"
+#include "win/handle-inl.h"
+
+void uv__fs_poll_endgame(uv_loop_t* loop, uv_fs_poll_t* handle) {
+ assert(handle->flags & UV_HANDLE_CLOSING);
+ assert(!(handle->flags & UV_HANDLE_CLOSED));
+ uv__handle_stop(handle);
+ uv__handle_close(handle);
+}
+
+#endif /* _WIN32 */
diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c
index 524ffd0c61..318eb7184e 100644
--- a/deps/uv/src/unix/core.c
+++ b/deps/uv/src/unix/core.c
@@ -109,6 +109,10 @@ void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
uv__poll_close((uv_poll_t*)handle);
break;
+ case UV_FS_POLL:
+ uv__fs_poll_close((uv_fs_poll_t*)handle);
+ break;
+
default:
assert(0);
}
@@ -133,6 +137,9 @@ static void uv__finish_close(uv_handle_t* handle) {
case UV_ASYNC:
case UV_TIMER:
case UV_PROCESS:
+ case UV_FS_EVENT:
+ case UV_FS_POLL:
+ case UV_POLL:
break;
case UV_NAMED_PIPE:
@@ -148,12 +155,6 @@ static void uv__finish_close(uv_handle_t* handle) {
uv__udp_finish_close((uv_udp_t*)handle);
break;
- case UV_FS_EVENT:
- break;
-
- case UV_POLL:
- break;
-
default:
assert(0);
break;
diff --git a/deps/uv/src/unix/linux/syscalls.c b/deps/uv/src/unix/linux/syscalls.c
index 4a1f8bc07f..5eb826b7c5 100644
--- a/deps/uv/src/unix/linux/syscalls.c
+++ b/deps/uv/src/unix/linux/syscalls.c
@@ -135,7 +135,7 @@
# elif __i386__
# define __NR_sendmmsg 345
# elif __arm__
-# define __NR_recvmmsg (UV_SYSCALL_BASE + 374)
+# define __NR_sendmmsg (UV_SYSCALL_BASE + 374)
# endif
#endif /* __NR_sendmmsg */
diff --git a/deps/uv/src/unix/sunos.c b/deps/uv/src/unix/sunos.c
index d5867acb6a..bfe02bb17a 100644
--- a/deps/uv/src/unix/sunos.c
+++ b/deps/uv/src/unix/sunos.c
@@ -213,6 +213,7 @@ void uv__fs_event_close(uv_fs_event_t* handle) {
free(handle->filename);
handle->filename = NULL;
handle->fo.fo_name = NULL;
+ uv__handle_stop(handle);
}
#else /* !HAVE_PORTS_FS */
diff --git a/deps/uv/src/uv-common.h b/deps/uv/src/uv-common.h
index 4c316ec11d..d159727d6c 100644
--- a/deps/uv/src/uv-common.h
+++ b/deps/uv/src/uv-common.h
@@ -86,6 +86,8 @@ int uv__tcp_connect6(uv_connect_t* req,
struct sockaddr_in6 address,
uv_connect_cb cb);
+void uv__fs_poll_close(uv_fs_poll_t* handle);
+
UNUSED static int uv__has_active_reqs(const uv_loop_t* loop) {
return !ngx_queue_empty(&loop->active_reqs);
diff --git a/deps/uv/src/win/handle-inl.h b/deps/uv/src/win/handle-inl.h
index ea2d9e0bc5..4064c24cf9 100644
--- a/deps/uv/src/win/handle-inl.h
+++ b/deps/uv/src/win/handle-inl.h
@@ -131,6 +131,10 @@ INLINE static void uv_process_endgames(uv_loop_t* loop) {
uv_fs_event_endgame(loop, (uv_fs_event_t*) handle);
break;
+ case UV_FS_POLL:
+ uv__fs_poll_endgame(loop, (uv_fs_poll_t*) handle);
+ break;
+
default:
assert(0);
break;
diff --git a/deps/uv/src/win/handle.c b/deps/uv/src/win/handle.c
index 9343d256e1..d4b86de99e 100644
--- a/deps/uv/src/win/handle.c
+++ b/deps/uv/src/win/handle.c
@@ -132,6 +132,12 @@ void uv_close(uv_handle_t* handle, uv_close_cb cb) {
uv_fs_event_close(loop, (uv_fs_event_t*) handle);
return;
+ case UV_FS_POLL:
+ uv__fs_poll_close((uv_fs_poll_t*) handle);
+ uv__handle_start(handle);
+ uv_want_endgame(loop, handle);
+ return;
+
default:
/* Not supported */
abort();
diff --git a/deps/uv/src/win/internal.h b/deps/uv/src/win/internal.h
index 30d9e8c5b4..aaae66e7a3 100644
--- a/deps/uv/src/win/internal.h
+++ b/deps/uv/src/win/internal.h
@@ -269,6 +269,12 @@ void uv_fs_event_endgame(uv_loop_t* loop, uv_fs_event_t* handle);
/*
+ * Stat poller.
+ */
+void uv__fs_poll_endgame(uv_loop_t* loop, uv_fs_poll_t* handle);
+
+
+/*
* Utilities.
*/
void uv__util_init();
diff --git a/deps/uv/test/test-fs-poll.c b/deps/uv/test/test-fs-poll.c
new file mode 100644
index 0000000000..d1c90e2ce2
--- /dev/null
+++ b/deps/uv/test/test-fs-poll.c
@@ -0,0 +1,147 @@
+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "uv.h"
+#include "task.h"
+
+#include <string.h>
+
+#define FIXTURE "testfile"
+
+static void timer_cb(uv_timer_t* handle, int status);
+static void close_cb(uv_handle_t* handle);
+static void poll_cb(uv_fs_poll_t* handle,
+ int status,
+ uv_statbuf_t* prev,
+ uv_statbuf_t* curr);
+
+static uv_fs_poll_t poll_handle;
+static uv_timer_t timer_handle;
+static uv_loop_t* loop;
+
+static int poll_cb_called;
+static int timer_cb_called;
+static int close_cb_called;
+
+
+static void touch_file(const char* path) {
+ static int count;
+ FILE* fp;
+ int i;
+
+ ASSERT((fp = fopen(FIXTURE, "w+")));
+
+ /* Need to change the file size because the poller may not pick up
+ * sub-second mtime changes.
+ */
+ i = ++count;
+
+ while (i--)
+ fputc('*', fp);
+
+ fclose(fp);
+}
+
+
+static void close_cb(uv_handle_t* handle) {
+ close_cb_called++;
+}
+
+
+static void timer_cb(uv_timer_t* handle, int status) {
+ touch_file(FIXTURE);
+ timer_cb_called++;
+}
+
+
+static void poll_cb(uv_fs_poll_t* handle,
+ int status,
+ uv_statbuf_t* prev,
+ uv_statbuf_t* curr) {
+ ASSERT(handle == &poll_handle);
+ ASSERT(uv_is_active((uv_handle_t*)handle));
+
+ switch (poll_cb_called++) {
+ case 0:
+ ASSERT(status == -1);
+ ASSERT(prev == NULL);
+ ASSERT(curr == NULL);
+ ASSERT(uv_last_error(loop).code == UV_ENOENT);
+ touch_file(FIXTURE);
+ break;
+
+ case 1:
+ ASSERT(status == 0);
+ ASSERT(prev != NULL);
+ ASSERT(curr != NULL);
+ {
+ uv_statbuf_t buf;
+ memset(&buf, 0, sizeof(buf));
+ ASSERT(0 == memcmp(&buf, prev, sizeof(buf)));
+ }
+ ASSERT(0 == uv_timer_start(&timer_handle, timer_cb, 20, 0));
+ break;
+
+ case 2:
+ ASSERT(status == 0);
+ ASSERT(prev != NULL);
+ ASSERT(curr != NULL);
+ ASSERT(0 == uv_timer_start(&timer_handle, timer_cb, 200, 0));
+ break;
+
+ case 3:
+ ASSERT(status == 0);
+ ASSERT(prev != NULL);
+ ASSERT(curr != NULL);
+ remove(FIXTURE);
+ break;
+
+ case 4:
+ ASSERT(status == -1);
+ ASSERT(prev == NULL);
+ ASSERT(curr == NULL);
+ ASSERT(uv_last_error(loop).code == UV_ENOENT);
+ uv_close((uv_handle_t*)handle, close_cb);
+ break;
+
+ default:
+ ASSERT(0);
+ }
+}
+
+
+TEST_IMPL(fs_poll) {
+ loop = uv_default_loop();
+
+ remove(FIXTURE);
+
+ ASSERT(0 == uv_timer_init(loop, &timer_handle));
+ ASSERT(0 == uv_fs_poll_init(loop, &poll_handle));
+ ASSERT(0 == uv_fs_poll_start(&poll_handle, poll_cb, FIXTURE, 100));
+ ASSERT(0 == uv_run(loop));
+
+ ASSERT(poll_cb_called == 5);
+ ASSERT(timer_cb_called == 2);
+ ASSERT(close_cb_called == 1);
+ uv_loop_delete(loop);
+
+ return 0;
+}
diff --git a/deps/uv/test/test-hrtime.c b/deps/uv/test/test-hrtime.c
index 91059f03af..2a9156ecf9 100644
--- a/deps/uv/test/test-hrtime.c
+++ b/deps/uv/test/test-hrtime.c
@@ -33,7 +33,7 @@
TEST_IMPL(hrtime) {
uint64_t a, b, diff;
- int i = 100;
+ int i = 75;
while (i > 0) {
a = uv_hrtime();
uv_sleep(45);
diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h
index 9af246dd7b..cf9a02edb1 100644
--- a/deps/uv/test/test-list.h
+++ b/deps/uv/test/test-list.h
@@ -97,6 +97,7 @@ TEST_DECLARE (unref_in_prepare_cb)
TEST_DECLARE (timer_ref)
TEST_DECLARE (timer_ref2)
TEST_DECLARE (fs_event_ref)
+TEST_DECLARE (fs_poll_ref)
TEST_DECLARE (tcp_ref)
TEST_DECLARE (tcp_ref2)
TEST_DECLARE (tcp_ref3)
@@ -134,6 +135,7 @@ TEST_DECLARE (spawn_and_ping)
TEST_DECLARE (spawn_setuid_fails)
TEST_DECLARE (spawn_setgid_fails)
TEST_DECLARE (spawn_stdout_to_file)
+TEST_DECLARE (fs_poll)
TEST_DECLARE (kill)
TEST_DECLARE (fs_file_noent)
TEST_DECLARE (fs_file_nametoolong)
@@ -293,6 +295,7 @@ TASK_LIST_START
TEST_ENTRY (ref)
TEST_ENTRY (idle_ref)
+ TEST_ENTRY (fs_poll_ref)
TEST_ENTRY (async_ref)
TEST_ENTRY (prepare_ref)
TEST_ENTRY (check_ref)
@@ -360,6 +363,7 @@ TASK_LIST_START
TEST_ENTRY (spawn_setuid_fails)
TEST_ENTRY (spawn_setgid_fails)
TEST_ENTRY (spawn_stdout_to_file)
+ TEST_ENTRY (fs_poll)
TEST_ENTRY (kill)
#ifdef _WIN32
TEST_ENTRY (spawn_detect_pipe_name_collisions_on_windows)
diff --git a/deps/uv/test/test-ref.c b/deps/uv/test/test-ref.c
index cc59aa7b6c..e0c38858ec 100644
--- a/deps/uv/test/test-ref.c
+++ b/deps/uv/test/test-ref.c
@@ -168,6 +168,16 @@ TEST_IMPL(fs_event_ref) {
}
+TEST_IMPL(fs_poll_ref) {
+ uv_fs_poll_t h;
+ uv_fs_poll_init(uv_default_loop(), &h);
+ uv_fs_poll_start(&h, NULL, ".", 999);
+ uv_unref((uv_handle_t*)&h);
+ uv_run(uv_default_loop());
+ return 0;
+}
+
+
TEST_IMPL(tcp_ref) {
uv_tcp_t h;
uv_tcp_init(uv_default_loop(), &h);
diff --git a/deps/uv/uv.gyp b/deps/uv/uv.gyp
index 0a519b7949..63f3ec0e5a 100644
--- a/deps/uv/uv.gyp
+++ b/deps/uv/uv.gyp
@@ -50,6 +50,7 @@
'include/uv-private/ngx-queue.h',
'include/uv-private/tree.h',
'src/cares.c',
+ 'src/fs-poll.c',
'src/uv-common.c',
'src/uv-common.h',
'src/ares/ares_cancel.c',
@@ -339,6 +340,7 @@
'test/test-shutdown-close.c',
'test/test-shutdown-eof.c',
'test/test-spawn.c',
+ 'test/test-fs-poll.c',
'test/test-stdio-over-pipes.c',
'test/test-tcp-bind-error.c',
'test/test-tcp-bind6-error.c',