|
var Long = require('bson').Long;
/**
Reply message from mongo db
**/
var MongoReply = exports.MongoReply = function() {
this.documents = [];
this.index = 0;
};
MongoReply.prototype.parseHeader = function(binary_reply, bson) {
// Unpack the standard header first
this.messageLength = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24;
this.index = this.index + 4;
// Fetch the request id for this reply
this.requestId = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24;
this.index = this.index + 4;
// Fetch the id of the request that triggered the response
this.responseTo = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24;
// Skip op-code field
this.index = this.index + 4 + 4;
// Unpack the reply message
this.responseFlag = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24;
this.index = this.index + 4;
// Unpack the cursor id (a 64 bit long integer)
var low_bits = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24;
this.index = this.index + 4;
var high_bits = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24;
this.index = this.index + 4;
this.cursorId = new Long(low_bits, high_bits);
// Unpack the starting from
this.startingFrom = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24;
this.index = this.index + 4;
// Unpack the number of objects returned
this.numberReturned = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24;
this.index = this.index + 4;
}
MongoReply.prototype.parseBody = function(binary_reply, bson, raw, callback) {
raw = raw == null ? false : raw;
// Just set a doc limit for deserializing
var docLimitSize = 1024*20;
// If our message length is very long, let's switch to process.nextTick for messages
if(this.messageLength > docLimitSize) {
var batchSize = this.numberReturned;
this.documents = new Array(this.numberReturned);
// Just walk down until we get a positive number >= 1
for(var i = 50; i > 0; i--) {
if((this.numberReturned/i) >= 1) {
batchSize = i;
break;
}
}
// Actual main creator of the processFunction setting internal state to control the flow
var parseFunction = function(_self, _binary_reply, _batchSize, _numberReturned) {
var object_index = 0;
// Internal loop process that will use nextTick to ensure we yield some time
var processFunction = function() {
// Adjust batchSize if we have less results left than batchsize
if((_numberReturned - object_index) < _batchSize) {
_batchSize = _numberReturned - object_index;
}
// If raw just process the entries
if(raw) {
// Iterate over the batch
for(var i = 0; i < _batchSize; i++) {
// Are we done ?
if(object_index <= _numberReturned) {
// Read the size of the bson object
var bsonObjectSize = _binary_reply[_self.index] | _binary_reply[_self.index + 1] << 8 | _binary_reply[_self.index + 2] << 16 | _binary_reply[_self.index + 3] << 24;
// If we are storing the raw responses to pipe straight through
_self.documents[object_index] = binary_reply.slice(_self.index, _self.index + bsonObjectSize);
// Adjust binary index to point to next block of binary bson data
_self.index = _self.index + bsonObjectSize;
// Update number of docs parsed
object_index = object_index + 1;
}
}
} else {
try {
// Parse documents
_self.index = bson.deserializeStream(binary_reply, _self.index, _batchSize, _self.documents, object_index);
// Adjust index
object_index = object_index + _batchSize;
} catch (err) {
return callback(err);
}
}
// If we hav more documents process NextTick
if(object_index < _numberReturned) {
process.nextTick(processFunction);
} else {
callback(null);
}
}
// Return the process function
return processFunction;
}(this, binary_reply, batchSize, this.numberReturned)();
} else {
try {
// Let's unpack all the bson documents, deserialize them and store them
for(var object_index = 0; object_index < this.numberReturned; object_index++) {
// Read the size of the bson object
var bsonObjectSize = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24;
// If we are storing the raw responses to pipe straight through
if(raw) {
// Deserialize the object and add to the documents array
this.documents.push(binary_reply.slice(this.index, this.index + bsonObjectSize));
} else {
// Deserialize the object and add to the documents array
this.documents.push(bson.deserialize(binary_reply.slice(this.index, this.index + bsonObjectSize)));
}
// Adjust binary index to point to next block of binary bson data
this.index = this.index + bsonObjectSize;
}
} catch(err) {
return callback(err);
}
// No error return
callback(null);
}
}
MongoReply.prototype.is_error = function(){
if(this.documents.length == 1) {
return this.documents[0].ok == 1 ? false : true;
}
return false;
};
MongoReply.prototype.error_message = function() {
return this.documents.length == 1 && this.documents[0].ok == 1 ? '' : this.documents[0].errmsg;
};
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
I currently hold the following qualifications (amongst others, I also studied Music Technology and Electronics, for my sins)
- MSc (Passed with distinctions), in Information Technology for E-Commerce
- BSc Hons (1st class) in Computer Science & Artificial Intelligence
Both of these at Sussex University UK.
Award(s)
I am lucky enough to have won a few awards for Zany Crazy code articles over the years
- Microsoft C# MVP 2016
- Codeproject MVP 2016
- Microsoft C# MVP 2015
- Codeproject MVP 2015
- Microsoft C# MVP 2014
- Codeproject MVP 2014
- Microsoft C# MVP 2013
- Codeproject MVP 2013
- Microsoft C# MVP 2012
- Codeproject MVP 2012
- Microsoft C# MVP 2011
- Codeproject MVP 2011
- Microsoft C# MVP 2010
- Codeproject MVP 2010
- Microsoft C# MVP 2009
- Codeproject MVP 2009
- Microsoft C# MVP 2008
- Codeproject MVP 2008
- And numerous codeproject awards which you can see over at my blog