Skip to content

Commit 44d5f21

Browse files
choonkeatry
authored andcommitted
Stat::Callback has 2 arguments for callback: current stat info and previous stat info
http://groups.google.com/group/nodejs/msg/f8e51a8e0c74bd85
1 parent 633d6be commit 44d5f21

File tree

7 files changed

+105
-78
lines changed

7 files changed

+105
-78
lines changed

doc/api.txt

+12
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,18 @@ The second argument is optional. The +options+ if provided should be an
137137
object containing two members a boolean, +persistent+, and +interval+, a
138138
polling value in milliseconds. The default is +{persistent: true, interval:
139139
0}+.
140+
+
141+
The +listener+ gets two arguments the current stat object and the previous
142+
stat object:
143+
+
144+
-------------------------
145+
process.watchFile(f, function (curr, prev) {
146+
sys.puts("the current mtime is: " + curr.mtime);
147+
sys.puts("the previous mtime was: " + prev.mtime);
148+
});
149+
-------------------------
150+
+
151+
These stat objects are instances of +posix.Stat+.
140152

141153
+process.unwatchFile(filename)+::
142154
Stop watching for changes on +filename+.

lib/posix.js

+10-8
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,37 @@
1-
process.fs.Stats.prototype._checkModeProperty = function (property) {
1+
process.Stats.prototype._checkModeProperty = function (property) {
22
return ((this.mode & property) === property);
33
};
44

5-
process.fs.Stats.prototype.isDirectory = function () {
5+
process.Stats.prototype.isDirectory = function () {
66
return this._checkModeProperty(process.S_IFDIR);
77
};
88

9-
process.fs.Stats.prototype.isFile = function () {
9+
process.Stats.prototype.isFile = function () {
1010
return this._checkModeProperty(process.S_IFREG);
1111
};
1212

13-
process.fs.Stats.prototype.isBlockDevice = function () {
13+
process.Stats.prototype.isBlockDevice = function () {
1414
return this._checkModeProperty(process.S_IFBLK);
1515
};
1616

17-
process.fs.Stats.prototype.isCharacterDevice = function () {
17+
process.Stats.prototype.isCharacterDevice = function () {
1818
return this._checkModeProperty(process.S_IFCHR);
1919
};
2020

21-
process.fs.Stats.prototype.isSymbolicLink = function () {
21+
process.Stats.prototype.isSymbolicLink = function () {
2222
return this._checkModeProperty(process.S_IFLNK);
2323
};
2424

25-
process.fs.Stats.prototype.isFIFO = function () {
25+
process.Stats.prototype.isFIFO = function () {
2626
return this._checkModeProperty(process.S_IFIFO);
2727
};
2828

29-
process.fs.Stats.prototype.isSocket = function () {
29+
process.Stats.prototype.isSocket = function () {
3030
return this._checkModeProperty(process.S_IFSOCK);
3131
};
3232

33+
exports.Stats = process.Stats;
34+
3335
for (var key in process.fs) {
3436
if (process.fs.hasOwnProperty(key)) exports[key] = process.fs[key];
3537
}

src/node.cc

+72
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,71 @@ ssize_t DecodeWrite(char *buf, size_t buflen,
160160
return buflen;
161161
}
162162

163+
#define DEV_SYMBOL String::NewSymbol("dev")
164+
#define INO_SYMBOL String::NewSymbol("ino")
165+
#define MODE_SYMBOL String::NewSymbol("mode")
166+
#define NLINK_SYMBOL String::NewSymbol("nlink")
167+
#define UID_SYMBOL String::NewSymbol("uid")
168+
#define GID_SYMBOL String::NewSymbol("gid")
169+
#define RDEV_SYMBOL String::NewSymbol("rdev")
170+
#define SIZE_SYMBOL String::NewSymbol("size")
171+
#define BLKSIZE_SYMBOL String::NewSymbol("blksize")
172+
#define BLOCKS_SYMBOL String::NewSymbol("blocks")
173+
#define ATIME_SYMBOL String::NewSymbol("atime")
174+
#define MTIME_SYMBOL String::NewSymbol("mtime")
175+
#define CTIME_SYMBOL String::NewSymbol("ctime")
176+
177+
static Persistent<FunctionTemplate> stats_constructor_template;
178+
179+
Local<Object> BuildStatsObject(struct stat * s) {
180+
HandleScope scope;
181+
182+
Local<Object> stats =
183+
stats_constructor_template->GetFunction()->NewInstance();
184+
185+
/* ID of device containing file */
186+
stats->Set(DEV_SYMBOL, Integer::New(s->st_dev));
187+
188+
/* inode number */
189+
stats->Set(INO_SYMBOL, Integer::New(s->st_ino));
190+
191+
/* protection */
192+
stats->Set(MODE_SYMBOL, Integer::New(s->st_mode));
193+
194+
/* number of hard links */
195+
stats->Set(NLINK_SYMBOL, Integer::New(s->st_nlink));
196+
197+
/* user ID of owner */
198+
stats->Set(UID_SYMBOL, Integer::New(s->st_uid));
199+
200+
/* group ID of owner */
201+
stats->Set(GID_SYMBOL, Integer::New(s->st_gid));
202+
203+
/* device ID (if special file) */
204+
stats->Set(RDEV_SYMBOL, Integer::New(s->st_rdev));
205+
206+
/* total size, in bytes */
207+
stats->Set(SIZE_SYMBOL, Integer::New(s->st_size));
208+
209+
/* blocksize for filesystem I/O */
210+
stats->Set(BLKSIZE_SYMBOL, Integer::New(s->st_blksize));
211+
212+
/* number of blocks allocated */
213+
stats->Set(BLOCKS_SYMBOL, Integer::New(s->st_blocks));
214+
215+
/* time of last access */
216+
stats->Set(ATIME_SYMBOL, NODE_UNIXTIME_V8(s->st_atime));
217+
218+
/* time of last modification */
219+
stats->Set(MTIME_SYMBOL, NODE_UNIXTIME_V8(s->st_mtime));
220+
221+
/* time of last status change */
222+
stats->Set(CTIME_SYMBOL, NODE_UNIXTIME_V8(s->st_ctime));
223+
224+
return scope.Close(stats);
225+
}
226+
227+
163228
// Extracts a C str from a V8 Utf8Value.
164229
const char* ToCString(const v8::String::Utf8Value& value) {
165230
return *value ? *value : "<str conversion failed>";
@@ -726,6 +791,13 @@ static Local<Object> Load(int argc, char *argv[]) {
726791
process->Set(String::NewSymbol("EventEmitter"),
727792
EventEmitter::constructor_template->GetFunction());
728793

794+
// Initialize the stats object
795+
Local<FunctionTemplate> stat_templ = FunctionTemplate::New();
796+
stats_constructor_template = Persistent<FunctionTemplate>::New(stat_templ);
797+
process->Set(String::NewSymbol("Stats"),
798+
stats_constructor_template->GetFunction());
799+
800+
729801
// Initialize the C++ modules..................filename of module
730802
Promise::Initialize(process); // events.cc
731803
Stdio::Initialize(process); // stdio.cc

src/node.h

+4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#include <eio.h>
77
#include <v8.h>
88
#include <evcom.h>
9+
#include <sys/types.h> /* struct stat */
10+
#include <sys/stat.h>
911

1012
#include <node_object_wrap.h>
1113

@@ -51,6 +53,8 @@ ssize_t DecodeWrite(char *buf,
5153
v8::Handle<v8::Value>,
5254
enum encoding encoding = BINARY);
5355

56+
v8::Local<v8::Object> BuildStatsObject(struct stat * s);
57+
5458

5559
} // namespace node
5660
#endif // SRC_NODE_H_

src/node_file.cc

+1-68
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,7 @@ namespace node {
1313

1414
using namespace v8;
1515

16-
#define DEV_SYMBOL String::NewSymbol("dev")
17-
#define INO_SYMBOL String::NewSymbol("ino")
18-
#define MODE_SYMBOL String::NewSymbol("mode")
19-
#define NLINK_SYMBOL String::NewSymbol("nlink")
20-
#define UID_SYMBOL String::NewSymbol("uid")
21-
#define GID_SYMBOL String::NewSymbol("gid")
22-
#define RDEV_SYMBOL String::NewSymbol("rdev")
23-
#define SIZE_SYMBOL String::NewSymbol("size")
24-
#define BLKSIZE_SYMBOL String::NewSymbol("blksize")
25-
#define BLOCKS_SYMBOL String::NewSymbol("blocks")
26-
#define ATIME_SYMBOL String::NewSymbol("atime")
27-
#define MTIME_SYMBOL String::NewSymbol("mtime")
28-
#define CTIME_SYMBOL String::NewSymbol("ctime")
29-
#define BAD_ARGUMENTS Exception::TypeError(String::New("Bad argument"))
16+
#define BAD_ARGUMENTS Exception::TypeError(String::New("Bad argument"))
3017

3118
void EIOPromise::Attach(void) {
3219
ev_ref(EV_DEFAULT_UC);
@@ -58,55 +45,6 @@ EIOPromise* EIOPromise::Create() {
5845
return ObjectWrap::Unwrap<EIOPromise>(handle);
5946
}
6047

61-
static Persistent<FunctionTemplate> stats_constructor_template;
62-
63-
static Local<Object> BuildStatsObject(struct stat * s) {
64-
HandleScope scope;
65-
66-
Local<Object> stats =
67-
stats_constructor_template->GetFunction()->NewInstance();
68-
69-
/* ID of device containing file */
70-
stats->Set(DEV_SYMBOL, Integer::New(s->st_dev));
71-
72-
/* inode number */
73-
stats->Set(INO_SYMBOL, Integer::New(s->st_ino));
74-
75-
/* protection */
76-
stats->Set(MODE_SYMBOL, Integer::New(s->st_mode));
77-
78-
/* number of hard links */
79-
stats->Set(NLINK_SYMBOL, Integer::New(s->st_nlink));
80-
81-
/* user ID of owner */
82-
stats->Set(UID_SYMBOL, Integer::New(s->st_uid));
83-
84-
/* group ID of owner */
85-
stats->Set(GID_SYMBOL, Integer::New(s->st_gid));
86-
87-
/* device ID (if special file) */
88-
stats->Set(RDEV_SYMBOL, Integer::New(s->st_rdev));
89-
90-
/* total size, in bytes */
91-
stats->Set(SIZE_SYMBOL, Integer::New(s->st_size));
92-
93-
/* blocksize for filesystem I/O */
94-
stats->Set(BLKSIZE_SYMBOL, Integer::New(s->st_blksize));
95-
96-
/* number of blocks allocated */
97-
stats->Set(BLOCKS_SYMBOL, Integer::New(s->st_blocks));
98-
99-
/* time of last access */
100-
stats->Set(ATIME_SYMBOL, NODE_UNIXTIME_V8(s->st_atime));
101-
102-
/* time of last modification */
103-
stats->Set(MTIME_SYMBOL, NODE_UNIXTIME_V8(s->st_mtime));
104-
105-
/* time of last status change */
106-
stats->Set(CTIME_SYMBOL, NODE_UNIXTIME_V8(s->st_ctime));
107-
108-
return scope.Close(stats);
109-
}
11048

11149
int EIOPromise::After(eio_req *req) {
11250
HandleScope scope;
@@ -388,11 +326,6 @@ void File::Initialize(Handle<Object> target) {
388326
NODE_SET_METHOD(target, "unlink", Unlink);
389327
NODE_SET_METHOD(target, "write", Write);
390328

391-
Local<FunctionTemplate> t = FunctionTemplate::New();
392-
stats_constructor_template = Persistent<FunctionTemplate>::New(t);
393-
target->Set(String::NewSymbol("Stats"),
394-
stats_constructor_template->GetFunction());
395-
396329

397330
Local<FunctionTemplate> t2 = FunctionTemplate::New(EIOPromise::New);
398331
EIOPromise::constructor_template = Persistent<FunctionTemplate>::New(t2);

src/node_stat.cc

+4-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,10 @@ void Stat::Callback(EV_P_ ev_stat *watcher, int revents) {
3232
Stat *handler = static_cast<Stat*>(watcher->data);
3333
assert(watcher == &handler->watcher_);
3434
HandleScope scope;
35-
handler->Emit("change", 0, NULL);
35+
Handle<Value> argv[2];
36+
argv[0] = Handle<Value>(BuildStatsObject(&watcher->attr));
37+
argv[1] = Handle<Value>(BuildStatsObject(&watcher->prev));
38+
handler->Emit("change", 2, argv);
3639
}
3740

3841

test/mjsunit/test-stat-handler.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ var f2 = path.join(fixturesDir, "x2.txt");
88
puts("watching for changes of " + f);
99

1010
var changes = 0;
11-
process.watchFile(f, function () {
11+
process.watchFile(f, function (curr, prev) {
1212
puts(f + " change");
1313
changes++;
14+
assertTrue(curr.mtime != prev.mtime);
1415
process.unwatchFile(f);
1516
});
1617

0 commit comments

Comments
 (0)