From 44d5f212febeb7a7cb76e67ca7a686490fa37598 Mon Sep 17 00:00:00 2001 From: choonkeat Date: Sat, 28 Nov 2009 14:52:27 +0100 Subject: [PATCH] Stat::Callback has 2 arguments for callback: current stat info and previous stat info http://groups.google.com/group/nodejs/msg/f8e51a8e0c74bd85 --- doc/api.txt | 12 ++++++ lib/posix.js | 18 ++++---- src/node.cc | 72 +++++++++++++++++++++++++++++++ src/node.h | 4 ++ src/node_file.cc | 69 +---------------------------- src/node_stat.cc | 5 ++- test/mjsunit/test-stat-handler.js | 3 +- 7 files changed, 105 insertions(+), 78 deletions(-) diff --git a/doc/api.txt b/doc/api.txt index 6387a3f86df..cabe9ddec3f 100644 --- a/doc/api.txt +++ b/doc/api.txt @@ -137,6 +137,18 @@ The second argument is optional. The +options+ if provided should be an object containing two members a boolean, +persistent+, and +interval+, a polling value in milliseconds. The default is +{persistent: true, interval: 0}+. ++ +The +listener+ gets two arguments the current stat object and the previous +stat object: ++ +------------------------- +process.watchFile(f, function (curr, prev) { + sys.puts("the current mtime is: " + curr.mtime); + sys.puts("the previous mtime was: " + prev.mtime); +}); +------------------------- ++ +These stat objects are instances of +posix.Stat+. +process.unwatchFile(filename)+:: Stop watching for changes on +filename+. diff --git a/lib/posix.js b/lib/posix.js index 01d09f05c16..989532a560e 100644 --- a/lib/posix.js +++ b/lib/posix.js @@ -1,35 +1,37 @@ -process.fs.Stats.prototype._checkModeProperty = function (property) { +process.Stats.prototype._checkModeProperty = function (property) { return ((this.mode & property) === property); }; -process.fs.Stats.prototype.isDirectory = function () { +process.Stats.prototype.isDirectory = function () { return this._checkModeProperty(process.S_IFDIR); }; -process.fs.Stats.prototype.isFile = function () { +process.Stats.prototype.isFile = function () { return this._checkModeProperty(process.S_IFREG); }; -process.fs.Stats.prototype.isBlockDevice = function () { +process.Stats.prototype.isBlockDevice = function () { return this._checkModeProperty(process.S_IFBLK); }; -process.fs.Stats.prototype.isCharacterDevice = function () { +process.Stats.prototype.isCharacterDevice = function () { return this._checkModeProperty(process.S_IFCHR); }; -process.fs.Stats.prototype.isSymbolicLink = function () { +process.Stats.prototype.isSymbolicLink = function () { return this._checkModeProperty(process.S_IFLNK); }; -process.fs.Stats.prototype.isFIFO = function () { +process.Stats.prototype.isFIFO = function () { return this._checkModeProperty(process.S_IFIFO); }; -process.fs.Stats.prototype.isSocket = function () { +process.Stats.prototype.isSocket = function () { return this._checkModeProperty(process.S_IFSOCK); }; +exports.Stats = process.Stats; + for (var key in process.fs) { if (process.fs.hasOwnProperty(key)) exports[key] = process.fs[key]; } diff --git a/src/node.cc b/src/node.cc index 76f5eac28e9..7df85028016 100644 --- a/src/node.cc +++ b/src/node.cc @@ -160,6 +160,71 @@ ssize_t DecodeWrite(char *buf, size_t buflen, return buflen; } +#define DEV_SYMBOL String::NewSymbol("dev") +#define INO_SYMBOL String::NewSymbol("ino") +#define MODE_SYMBOL String::NewSymbol("mode") +#define NLINK_SYMBOL String::NewSymbol("nlink") +#define UID_SYMBOL String::NewSymbol("uid") +#define GID_SYMBOL String::NewSymbol("gid") +#define RDEV_SYMBOL String::NewSymbol("rdev") +#define SIZE_SYMBOL String::NewSymbol("size") +#define BLKSIZE_SYMBOL String::NewSymbol("blksize") +#define BLOCKS_SYMBOL String::NewSymbol("blocks") +#define ATIME_SYMBOL String::NewSymbol("atime") +#define MTIME_SYMBOL String::NewSymbol("mtime") +#define CTIME_SYMBOL String::NewSymbol("ctime") + +static Persistent stats_constructor_template; + +Local BuildStatsObject(struct stat * s) { + HandleScope scope; + + Local stats = + stats_constructor_template->GetFunction()->NewInstance(); + + /* ID of device containing file */ + stats->Set(DEV_SYMBOL, Integer::New(s->st_dev)); + + /* inode number */ + stats->Set(INO_SYMBOL, Integer::New(s->st_ino)); + + /* protection */ + stats->Set(MODE_SYMBOL, Integer::New(s->st_mode)); + + /* number of hard links */ + stats->Set(NLINK_SYMBOL, Integer::New(s->st_nlink)); + + /* user ID of owner */ + stats->Set(UID_SYMBOL, Integer::New(s->st_uid)); + + /* group ID of owner */ + stats->Set(GID_SYMBOL, Integer::New(s->st_gid)); + + /* device ID (if special file) */ + stats->Set(RDEV_SYMBOL, Integer::New(s->st_rdev)); + + /* total size, in bytes */ + stats->Set(SIZE_SYMBOL, Integer::New(s->st_size)); + + /* blocksize for filesystem I/O */ + stats->Set(BLKSIZE_SYMBOL, Integer::New(s->st_blksize)); + + /* number of blocks allocated */ + stats->Set(BLOCKS_SYMBOL, Integer::New(s->st_blocks)); + + /* time of last access */ + stats->Set(ATIME_SYMBOL, NODE_UNIXTIME_V8(s->st_atime)); + + /* time of last modification */ + stats->Set(MTIME_SYMBOL, NODE_UNIXTIME_V8(s->st_mtime)); + + /* time of last status change */ + stats->Set(CTIME_SYMBOL, NODE_UNIXTIME_V8(s->st_ctime)); + + return scope.Close(stats); +} + + // Extracts a C str from a V8 Utf8Value. const char* ToCString(const v8::String::Utf8Value& value) { return *value ? *value : ""; @@ -726,6 +791,13 @@ static Local Load(int argc, char *argv[]) { process->Set(String::NewSymbol("EventEmitter"), EventEmitter::constructor_template->GetFunction()); + // Initialize the stats object + Local stat_templ = FunctionTemplate::New(); + stats_constructor_template = Persistent::New(stat_templ); + process->Set(String::NewSymbol("Stats"), + stats_constructor_template->GetFunction()); + + // Initialize the C++ modules..................filename of module Promise::Initialize(process); // events.cc Stdio::Initialize(process); // stdio.cc diff --git a/src/node.h b/src/node.h index de5b7b3bed9..159cc8c9708 100644 --- a/src/node.h +++ b/src/node.h @@ -6,6 +6,8 @@ #include #include #include +#include /* struct stat */ +#include #include @@ -51,6 +53,8 @@ ssize_t DecodeWrite(char *buf, v8::Handle, enum encoding encoding = BINARY); +v8::Local BuildStatsObject(struct stat * s); + } // namespace node #endif // SRC_NODE_H_ diff --git a/src/node_file.cc b/src/node_file.cc index 399ec88dd7f..efe3ab0fb45 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -13,20 +13,7 @@ namespace node { using namespace v8; -#define DEV_SYMBOL String::NewSymbol("dev") -#define INO_SYMBOL String::NewSymbol("ino") -#define MODE_SYMBOL String::NewSymbol("mode") -#define NLINK_SYMBOL String::NewSymbol("nlink") -#define UID_SYMBOL String::NewSymbol("uid") -#define GID_SYMBOL String::NewSymbol("gid") -#define RDEV_SYMBOL String::NewSymbol("rdev") -#define SIZE_SYMBOL String::NewSymbol("size") -#define BLKSIZE_SYMBOL String::NewSymbol("blksize") -#define BLOCKS_SYMBOL String::NewSymbol("blocks") -#define ATIME_SYMBOL String::NewSymbol("atime") -#define MTIME_SYMBOL String::NewSymbol("mtime") -#define CTIME_SYMBOL String::NewSymbol("ctime") -#define BAD_ARGUMENTS Exception::TypeError(String::New("Bad argument")) +#define BAD_ARGUMENTS Exception::TypeError(String::New("Bad argument")) void EIOPromise::Attach(void) { ev_ref(EV_DEFAULT_UC); @@ -58,55 +45,6 @@ EIOPromise* EIOPromise::Create() { return ObjectWrap::Unwrap(handle); } -static Persistent stats_constructor_template; - -static Local BuildStatsObject(struct stat * s) { - HandleScope scope; - - Local stats = - stats_constructor_template->GetFunction()->NewInstance(); - - /* ID of device containing file */ - stats->Set(DEV_SYMBOL, Integer::New(s->st_dev)); - - /* inode number */ - stats->Set(INO_SYMBOL, Integer::New(s->st_ino)); - - /* protection */ - stats->Set(MODE_SYMBOL, Integer::New(s->st_mode)); - - /* number of hard links */ - stats->Set(NLINK_SYMBOL, Integer::New(s->st_nlink)); - - /* user ID of owner */ - stats->Set(UID_SYMBOL, Integer::New(s->st_uid)); - - /* group ID of owner */ - stats->Set(GID_SYMBOL, Integer::New(s->st_gid)); - - /* device ID (if special file) */ - stats->Set(RDEV_SYMBOL, Integer::New(s->st_rdev)); - - /* total size, in bytes */ - stats->Set(SIZE_SYMBOL, Integer::New(s->st_size)); - - /* blocksize for filesystem I/O */ - stats->Set(BLKSIZE_SYMBOL, Integer::New(s->st_blksize)); - - /* number of blocks allocated */ - stats->Set(BLOCKS_SYMBOL, Integer::New(s->st_blocks)); - - /* time of last access */ - stats->Set(ATIME_SYMBOL, NODE_UNIXTIME_V8(s->st_atime)); - - /* time of last modification */ - stats->Set(MTIME_SYMBOL, NODE_UNIXTIME_V8(s->st_mtime)); - - /* time of last status change */ - stats->Set(CTIME_SYMBOL, NODE_UNIXTIME_V8(s->st_ctime)); - - return scope.Close(stats); -} int EIOPromise::After(eio_req *req) { HandleScope scope; @@ -388,11 +326,6 @@ void File::Initialize(Handle target) { NODE_SET_METHOD(target, "unlink", Unlink); NODE_SET_METHOD(target, "write", Write); - Local t = FunctionTemplate::New(); - stats_constructor_template = Persistent::New(t); - target->Set(String::NewSymbol("Stats"), - stats_constructor_template->GetFunction()); - Local t2 = FunctionTemplate::New(EIOPromise::New); EIOPromise::constructor_template = Persistent::New(t2); diff --git a/src/node_stat.cc b/src/node_stat.cc index f94e144252d..9ae82d75e88 100644 --- a/src/node_stat.cc +++ b/src/node_stat.cc @@ -32,7 +32,10 @@ void Stat::Callback(EV_P_ ev_stat *watcher, int revents) { Stat *handler = static_cast(watcher->data); assert(watcher == &handler->watcher_); HandleScope scope; - handler->Emit("change", 0, NULL); + Handle argv[2]; + argv[0] = Handle(BuildStatsObject(&watcher->attr)); + argv[1] = Handle(BuildStatsObject(&watcher->prev)); + handler->Emit("change", 2, argv); } diff --git a/test/mjsunit/test-stat-handler.js b/test/mjsunit/test-stat-handler.js index 4c520880d86..3df1c5279e7 100644 --- a/test/mjsunit/test-stat-handler.js +++ b/test/mjsunit/test-stat-handler.js @@ -8,9 +8,10 @@ var f2 = path.join(fixturesDir, "x2.txt"); puts("watching for changes of " + f); var changes = 0; -process.watchFile(f, function () { +process.watchFile(f, function (curr, prev) { puts(f + " change"); changes++; + assertTrue(curr.mtime != prev.mtime); process.unwatchFile(f); });