Skip to content
This repository has been archived by the owner. It is now read-only.
Permalink
Browse files

domains

Node must be invoked with --domains to use.
  • Loading branch information...
ry committed Sep 3, 2011
1 parent 12798c6 commit 8cfc680b348e64803365888fae698f5b9f6d4482
Showing with 375 additions and 50 deletions.
  1. +119 −0 lib/domain.js
  2. +60 −27 lib/fs.js
  3. +27 −8 lib/net_uv.js
  4. +30 −6 lib/timers_uv.js
  5. +1 −0 node.gyp
  6. +52 −8 src/node.cc
  7. +27 −1 src/node.js
  8. +59 −0 test/simple/test-domains.js
@@ -0,0 +1,119 @@
// Copyright Joyent, Inc. and other Node contributors.
//
// 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.

var assert = require('assert');
var EventEmitter = require('events').EventEmitter;
var util = require('util');

var currentDomain = null;
var defaultDomain = new Domain();
var createQueue = [];

var debug;
if (process.env.NODE_DEBUG && /domain/.test(process.env.NODE_DEBUG)) {
debug = function() { console.error.apply(this, arguments); };
} else {
debug = function() { };
}


function Domain() {
this.handles = [];
}
util.inherits(Domain, EventEmitter);



Domain.prototype.enter = function() {
assert.ok(!currentDomain);
currentDomain = this;
};


Domain.prototype.kill = function() {
for (var i = 0; i < this.handles.length; i++) {
debug("kill handle", this.handles[i]);
if (this.handles[i].close) {
this.handles[i].close();
} else {
this.handles[i].oncomplete = null;
}
}
this.handles = [];
};


Domain.prototype.exit = function() {
assert.ok(currentDomain == this);
currentDomain = null;

if (this.handles.length == 0) {
this.emit('exit');
}
};


exports.pollNewDomains = function() {
var d;
while ((d = createQueue.shift())) {
d.enter();

try {
d.cb(d.arg);
} catch (e) {
d.emit('error', e);
d.kill();
}

d.cb = null;
d.arg = null;
d.exit();
}
};



exports.add = function(handle) {
if (process.features.domains) {
debug("add handle", handle, "to domain", currentDomain);
currentDomain.handles.push(handle);
handle.domain = currentDomain;
}
};


exports.remove = function(handle) {
if (process.features.domains) {
// TODO do this in O(1)
assert.equal(currentDomain, handle.domain);
var i = currentDomain.handles.indexOf(handle);
currentDomain.handles.splice(i, 1);
}
};


exports.create = function(arg, cb) {
var d = new Domain();
d.cb = cb;
d.arg = arg;
createQueue.push(d);
return d;
};
@@ -26,10 +26,42 @@ var constants = process.binding('constants');
var fs = exports;
var Stream = require('stream').Stream;
var EventEmitter = require('events').EventEmitter;
var assert = require('assert');

var kMinPoolSpace = 128;
var kPoolSize = 40 * 1024;

function wrapReq(method /* , args */) {
// Make arguments an array starting at index 1. It should be nice if
// Array.prototype.slice.call(arguments, 1) was optimized by crankshaft.
var l = arguments.length;
var args = new Array(l - 1);
for (var i = 1; i < l; i++) {
args[i - 1] = arguments[i];
}

// If we're using domains, remove the req from the domain
// before making the final callback.
if (process.features.domains) {
assert.ok(l > 0);
var callback = args[l - 1];
args[l - 1] = function() {
// closeReq
require('domain').remove(req);
callback.call(this, arguments);
};
}

var req = binding[method].apply(binding, args);
if (process.features.domains) require('domain').add(req);
return req;
}

function closeReq(req) {
if (process.features.domains) require('domain').remove(req);
}


fs.Stats = binding.Stats;

