Skip to content

Commit cd70d4a

Browse files
committed
Add "/file.js" buffered disk I/O object.
This is similar to the class node.File which was removed in 82cb1b5. Needs documentation.
1 parent 4b8f503 commit cd70d4a

2 files changed

Lines changed: 166 additions & 0 deletions

File tree

lib/file.js

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
exports.debugLevel = 0; // Increase to get more verbose debug output
2+
3+
function debugMessage (msg) {
4+
if (exports.debugLevel > 0) {
5+
node.error(__filename + ": " + msg.toString());
6+
}
7+
}
8+
9+
function debugObject (obj) {
10+
if (exports.debugLevel > 0) {
11+
node.error(__filename + ": " + JSON.stringify(obj));
12+
}
13+
}
14+
15+
exports.File = function (filename, mode, options) {
16+
var self = this;
17+
18+
options = options || {};
19+
self.encoding = options.encoding || "utf8";
20+
21+
self.filename = filename;
22+
23+
self.actionQueue = [];
24+
self.currentAction = null;
25+
26+
switch (mode) {
27+
case "r":
28+
self.flags = node.O_RDONLY;
29+
break;
30+
31+
case "r+":
32+
self.flags = node.O_RDWR;
33+
break;
34+
35+
case "w":
36+
self.flags = node.O_CREAT | node.O_TRUNC | node.O_WRONLY;
37+
break;
38+
39+
case "w+":
40+
self.flags = node.O_CREAT | node.O_TRUNC | node.O_RDWR;
41+
break;
42+
43+
case "a":
44+
self.flags = node.O_APPEND | node.O_CREAT | node.O_WRONLY;
45+
break;
46+
47+
case "a+":
48+
self.flags = node.O_APPEND | node.O_CREAT | node.O_RDWR;
49+
break;
50+
51+
default:
52+
throw new Error("Unknown mode");
53+
}
54+
55+
self.open(self.filename, self.flags, 0666).addCallback(function (fd) {
56+
debugMessage(self.filename + " opened. fd = " + fd);
57+
self.fd = fd;
58+
}).addErrback(function () {
59+
self.emit("error", ["open"]);
60+
});
61+
};
62+
63+
var proto = exports.File.prototype;
64+
65+
proto._maybeDispatch = function () {
66+
var self = this;
67+
68+
if (self.currentAction) return;
69+
self.currentAction = self.actionQueue.shift();
70+
if (!self.currentAction) return;
71+
72+
debugObject(self.currentAction);
73+
74+
var args = self.currentAction.args || [];
75+
76+
if (self.currentAction.method != "open") {
77+
args.unshift(self.fd);
78+
}
79+
80+
var method = self.currentAction.method;
81+
82+
if (!args[3] && (method == "read" || method == "write")) {
83+
args[3] = self.encoding;
84+
}
85+
86+
var promise = node.fs[method].apply(self, args);
87+
88+
var userPromise = self.currentAction.promise;
89+
90+
promise.addCallback(function () {
91+
node.assert(self.currentAction.promise == userPromise);
92+
userPromise.emitSuccess.apply(userPromise, arguments);
93+
self.currentAction = null;
94+
self._maybeDispatch();
95+
}).addErrback(function () {
96+
debugMessage("Error in method " + method);
97+
node.assert(self.currentAction.promise == userPromise);
98+
userPromise.emitError.apply(userPromise, arguments);
99+
self.currentAction = null;
100+
self._maybeDispatch();
101+
});
102+
};
103+
104+
proto._queueAction = function (method, args) {
105+
var userPromise = new node.Promise;
106+
this.actionQueue.push({ method: method, args: args, promise: userPromise });
107+
this._maybeDispatch();
108+
return userPromise;
109+
};
110+
111+
// FIXME the following can probably be DRY'd up with some fancy getter
112+
// stuff.
113+
114+
proto.open = function (filename, flags, mode) {
115+
return this._queueAction("open", [filename, flags, mode]);
116+
};
117+
118+
proto.write = function (data, pos, encoding) {
119+
return this._queueAction("write", [data, pos, encoding]);
120+
};
121+
122+
proto.read = function (length, pos, encoding) {
123+
return this._queueAction("read", [length, pos, encoding]);
124+
};
125+
126+
proto.close = function () {
127+
return this._queueAction("close");
128+
};

test/mjsunit/test-buffered-file.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
include("common.js");
2+
3+
var testTxt = node.path.join(fixturesDir, "test.txt");
4+
5+
var libDir = node.path.join(testDir, "../../lib");
6+
node.libraryPaths.unshift(libDir);
7+
include("/file.js");
8+
9+
var fileUnlinked = false;
10+
11+
var file = new File(testTxt, "w+");
12+
file.write("hello\n");
13+
file.write("world\n");
14+
setTimeout(function () {
15+
file.write("hello\n");
16+
file.write("world\n");
17+
file.close().addCallback(function () {
18+
node.error("file closed...");
19+
var out = node.fs.cat(testTxt).wait();
20+
print("the file contains: ");
21+
p(out);
22+
assertEquals("hello\nworld\nhello\nworld\n", out);
23+
var file2 = new File(testTxt, "r");
24+
file2.read(5).addCallback(function (data) {
25+
puts("read(5): " + JSON.stringify(data));
26+
assertEquals("hello", data);
27+
node.fs.unlink(testTxt).addCallback(function () {
28+
fileUnlinked = true;
29+
});
30+
});
31+
file2.close();
32+
});
33+
}, 10);
34+
35+
process.addListener("exit", function () {
36+
assertTrue(fileUnlinked);
37+
puts("done");
38+
});

0 commit comments

Comments
 (0)