Browse Source

Moving the http.js, net.js FreeList to being standalone.

v0.7.4-release
Micheil Smith 15 years ago
committed by Ryan Dahl
parent
commit
57ea07ac91
  1. 22
      lib/freelist.js
  2. 162
      lib/http.js
  3. 30
      lib/net.js
  4. 1
      src/node.cc

22
lib/freelist.js

@ -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

@ -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); // Only servers will get URL events.
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.onMessageBegin = function () { parser.onHeaderField = function (b, start, len) {
parser.incoming = new IncomingMessage(parser.socket); 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) {
var slice = b.toString('ascii', start, start+len).toLowerCase();
if (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.onHeadersComplete = function (info) {
var slice = b.toString('ascii', start, start+len); if (parser.field && parser.value) {
if (parser.value) { parser.incoming._addHeaderLine(parser.field, parser.value);
parser.value += slice; }
} else {
parser.value = slice;
}
};
parser.onHeadersComplete = function (info) { parser.incoming.httpVersionMajor = info.versionMajor;
if (parser.field && parser.value) { parser.incoming.httpVersionMinor = info.versionMinor;
parser.incoming._addHeaderLine(parser.field, parser.value); parser.incoming.httpVersion = info.versionMajor
} + '.'
+ info.versionMinor ;
parser.incoming.httpVersionMajor = info.versionMajor; if (info.method) {
parser.incoming.httpVersionMinor = info.versionMinor; // server only
parser.incoming.httpVersion = info.versionMajor parser.incoming.method = info.method;
+ '.' } else {
+ info.versionMinor ; // client only
parser.incoming.statusCode = info.statusCode;
}
if (info.method) { parser.onIncoming(parser.incoming, info.shouldKeepAlive);
// server only };
parser.incoming.method = info.method;
} else {
// client only
parser.incoming.statusCode = info.statusCode;
}
parser.onIncoming(parser.incoming, info.shouldKeepAlive); 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.onBody = function (b, start, len) { parser.onMessageComplete = function () {
// TODO body encoding? parser.incoming.emit("end");
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

@ -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();
}); });

1
src/node.cc

@ -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…
Cancel
Save