fs.Stats.prototype._checkModeProperty = function(property) {
@@ -186,7 +218,7 @@ function noop() {}
// list to make the arguments clear.

fs.close = function(fd, callback) {
binding.close(fd, callback || noop);
return wrapReq("close", fd, callback || noop);
};

fs.closeSync = function(fd) {
@@ -214,7 +246,7 @@ fs.open = function(path, flags, mode, callback) {

mode = modeNum(mode, '0666');

binding.open(path, stringToFlags(flags), mode, callback);
return wrapReq("open", path, stringToFlags(flags), mode, callback);
};

fs.openSync = function(path, flags, mode) {
@@ -246,7 +278,7 @@ fs.read = function(fd, buffer, offset, length, position, callback) {
callback && callback(err, bytesRead || 0, buffer);
}

binding.read(fd, buffer, offset, length, position, wrapper);
return wrapReq("read", fd, buffer, offset, length, position, wrapper);
};

fs.readSync = function(fd, buffer, offset, length, position) {
@@ -296,7 +328,7 @@ fs.write = function(fd, buffer, offset, length, position, callback) {
callback && callback(err, written || 0, buffer);
}

binding.write(fd, buffer, offset, length, position, wrapper);
return wrapReq("write", fd, buffer, offset, length, position, wrapper);
};

fs.writeSync = function(fd, buffer, offset, length, position) {
@@ -314,79 +346,80 @@ fs.writeSync = function(fd, buffer, offset, length, position) {
};

fs.rename = function(oldPath, newPath, callback) {
binding.rename(oldPath, newPath, callback || noop);
return wrapReq("rename", oldPath, newPath, callback || noop);
};

fs.renameSync = function(oldPath, newPath) {
return binding.rename(oldPath, newPath);
};

fs.truncate = function(fd, len, callback) {
binding.truncate(fd, len, callback || noop);
return wrapReq("truncate", fd, len, callback || noop);
};

fs.truncateSync = function(fd, len) {
return binding.truncate(fd, len);
};

fs.rmdir = function(path, callback) {
binding.rmdir(path, callback || noop);
return wrapReq("rmdir", path, callback || noop);
};

fs.rmdirSync = function(path) {
return binding.rmdir(path);
};

fs.fdatasync = function(fd, callback) {
binding.fdatasync(fd, callback || noop);
return wrapReq("fdatasync", fd, callback || noop);
};

fs.fdatasyncSync = function(fd) {
return binding.fdatasync(fd);
};

fs.fsync = function(fd, callback) {
binding.fsync(fd, callback || noop);
return wrapReq("fsync", fd, callback || noop);
};

fs.fsyncSync = function(fd) {
return binding.fsync(fd);
};

fs.mkdir = function(path, mode, callback) {
binding.mkdir(path, modeNum(mode), callback || noop);
return wrapReq("mkdir", path, modeNum, mode, callback || noop);
};

fs.mkdirSync = function(path, mode) {
return binding.mkdir(path, modeNum(mode));
};

fs.sendfile = function(outFd, inFd, inOffset, length, callback) {
binding.sendfile(outFd, inFd, inOffset, length, callback || noop);
return wrapReq("sendfile", outFd, inFd, inOffset, length,
callback || noop);
};

fs.sendfileSync = function(outFd, inFd, inOffset, length) {
return binding.sendfile(outFd, inFd, inOffset, length);
};

fs.readdir = function(path, callback) {
binding.readdir(path, callback || noop);
return wrapReq("readdir", path, callback || noop);
};

fs.readdirSync = function(path) {
return binding.readdir(path);
};

fs.fstat = function(fd, callback) {
binding.fstat(fd, callback || noop);
return wrapReq("fstat", fd, callback || noop);
};

fs.lstat = function(path, callback) {
binding.lstat(path, callback || noop);
return wrapReq("lstat", path, callback || noop);
};

fs.stat = function(path, callback) {
binding.stat(path, callback || noop);
return wrapReq("stat", path, callback || noop);
};

fs.fstatSync = function(fd) {
@@ -402,7 +435,7 @@ fs.statSync = function(path) {
};

fs.readlink = function(path, callback) {
binding.readlink(path, callback || noop);
return wrapReq("readlink", path, callback || noop);
};

fs.readlinkSync = function(path) {
@@ -413,31 +446,31 @@ fs.symlink = function(destination, path, mode_, callback) {
var mode = (typeof(mode_) == 'string' ? mode_ : null);
var callback_ = arguments[arguments.length - 1];
var callback = (typeof(callback_) == 'function' ? callback_ : null);
binding.symlink(destination, path, mode, callback);
return wrapReq("symlink", destination, path, mode, callback);
};

fs.symlinkSync = function(destination, path, mode) {
return binding.symlink(destination, path, mode);
};

fs.link = function(srcpath, dstpath, callback) {
binding.link(srcpath, dstpath, callback || noop);
return wrapReq("link", srcpath, dstpath, callback || noop);
};

fs.linkSync = function(srcpath, dstpath) {
return binding.link(srcpath, dstpath);
};

fs.unlink = function(path, callback) {
binding.unlink(path, callback || noop);
return wrapReq("unlink", path, callback || noop);
};

fs.unlinkSync = function(path) {
return binding.unlink(path);
};

fs.fchmod = function(fd, mode, callback) {
binding.fchmod(fd, modeNum(mode), callback || noop);
return wrapReq("fchmod", fd, modeNum, mode, callback || noop);
};

fs.fchmodSync = function(fd, mode) {
@@ -464,7 +497,7 @@ if (constants.hasOwnProperty('O_SYMLINK')) {


fs.chmod = function(path, mode, callback) {
binding.chmod(path, modeNum(mode), callback || noop);
return wrapReq("chmod", path, modeNum, mode, callback || noop);
};

fs.chmodSync = function(path, mode) {
@@ -490,15 +523,15 @@ if (constants.hasOwnProperty('O_SYMLINK')) {
}

fs.fchown = function(fd, uid, gid, callback) {
binding.fchown(fd, uid, gid, callback || noop);
return wrapReq("fchown", fd, uid, gid, callback || noop);
};

fs.fchownSync = function(fd, uid, gid) {
return binding.fchown(fd, uid, gid);
};

fs.chown = function(path, uid, gid, callback) {
binding.chown(path, uid, gid, callback || noop);
return wrapReq("chown", path, uid, gid, callback || noop);
};

fs.chownSync = function(path, uid, gid) {
@@ -523,25 +556,25 @@ fs._toUnixTimestamp = toUnixTimestamp;
fs.utimes = function(path, atime, mtime, callback) {
atime = toUnixTimestamp(atime);
mtime = toUnixTimestamp(mtime);
binding.utimes(path, atime, mtime, callback || noop);
return wrapReq("utimes", path, atime, mtime, callback || noop);
};

fs.utimesSync = function(path, atime, mtime) {
atime = toUnixTimestamp(atime);
mtime = toUnixTimestamp(mtime);
binding.utimes(path, atime, mtime);
return binding.utimes(path, atime, mtime);
};

fs.futimes = function(fd, atime, mtime, callback) {
atime = toUnixTimestamp(atime);
mtime = toUnixTimestamp(mtime);
binding.futimes(fd, atime, mtime, callback || noop);
return wrapReq("futimes", fd, atime, mtime, callback || noop);
};

fs.futimesSync = function(fd, atime, mtime) {
atime = toUnixTimestamp(atime);
mtime = toUnixTimestamp(mtime);
binding.futimes(fd, atime, mtime);
return binding.futimes(fd, atime, mtime);
};

function writeAll(fd, buffer, offset, length, callback) {

0 comments on commit 8cfc680

Please sign in to comment.
You can’t perform that action at this time.