diff options
author | Ben Noordhuis <info@bnoordhuis.nl> | 2012-06-17 00:41:37 +0400 |
---|---|---|
committer | Ben Noordhuis <info@bnoordhuis.nl> | 2012-06-21 05:05:18 +0400 |
commit | f0ce98441ff7315e6a6c268dabcec58fc37da926 (patch) | |
tree | 9d0f41c17dbf55b42796cac9d725ba42c88c90e1 | |
parent | d98a8578d62cd1b35574269dc028a0c8c34ef25b (diff) |
fs: make fs.watchFile() work on windows
-rw-r--r-- | lib/fs.js | 12 | ||||
-rw-r--r-- | node.gyp | 2 | ||||
-rw-r--r-- | src/node.cc | 1 | ||||
-rw-r--r-- | src/node_file.cc | 6 | ||||
-rw-r--r-- | src/node_stat_watcher.cc | 68 | ||||
-rw-r--r-- | src/node_stat_watcher.h | 15 | ||||
-rw-r--r-- | test/pummel/test-fs-watch-file.js | 6 | ||||
-rw-r--r-- | test/pummel/test-watch-file.js | 5 |
8 files changed, 52 insertions, 63 deletions
diff --git a/lib/fs.js b/lib/fs.js index 17c79c93573..8b3b6b233e8 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -876,7 +876,13 @@ function StatWatcher() { var self = this; this._handle = new binding.StatWatcher(); - this._handle.onchange = function(current, previous) { + // uv_fs_poll is a little more powerful than ev_stat but we curb it for + // the sake of backwards compatibility + var oldStatus = -1; + + this._handle.onchange = function(current, previous, newStatus) { + if (oldStatus == -1 && newStatus == -1) return; + oldStatus = newStatus; self.emit('change', current, previous); }; @@ -905,10 +911,6 @@ function inStatWatchers(filename) { fs.watchFile = function(filename) { - if (isWindows) { - throw new Error('use fs.watch api instead'); - } - var stat; var options; var listener; @@ -82,6 +82,7 @@ 'src/node_main.cc', 'src/node_os.cc', 'src/node_script.cc', + 'src/node_stat_watcher.cc', 'src/node_string.cc', 'src/node_zlib.cc', 'src/pipe_wrap.cc', @@ -208,7 +209,6 @@ 'defines': [ '__POSIX__' ], 'sources': [ 'src/node_signal_watcher.cc', - 'src/node_stat_watcher.cc', 'src/node_io_watcher.cc', ] }], diff --git a/src/node.cc b/src/node.cc index 991f63b31eb..d71a21b6938 100644 --- a/src/node.cc +++ b/src/node.cc @@ -69,7 +69,6 @@ typedef int mode_t; #include "node_http_parser.h" #ifdef __POSIX__ # include "node_signal_watcher.h" -# include "node_stat_watcher.h" #endif #include "node_constants.h" #include "node_javascript.h" diff --git a/src/node_file.cc b/src/node_file.cc index f48790a0934..7e8badf5c22 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -22,9 +22,7 @@ #include "node.h" #include "node_file.h" #include "node_buffer.h" -#ifdef __POSIX__ -# include "node_stat_watcher.h" -#endif +#include "node_stat_watcher.h" #include "req_wrap.h" #include <fcntl.h> @@ -984,9 +982,7 @@ void InitFs(Handle<Object> target) { oncomplete_sym = NODE_PSYMBOL("oncomplete"); -#ifdef __POSIX__ StatWatcher::Initialize(target); -#endif } } // end namespace node diff --git a/src/node_stat_watcher.cc b/src/node_stat_watcher.cc index efe3939e9bb..33190895a9d 100644 --- a/src/node_stat_watcher.cc +++ b/src/node_stat_watcher.cc @@ -25,6 +25,11 @@ #include <string.h> #include <stdlib.h> +// Poll interval in milliseconds. 5007 is what libev used to use. It's a little +// on the slow side but let's stick with it for now, keep behavioral changes to +// a minimum. +#define DEFAULT_POLL_INTERVAL 5007 + namespace node { using namespace v8; @@ -33,6 +38,7 @@ Persistent<FunctionTemplate> StatWatcher::constructor_template; static Persistent<String> onchange_sym; static Persistent<String> onstop_sym; + void StatWatcher::Initialize(Handle<Object> target) { HandleScope scope; @@ -48,18 +54,24 @@ void StatWatcher::Initialize(Handle<Object> target) { } -void StatWatcher::Callback(EV_P_ ev_stat *watcher, int revents) { - assert(revents == EV_STAT); - StatWatcher *handler = static_cast<StatWatcher*>(watcher->data); - assert(watcher == &handler->watcher_); +void StatWatcher::Callback(uv_fs_poll_t* handle, + int status, + const uv_statbuf_t* prev, + const uv_statbuf_t* curr) { + StatWatcher* wrap = container_of(handle, StatWatcher, watcher_); + assert(handle == &wrap->watcher_); HandleScope scope; - Local<Value> argv[2]; - argv[0] = BuildStatsObject(&watcher->attr); - argv[1] = BuildStatsObject(&watcher->prev); + Local<Value> argv[3]; + argv[0] = BuildStatsObject(curr); + argv[1] = BuildStatsObject(prev); + argv[2] = Integer::New(status); + if (status == -1) { + SetErrno(uv_last_error(wrap->watcher_.loop)); + } if (onchange_sym.IsEmpty()) { onchange_sym = NODE_PSYMBOL("onchange"); } - MakeCallback(handler->handle_, onchange_sym, ARRAY_SIZE(argv), argv); + MakeCallback(wrap->handle_, onchange_sym, ARRAY_SIZE(argv), argv); } @@ -69,7 +81,7 @@ Handle<Value> StatWatcher::New(const Arguments& args) { } HandleScope scope; - StatWatcher *s = new StatWatcher(); + StatWatcher* s = new StatWatcher(); s->Wrap(args.Holder()); return args.This(); } @@ -82,27 +94,23 @@ Handle<Value> StatWatcher::Start(const Arguments& args) { return ThrowException(Exception::TypeError(String::New("Bad arguments"))); } - StatWatcher *handler = ObjectWrap::Unwrap<StatWatcher>(args.Holder()); + StatWatcher* wrap = ObjectWrap::Unwrap<StatWatcher>(args.Holder()); String::Utf8Value path(args[0]); - assert(handler->path_ == NULL); - handler->path_ = strdup(*path); - - ev_tstamp interval = 0.; - if (args[2]->IsInt32()) { - interval = NODE_V8_UNIXTIME(args[2]); + uint32_t interval = DEFAULT_POLL_INTERVAL; + if (args[2]->IsUint32()) { + interval = args[2]->Uint32Value(); } - ev_stat_set(&handler->watcher_, handler->path_, interval); - ev_stat_start(EV_DEFAULT_UC_ &handler->watcher_); + uv_fs_poll_start(&wrap->watcher_, Callback, *path, interval); - handler->persistent_ = args[1]->IsTrue(); + wrap->persistent_ = args[1]->IsTrue(); - if (!handler->persistent_) { - ev_unref(EV_DEFAULT_UC); + if (!wrap->persistent_) { + uv_unref(reinterpret_cast<uv_handle_t*>(&wrap->watcher_)); } - handler->Ref(); + wrap->Ref(); return Undefined(); } @@ -110,24 +118,20 @@ Handle<Value> StatWatcher::Start(const Arguments& args) { Handle<Value> StatWatcher::Stop(const Arguments& args) { HandleScope scope; - StatWatcher *handler = ObjectWrap::Unwrap<StatWatcher>(args.Holder()); + StatWatcher* wrap = ObjectWrap::Unwrap<StatWatcher>(args.Holder()); if (onstop_sym.IsEmpty()) { onstop_sym = NODE_PSYMBOL("onstop"); } - MakeCallback(handler->handle_, onstop_sym, 0, NULL); - handler->Stop(); + MakeCallback(wrap->handle_, onstop_sym, 0, NULL); + wrap->Stop(); return Undefined(); } void StatWatcher::Stop () { - if (watcher_.active) { - if (!persistent_) ev_ref(EV_DEFAULT_UC); - ev_stat_stop(EV_DEFAULT_UC_ &watcher_); - free(path_); - path_ = NULL; - Unref(); - } + if (!uv_is_active(reinterpret_cast<uv_handle_t*>(&watcher_))) return; + uv_fs_poll_stop(&watcher_); + Unref(); } diff --git a/src/node_stat_watcher.h b/src/node_stat_watcher.h index 2b2d1331de2..5b09d2f04c3 100644 --- a/src/node_stat_watcher.h +++ b/src/node_stat_watcher.h @@ -23,7 +23,7 @@ #define NODE_STAT_WATCHER_H_ #include "node.h" -#include "uv-private/ev.h" +#include "uv.h" namespace node { @@ -36,14 +36,11 @@ class StatWatcher : ObjectWrap { StatWatcher() : ObjectWrap() { persistent_ = false; - path_ = NULL; - ev_init(&watcher_, StatWatcher::Callback); - watcher_.data = this; + uv_fs_poll_init(uv_default_loop(), &watcher_); } ~StatWatcher() { Stop(); - assert(path_ == NULL); } static v8::Handle<v8::Value> New(const v8::Arguments& args); @@ -51,13 +48,15 @@ class StatWatcher : ObjectWrap { static v8::Handle<v8::Value> Stop(const v8::Arguments& args); private: - static void Callback(EV_P_ ev_stat *watcher, int revents); + static void Callback(uv_fs_poll_t* handle, + int status, + const uv_statbuf_t* prev, + const uv_statbuf_t* curr); void Stop(); - ev_stat watcher_; + uv_fs_poll_t watcher_; bool persistent_; - char *path_; }; } // namespace node diff --git a/test/pummel/test-fs-watch-file.js b/test/pummel/test-fs-watch-file.js index 49455a197fb..3df28af56fc 100644 --- a/test/pummel/test-fs-watch-file.js +++ b/test/pummel/test-fs-watch-file.js @@ -19,12 +19,6 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. -// fs.watchFile is not available on Windows -if (process.platform === 'win32') { - process.exit(0); -} - - var common = require('../common'); var assert = require('assert'); var path = require('path'); diff --git a/test/pummel/test-watch-file.js b/test/pummel/test-watch-file.js index 3cdc3d67f56..1a3d854101c 100644 --- a/test/pummel/test-watch-file.js +++ b/test/pummel/test-watch-file.js @@ -19,11 +19,6 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. -// fs.watchFile is not available on Windows -if (process.platform === 'win32') { - process.exit(0); -} - var common = require('../common'); var assert = require('assert'); |