|
@ -61,15 +61,15 @@ cluster.isMaster = ! cluster.isWorker; |
|
|
|
|
|
|
|
|
// The worker object is only used in a worker
|
|
|
// The worker object is only used in a worker
|
|
|
cluster.worker = cluster.isWorker ? {} : null; |
|
|
cluster.worker = cluster.isWorker ? {} : null; |
|
|
// The workers array is oly used in the naster
|
|
|
// The workers array is only used in the master
|
|
|
cluster.workers = cluster.isMaster ? {} : null; |
|
|
cluster.workers = cluster.isMaster ? {} : null; |
|
|
|
|
|
|
|
|
// Settings object
|
|
|
// Settings object
|
|
|
var settings = cluster.settings = {}; |
|
|
var settings = cluster.settings = {}; |
|
|
|
|
|
|
|
|
// Simple function there call a function on each worker
|
|
|
// Simple function to call a function on each worker
|
|
|
function eachWorker(cb) { |
|
|
function eachWorker(cb) { |
|
|
// Go througe all workers
|
|
|
// Go through all workers
|
|
|
for (var id in cluster.workers) { |
|
|
for (var id in cluster.workers) { |
|
|
if (cluster.workers.hasOwnProperty(id)) { |
|
|
if (cluster.workers.hasOwnProperty(id)) { |
|
|
cb(cluster.workers[id]); |
|
|
cb(cluster.workers[id]); |
|
@ -94,7 +94,7 @@ cluster.setupMaster = function(options) { |
|
|
// This can only be called from the master.
|
|
|
// This can only be called from the master.
|
|
|
assert(cluster.isMaster); |
|
|
assert(cluster.isMaster); |
|
|
|
|
|
|
|
|
// Don't allow this function to run more that once
|
|
|
// Don't allow this function to run more than once
|
|
|
if (masterStarted) return; |
|
|
if (masterStarted) return; |
|
|
masterStarted = true; |
|
|
masterStarted = true; |
|
|
|
|
|
|
|
@ -121,7 +121,7 @@ function isInternalMessage(message) { |
|
|
message.cmd.indexOf(INTERNAL_PREFIX) === 0); |
|
|
message.cmd.indexOf(INTERNAL_PREFIX) === 0); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Modyfi message object to be internal
|
|
|
// Modify message object to be internal
|
|
|
function internalMessage(inMessage) { |
|
|
function internalMessage(inMessage) { |
|
|
var outMessage = util._extend({}, inMessage); |
|
|
var outMessage = util._extend({}, inMessage); |
|
|
|
|
|
|
|
@ -131,10 +131,10 @@ function internalMessage(inMessage) { |
|
|
return outMessage; |
|
|
return outMessage; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Handle callback messges
|
|
|
// Handle callback messages
|
|
|
function handleResponse(outMessage, outHandle, inMessage, inHandle, worker) { |
|
|
function handleResponse(outMessage, outHandle, inMessage, inHandle, worker) { |
|
|
|
|
|
|
|
|
// The message there will be send
|
|
|
// The message there will be sent
|
|
|
var message = internalMessage(outMessage); |
|
|
var message = internalMessage(outMessage); |
|
|
|
|
|
|
|
|
// callback id - will be undefined if not set
|
|
|
// callback id - will be undefined if not set
|
|
@ -146,7 +146,7 @@ function handleResponse(outMessage, outHandle, inMessage, inHandle, worker) { |
|
|
delete queryCallbacks[inMessage._queryEcho]; |
|
|
delete queryCallbacks[inMessage._queryEcho]; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Send if outWrap do contain something useful
|
|
|
// Send if outWrap contains something useful
|
|
|
if (!(outMessage === undefined && message._queryEcho === undefined)) { |
|
|
if (!(outMessage === undefined && message._queryEcho === undefined)) { |
|
|
sendInternalMessage(worker, message, outHandle); |
|
|
sendInternalMessage(worker, message, outHandle); |
|
|
} |
|
|
} |
|
@ -166,18 +166,18 @@ function handleMessage(worker, inMessage, inHandle) { |
|
|
handleResponse(outMessage, outHandler, inMessage, inHandle, worker); |
|
|
handleResponse(outMessage, outHandler, inMessage, inHandle, worker); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Run handler if it exist
|
|
|
// Run handler if it exists
|
|
|
if (messageHandler[message.cmd]) { |
|
|
if (messageHandler[message.cmd]) { |
|
|
messageHandler[message.cmd](message, worker, respond); |
|
|
messageHandler[message.cmd](message, worker, respond); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Send respond if it wasn't done
|
|
|
// Send respond if it hasn't been called yet
|
|
|
if (respondUsed === false) { |
|
|
if (respondUsed === false) { |
|
|
respond(); |
|
|
respond(); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Messages to the master will be handled using this methods
|
|
|
// Messages to the master will be handled using these methods
|
|
|
if (cluster.isMaster) { |
|
|
if (cluster.isMaster) { |
|
|
|
|
|
|
|
|
// Handle online messages from workers
|
|
|
// Handle online messages from workers
|
|
@ -188,11 +188,11 @@ if (cluster.isMaster) { |
|
|
cluster.emit('online', worker); |
|
|
cluster.emit('online', worker); |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
// Handle queryServer messages form workers
|
|
|
// Handle queryServer messages from workers
|
|
|
messageHandler.queryServer = function(message, worker, send) { |
|
|
messageHandler.queryServer = function(message, worker, send) { |
|
|
|
|
|
|
|
|
// This sequence of infomation is unique to the connection but not
|
|
|
// This sequence of information is unique to the connection
|
|
|
// to the worker
|
|
|
// but not to the worker
|
|
|
var args = [message.address, message.port, message.addressType]; |
|
|
var args = [message.address, message.port, message.addressType]; |
|
|
var key = args.join(':'); |
|
|
var key = args.join(':'); |
|
|
var handler; |
|
|
var handler; |
|
@ -212,7 +212,7 @@ if (cluster.isMaster) { |
|
|
|
|
|
|
|
|
worker.state = 'listening'; |
|
|
worker.state = 'listening'; |
|
|
|
|
|
|
|
|
// Emit listining, now that we know the worker is listning
|
|
|
// Emit listening, now that we know the worker is listening
|
|
|
worker.emit('listening', worker, { |
|
|
worker.emit('listening', worker, { |
|
|
address: message.address, |
|
|
address: message.address, |
|
|
port: message.port, |
|
|
port: message.port, |
|
@ -232,7 +232,7 @@ if (cluster.isMaster) { |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Messages to a worker will be handled using this methods
|
|
|
// Messages to a worker will be handled using these methods
|
|
|
else if (cluster.isWorker) { |
|
|
else if (cluster.isWorker) { |
|
|
|
|
|
|
|
|
// Handle worker.disconnect from master
|
|
|
// Handle worker.disconnect from master
|
|
@ -246,7 +246,7 @@ function toDecInt(value) { |
|
|
return isNaN(value) ? null : value; |
|
|
return isNaN(value) ? null : value; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Create a worker object, there works both for master and worker
|
|
|
// Create a worker object, that works both for master and worker
|
|
|
function Worker(customEnv) { |
|
|
function Worker(customEnv) { |
|
|
if (!(this instanceof Worker)) return new Worker(); |
|
|
if (!(this instanceof Worker)) return new Worker(); |
|
|
|
|
|
|
|
@ -379,7 +379,7 @@ Worker.prototype.destroy = function() { |
|
|
// Channel is open
|
|
|
// Channel is open
|
|
|
if (this.process.connected) { |
|
|
if (this.process.connected) { |
|
|
|
|
|
|
|
|
// Inform master that is is suicide and then kill
|
|
|
// Inform master to suicide and then kill
|
|
|
sendInternalMessage(this, {cmd: 'suicide'}, function() { |
|
|
sendInternalMessage(this, {cmd: 'suicide'}, function() { |
|
|
process.exit(0); |
|
|
process.exit(0); |
|
|
}); |
|
|
}); |
|
@ -394,8 +394,8 @@ Worker.prototype.destroy = function() { |
|
|
} |
|
|
} |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
// The .disconnect function will close all server and then disconnect
|
|
|
// The .disconnect function will close all servers
|
|
|
// the IPC channel.
|
|
|
// and then disconnect the IPC channel.
|
|
|
if (cluster.isMaster) { |
|
|
if (cluster.isMaster) { |
|
|
// Used in master
|
|
|
// Used in master
|
|
|
Worker.prototype.disconnect = function() { |
|
|
Worker.prototype.disconnect = function() { |
|
@ -414,7 +414,7 @@ if (cluster.isMaster) { |
|
|
// keep track of open servers
|
|
|
// keep track of open servers
|
|
|
var servers = Object.keys(serverListeners).length; |
|
|
var servers = Object.keys(serverListeners).length; |
|
|
var progress = new ProgressTracker(servers, function() { |
|
|
var progress = new ProgressTracker(servers, function() { |
|
|
// there are no more servers open so we will close the IPC channel.
|
|
|
// There are no more servers open so we will close the IPC channel.
|
|
|
// Closing the IPC channel will emit a disconnect event
|
|
|
// Closing the IPC channel will emit a disconnect event
|
|
|
// in both master and worker on the process object.
|
|
|
// in both master and worker on the process object.
|
|
|
// This event will be handled by prepareExit.
|
|
|
// This event will be handled by prepareExit.
|
|
@ -422,8 +422,8 @@ if (cluster.isMaster) { |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
// depending on where this function was called from (master or worker)
|
|
|
// depending on where this function was called from (master or worker)
|
|
|
// the suicide state has allready been set.
|
|
|
// The suicide state has already been set,
|
|
|
// But it dosn't really matter if we set it again.
|
|
|
// but it doesn't really matter if we set it again.
|
|
|
sendInternalMessage(this, {cmd: 'suicide'}, function() { |
|
|
sendInternalMessage(this, {cmd: 'suicide'}, function() { |
|
|
// in case there are no servers
|
|
|
// in case there are no servers
|
|
|
progress.check(); |
|
|
progress.check(); |
|
@ -433,7 +433,7 @@ if (cluster.isMaster) { |
|
|
for (var key in serverListeners) { |
|
|
for (var key in serverListeners) { |
|
|
server = serverListeners[key]; |
|
|
server = serverListeners[key]; |
|
|
|
|
|
|
|
|
// in case the server is closed we wont close it again
|
|
|
// in case the server is closed we won't close it again
|
|
|
if (server._handle === null) { |
|
|
if (server._handle === null) { |
|
|
progress.done(); |
|
|
progress.done(); |
|
|
continue; |
|
|
continue; |
|
@ -452,7 +452,7 @@ cluster.fork = function(env) { |
|
|
// This can only be called from the master.
|
|
|
// This can only be called from the master.
|
|
|
assert(cluster.isMaster); |
|
|
assert(cluster.isMaster); |
|
|
|
|
|
|
|
|
// Make sure that the master has been initalized
|
|
|
// Make sure that the master has been initialized
|
|
|
cluster.setupMaster(); |
|
|
cluster.setupMaster(); |
|
|
|
|
|
|
|
|
return (new cluster.Worker(env)); |
|
|
return (new cluster.Worker(env)); |
|
@ -481,7 +481,7 @@ cluster.disconnect = function(callback) { |
|
|
worker.disconnect(); |
|
|
worker.disconnect(); |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
// in case there wasn't any workers
|
|
|
// in case there weren't any workers
|
|
|
progress.check(); |
|
|
progress.check(); |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
@ -491,8 +491,8 @@ cluster._setupWorker = function() { |
|
|
// Get worker class
|
|
|
// Get worker class
|
|
|
var worker = cluster.worker = new Worker(); |
|
|
var worker = cluster.worker = new Worker(); |
|
|
|
|
|
|
|
|
// when the worker is disconnected from parent accidentally
|
|
|
|
|
|
// we will terminate the worker
|
|
|
// we will terminate the worker
|
|
|
|
|
|
// when the worker is disconnected from the parent accidentally
|
|
|
process.once('disconnect', function() { |
|
|
process.once('disconnect', function() { |
|
|
if (worker.suicide !== true) { |
|
|
if (worker.suicide !== true) { |
|
|
process.exit(0); |
|
|
process.exit(0); |
|
@ -532,7 +532,7 @@ cluster._getServer = function(tcpSelf, address, port, addressType, cb) { |
|
|
addressType: addressType |
|
|
addressType: addressType |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
// The callback will be stored until the master has responed
|
|
|
// The callback will be stored until the master has responded
|
|
|
sendInternalMessage(cluster.worker, message, function(msg, handle) { |
|
|
sendInternalMessage(cluster.worker, message, function(msg, handle) { |
|
|
cb(handle); |
|
|
cb(handle); |
|
|
}); |
|
|
}); |
|
|