Moving the http.js, net.js FreeList to being standalone.
This commit is contained in:
parent
b7947e45c0
commit
57ea07ac91
22
lib/freelist.js
Normal file
22
lib/freelist.js
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// This is a free list to avoid creating so many of the same object.
|
||||||
|
exports.FreeList = function(name, max, constructor) {
|
||||||
|
this.name = name;
|
||||||
|
this.constructor = constructor;
|
||||||
|
this.max = max;
|
||||||
|
this.list = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
exports.FreeList.prototype.alloc = function () {
|
||||||
|
//debug("alloc " + this.name + " " + this.list.length);
|
||||||
|
return this.list.length ? this.list.shift()
|
||||||
|
: this.constructor.apply(this, arguments);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
exports.FreeList.prototype.free = function (obj) {
|
||||||
|
//debug("free " + this.name + " " + this.list.length);
|
||||||
|
if (this.list.length < this.max) {
|
||||||
|
this.list.push(obj);
|
||||||
|
}
|
||||||
|
};
|
162
lib/http.js
162
lib/http.js
@ -11,101 +11,91 @@ var sys = require('sys');
|
|||||||
var net = require('net');
|
var net = require('net');
|
||||||
var events = require('events');
|
var events = require('events');
|
||||||
|
|
||||||
|
var FreeList = require('freelist').FreeList;
|
||||||
var HTTPParser = process.binding('http_parser').HTTPParser;
|
var HTTPParser = process.binding('http_parser').HTTPParser;
|
||||||
|
|
||||||
var parserFreeList = [];
|
var parsers = new FreeList('parsers', 1000, function () {
|
||||||
|
var parser = new HTTPParser('request');
|
||||||
|
|
||||||
function newParser (type) {
|
parser.onMessageBegin = function () {
|
||||||
var parser;
|
parser.incoming = new IncomingMessage(parser.socket);
|
||||||
if (parserFreeList.length) {
|
parser.field = null;
|
||||||
parser = parserFreeList.shift();
|
parser.value = null;
|
||||||
parser.reinitialize(type);
|
};
|
||||||
} else {
|
|
||||||
parser = new HTTPParser(type);
|
|
||||||
|
|
||||||
parser.onMessageBegin = function () {
|
// Only servers will get URL events.
|
||||||
parser.incoming = new IncomingMessage(parser.socket);
|
parser.onURL = function (b, start, len) {
|
||||||
|
var slice = b.toString('ascii', start, start+len);
|
||||||
|
if (parser.incoming.url) {
|
||||||
|
parser.incoming.url += slice;
|
||||||
|
} else {
|
||||||
|
// Almost always will branch here.
|
||||||
|
parser.incoming.url = slice;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
parser.onHeaderField = function (b, start, len) {
|
||||||
|
var slice = b.toString('ascii', start, start+len).toLowerCase();
|
||||||
|
if (parser.value) {
|
||||||
|
parser.incoming._addHeaderLine(parser.field, parser.value);
|
||||||
parser.field = null;
|
parser.field = null;
|
||||||
parser.value = null;
|
parser.value = null;
|
||||||
};
|
}
|
||||||
|
if (parser.field) {
|
||||||
|
parser.field += slice;
|
||||||
|
} else {
|
||||||
|
parser.field = slice;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Only servers will get URL events.
|
parser.onHeaderValue = function (b, start, len) {
|
||||||
parser.onURL = function (b, start, len) {
|
var slice = b.toString('ascii', start, start+len);
|
||||||
var slice = b.toString('ascii', start, start+len);
|
if (parser.value) {
|
||||||
if (parser.incoming.url) {
|
parser.value += slice;
|
||||||
parser.incoming.url += slice;
|
} else {
|
||||||
} else {
|
parser.value = slice;
|
||||||
// Almost always will branch here.
|
}
|
||||||
parser.incoming.url = slice;
|
};
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
parser.onHeaderField = function (b, start, len) {
|
parser.onHeadersComplete = function (info) {
|
||||||
var slice = b.toString('ascii', start, start+len).toLowerCase();
|
if (parser.field && parser.value) {
|
||||||
if (parser.value) {
|
parser.incoming._addHeaderLine(parser.field, parser.value);
|
||||||
parser.incoming._addHeaderLine(parser.field, parser.value);
|
}
|
||||||
parser.field = null;
|
|
||||||
parser.value = null;
|
|
||||||
}
|
|
||||||
if (parser.field) {
|
|
||||||
parser.field += slice;
|
|
||||||
} else {
|
|
||||||
parser.field = slice;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
parser.onHeaderValue = function (b, start, len) {
|
parser.incoming.httpVersionMajor = info.versionMajor;
|
||||||
var slice = b.toString('ascii', start, start+len);
|
parser.incoming.httpVersionMinor = info.versionMinor;
|
||||||
if (parser.value) {
|
parser.incoming.httpVersion = info.versionMajor
|
||||||
parser.value += slice;
|
+ '.'
|
||||||
} else {
|
+ info.versionMinor ;
|
||||||
parser.value = slice;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
parser.onHeadersComplete = function (info) {
|
if (info.method) {
|
||||||
if (parser.field && parser.value) {
|
// server only
|
||||||
parser.incoming._addHeaderLine(parser.field, parser.value);
|
parser.incoming.method = info.method;
|
||||||
}
|
} else {
|
||||||
|
// client only
|
||||||
|
parser.incoming.statusCode = info.statusCode;
|
||||||
|
}
|
||||||
|
|
||||||
parser.incoming.httpVersionMajor = info.versionMajor;
|
parser.onIncoming(parser.incoming, info.shouldKeepAlive);
|
||||||
parser.incoming.httpVersionMinor = info.versionMinor;
|
};
|
||||||
parser.incoming.httpVersion = info.versionMajor
|
|
||||||
+ '.'
|
|
||||||
+ info.versionMinor ;
|
|
||||||
|
|
||||||
if (info.method) {
|
parser.onBody = function (b, start, len) {
|
||||||
// server only
|
// TODO body encoding?
|
||||||
parser.incoming.method = info.method;
|
var enc = parser.incoming._encoding;
|
||||||
} else {
|
if (!enc) {
|
||||||
// client only
|
parser.incoming.emit('data', b.slice(start, start+len));
|
||||||
parser.incoming.statusCode = info.statusCode;
|
} else {
|
||||||
}
|
var string = b.toString(enc, start, start+len);
|
||||||
|
parser.incoming.emit('data', string);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
parser.onIncoming(parser.incoming, info.shouldKeepAlive);
|
parser.onMessageComplete = function () {
|
||||||
};
|
parser.incoming.emit("end");
|
||||||
|
};
|
||||||
|
|
||||||
parser.onBody = function (b, start, len) {
|
|
||||||
// TODO body encoding?
|
|
||||||
var enc = parser.incoming._encoding;
|
|
||||||
if (!enc) {
|
|
||||||
parser.incoming.emit('data', b.slice(start, start+len));
|
|
||||||
} else {
|
|
||||||
var string = b.toString(enc, start, start+len);
|
|
||||||
parser.incoming.emit('data', string);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
parser.onMessageComplete = function () {
|
|
||||||
parser.incoming.emit("end");
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return parser;
|
return parser;
|
||||||
}
|
});
|
||||||
|
|
||||||
function freeParser (parser) {
|
|
||||||
if (parserFreeList.length < 1000) parserFreeList.push(parser);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var CRLF = "\r\n";
|
var CRLF = "\r\n";
|
||||||
@ -517,7 +507,9 @@ function connectionListener (socket) {
|
|||||||
// we need to keep track of the order they were sent.
|
// we need to keep track of the order they were sent.
|
||||||
var responses = [];
|
var responses = [];
|
||||||
|
|
||||||
var parser = newParser('request');
|
var parser = parsers.alloc();
|
||||||
|
parser.reinitialize('request');
|
||||||
|
parser.socket = socket;
|
||||||
|
|
||||||
socket.ondata = function (d, start, end) {
|
socket.ondata = function (d, start, end) {
|
||||||
parser.execute(d, start, end - start);
|
parser.execute(d, start, end - start);
|
||||||
@ -526,7 +518,7 @@ function connectionListener (socket) {
|
|||||||
socket.onend = function () {
|
socket.onend = function () {
|
||||||
parser.finish();
|
parser.finish();
|
||||||
// unref the parser for easy gc
|
// unref the parser for easy gc
|
||||||
freeParser(parser);
|
parsers.free(parser);
|
||||||
|
|
||||||
if (responses.length == 0) {
|
if (responses.length == 0) {
|
||||||
socket.end();
|
socket.end();
|
||||||
@ -535,7 +527,6 @@ function connectionListener (socket) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
parser.socket = socket;
|
|
||||||
// The following callback is issued after the headers have been read on a
|
// The following callback is issued after the headers have been read on a
|
||||||
// new message. In this callback we setup the response object and pass it
|
// new message. In this callback we setup the response object and pass it
|
||||||
// to the user.
|
// to the user.
|
||||||
@ -563,7 +554,8 @@ function Client ( ) {
|
|||||||
var requests = [];
|
var requests = [];
|
||||||
var currentRequest;
|
var currentRequest;
|
||||||
|
|
||||||
var parser = newParser('response');
|
var parser = parsers.alloc();
|
||||||
|
parser.reinitialize('response');
|
||||||
parser.socket = this;
|
parser.socket = this;
|
||||||
|
|
||||||
self._reconnect = function () {
|
self._reconnect = function () {
|
||||||
@ -617,7 +609,7 @@ function Client ( ) {
|
|||||||
if (requests.length > 0) {
|
if (requests.length > 0) {
|
||||||
self._reconnect();
|
self._reconnect();
|
||||||
} else {
|
} else {
|
||||||
freeParser(parser);
|
parsers.free(parser);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
30
lib/net.js
30
lib/net.js
@ -22,6 +22,7 @@ var binding = process.binding('net');
|
|||||||
// yet convinced that every use-case can be fit into that abstraction, so
|
// yet convinced that every use-case can be fit into that abstraction, so
|
||||||
// waiting to implement it until I get more experience with this.
|
// waiting to implement it until I get more experience with this.
|
||||||
var Buffer = require('buffer').Buffer;
|
var Buffer = require('buffer').Buffer;
|
||||||
|
var FreeList = require('freelist').FreeList;
|
||||||
|
|
||||||
var IOWatcher = process.IOWatcher;
|
var IOWatcher = process.IOWatcher;
|
||||||
var assert = process.assert;
|
var assert = process.assert;
|
||||||
@ -205,35 +206,6 @@ var timeout = new (function () {
|
|||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// This is a free list to avoid creating so many of the same object.
|
|
||||||
|
|
||||||
function FreeList (name, max, constructor) {
|
|
||||||
this.name = name;
|
|
||||||
this.constructor = constructor;
|
|
||||||
this.max = max;
|
|
||||||
this.list = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
FreeList.prototype.alloc = function () {
|
|
||||||
//debug("alloc " + this.name + " " + this.list.length);
|
|
||||||
return this.list.length ? this.list.shift()
|
|
||||||
: this.constructor.apply(this, arguments);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
FreeList.prototype.free = function (obj) {
|
|
||||||
//debug("free " + this.name + " " + this.list.length);
|
|
||||||
if (this.list.length < this.max) {
|
|
||||||
this.list.push(obj);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
var ioWatchers = new FreeList("iowatcher", 100, function () {
|
var ioWatchers = new FreeList("iowatcher", 100, function () {
|
||||||
return new IOWatcher();
|
return new IOWatcher();
|
||||||
});
|
});
|
||||||
|
@ -1268,6 +1268,7 @@ static Handle<Value> Binding(const Arguments& args) {
|
|||||||
exports->Set(String::New("dns"), String::New(native_dns));
|
exports->Set(String::New("dns"), String::New(native_dns));
|
||||||
exports->Set(String::New("events"), String::New(native_events));
|
exports->Set(String::New("events"), String::New(native_events));
|
||||||
exports->Set(String::New("file"), String::New(native_file));
|
exports->Set(String::New("file"), String::New(native_file));
|
||||||
|
exports->Set(String::New("freelist"), String::New(native_freelist));
|
||||||
exports->Set(String::New("fs"), String::New(native_fs));
|
exports->Set(String::New("fs"), String::New(native_fs));
|
||||||
exports->Set(String::New("http"), String::New(native_http));
|
exports->Set(String::New("http"), String::New(native_http));
|
||||||
exports->Set(String::New("http_old"), String::New(native_http_old));
|
exports->Set(String::New("http_old"), String::New(native_http_old));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user