UNPKG

nodulator

Version:

Complete NodeJS Framework for Restfull APIs

526 lines (480 loc) 19.4 kB
var BinaryParser = require('./bson/binary_parser').BinaryParser; var BSON = require('./bson/bson').BSON; var OrderedHash = require('./bson/collections').OrderedHash; /** Base object used for common functionality **/ var Commands = exports.Commands = function() { return (this).Commands }; insert = function(c) { // Calculate total length of the document var totalLengthOfCommand = 4 + Buffer.byteLength(c.collectionName) + 1 + (4 * 4); // var docLength = 0 for(var i = 0; i < c.documents.length; i++) { // Calculate size of document totalLengthOfCommand += BSON.calculateObjectSize(c.documents[i]); } // Let's build the single pass buffer command var _index = 0; var _command = new Buffer(totalLengthOfCommand); // Write the header information to the buffer _command[_index + 3] = (totalLengthOfCommand >> 24) & 0xff; _command[_index + 2] = (totalLengthOfCommand >> 16) & 0xff; _command[_index + 1] = (totalLengthOfCommand >> 8) & 0xff; _command[_index] = totalLengthOfCommand & 0xff; // Adjust index _index = _index + 4; // Write the request ID _command[_index + 3] = (c.requestId >> 24) & 0xff; _command[_index + 2] = (c.requestId >> 16) & 0xff; _command[_index + 1] = (c.requestId >> 8) & 0xff; _command[_index] = c.requestId & 0xff; // Adjust index _index = _index + 4; // Write zero _command[_index++] = 0; _command[_index++] = 0; _command[_index++] = 0; _command[_index++] = 0; // Write the op_code for the command _command[_index + 3] = (Commands.OP_INSERT >> 24) & 0xff; _command[_index + 2] = (Commands.OP_INSERT >> 16) & 0xff; _command[_index + 1] = (Commands.OP_INSERT >> 8) & 0xff; _command[_index] = Commands.OP_INSERT & 0xff; // Adjust index _index = _index + 4; // Write zero _command[_index++] = 0; _command[_index++] = 0; _command[_index++] = 0; _command[_index++] = 0; // Write the collection name to the command _index = _index + _command.write(c.collectionName, _index, 'utf8') + 1; _command[_index - 1] = 0; // Write all the bson documents to the buffer at the index offset for(var i = 0; i < c.documents.length; i++) { // Serialize the document straight to the buffer var documentLength = BSON.serializeWithBufferAndIndex(c.documents[i], c.checkKeys, _command, _index) - _index + 1; // Write the length to the document _command[_index + 3] = (documentLength >> 24) & 0xff; _command[_index + 2] = (documentLength >> 16) & 0xff; _command[_index + 1] = (documentLength >> 8) & 0xff; _command[_index] = documentLength & 0xff; // Update index in buffer _index = _index + documentLength; // Add terminating 0 for the object _command[_index - 1] = 0; } return _command; }; more = function(c) { // debug("======================================================= GETMORE") // debug("================ " + BSON.calculateObjectSize(c.query)) // Calculate total length of the document var totalLengthOfCommand = 4 + Buffer.byteLength(c.collectionName) + 1 + 4 + 8 + (4 * 4); // Let's build the single pass buffer command var _index = 0; var _command = new Buffer(totalLengthOfCommand); // Write the header information to the buffer _command[_index + 3] = (totalLengthOfCommand >> 24) & 0xff; _command[_index + 2] = (totalLengthOfCommand >> 16) & 0xff; _command[_index + 1] = (totalLengthOfCommand >> 8) & 0xff; _command[_index] = totalLengthOfCommand & 0xff; // Adjust index _index = _index + 4; // Write the request ID _command[_index + 3] = (c.requestId >> 24) & 0xff; _command[_index + 2] = (c.requestId >> 16) & 0xff; _command[_index + 1] = (c.requestId >> 8) & 0xff; _command[_index] = c.requestId & 0xff; // Adjust index _index = _index + 4; // Write zero _command[_index++] = 0; _command[_index++] = 0; _command[_index++] = 0; _command[_index++] = 0; // Write the op_code for the command _command[_index + 3] = (Commands.OP_GET_MORE >> 24) & 0xff; _command[_index + 2] = (Commands.OP_GET_MORE >> 16) & 0xff; _command[_index + 1] = (Commands.OP_GET_MORE >> 8) & 0xff; _command[_index] = Commands.OP_GET_MORE & 0xff; // Adjust index _index = _index + 4; // Write zero _command[_index++] = 0; _command[_index++] = 0; _command[_index++] = 0; _command[_index++] = 0; // Write the collection name to the command _index = _index + _command.write(c.collectionName, _index, 'utf8') + 1; _command[_index - 1] = 0; // Number of documents to return _command[_index + 3] = (c.numberToReturn >> 24) & 0xff; _command[_index + 2] = (c.numberToReturn >> 16) & 0xff; _command[_index + 1] = (c.numberToReturn >> 8) & 0xff; _command[_index] = c.numberToReturn & 0xff; // Adjust index _index = _index + 4; // Encode the cursor id var low_bits = c.cursorID.getLowBits(); // Encode low bits _command[_index + 3] = (low_bits >> 24) & 0xff; _command[_index + 2] = (low_bits >> 16) & 0xff; _command[_index + 1] = (low_bits >> 8) & 0xff; _command[_index] = low_bits & 0xff; // Adjust index _index = _index + 4; var high_bits = c.cursorID.getHighBits(); // Encode high bits _command[_index + 3] = (high_bits >> 24) & 0xff; _command[_index + 2] = (high_bits >> 16) & 0xff; _command[_index + 1] = (high_bits >> 8) & 0xff; _command[_index] = high_bits & 0xff; // Adjust index _index = _index + 4; return _command; }; kill = function(c) { // Calculate total length of the document var totalLengthOfCommand = 4 + 4 + (4 * 4) + (c.cursorIDs.length * 8); // Let's build the single pass buffer command var _index = 0; var _command = new Buffer(totalLengthOfCommand); // Write the header information to the buffer _command[_index + 3] = (totalLengthOfCommand >> 24) & 0xff; _command[_index + 2] = (totalLengthOfCommand >> 16) & 0xff; _command[_index + 1] = (totalLengthOfCommand >> 8) & 0xff; _command[_index] = totalLengthOfCommand & 0xff; // Adjust index _index = _index + 4; // Write the request ID _command[_index + 3] = (c.requestId >> 24) & 0xff; _command[_index + 2] = (c.requestId >> 16) & 0xff; _command[_index + 1] = (c.requestId >> 8) & 0xff; _command[_index] = c.requestId & 0xff; // Adjust index _index = _index + 4; // Write zero _command[_index++] = 0; _command[_index++] = 0; _command[_index++] = 0; _command[_index++] = 0; // Write the op_code for the command _command[_index + 3] = (Commands.OP_KILL_CURSORS >> 24) & 0xff; _command[_index + 2] = (Commands.OP_KILL_CURSORS >> 16) & 0xff; _command[_index + 1] = (Commands.OP_KILL_CURSORS >> 8) & 0xff; _command[_index] = Commands.OP_KILL_CURSORS & 0xff; // Adjust index _index = _index + 4; // Write zero _command[_index++] = 0; _command[_index++] = 0; _command[_index++] = 0; _command[_index++] = 0; // Number of cursors to kill var numberOfCursors = c.cursorIDs.length; _command[_index + 3] = (numberOfCursors >> 24) & 0xff; _command[_index + 2] = (numberOfCursors >> 16) & 0xff; _command[_index + 1] = (numberOfCursors >> 8) & 0xff; _command[_index] = numberOfCursors & 0xff; // Adjust index _index = _index + 4; // Encode all the cursors for(var i = 0; i < c.cursorIDs.length; i++) { // Encode the cursor id var low_bits = c.cursorIDs[i].getLowBits(); // Encode low bits _command[_index + 3] = (low_bits >> 24) & 0xff; _command[_index + 2] = (low_bits >> 16) & 0xff; _command[_index + 1] = (low_bits >> 8) & 0xff; _command[_index] = low_bits & 0xff; // Adjust index _index = _index + 4; var high_bits = c.cursorIDs[i].getHighBits(); // Encode high bits _command[_index + 3] = (high_bits >> 24) & 0xff; _command[_index + 2] = (high_bits >> 16) & 0xff; _command[_index + 1] = (high_bits >> 8) & 0xff; _command[_index] = high_bits & 0xff; // Adjust index _index = _index + 4; } return _command; }; update = function(c) { // Calculate total length of the document var totalLengthOfCommand = 4 + Buffer.byteLength(c.collectionName) + 1 + 4 + BSON.calculateObjectSize(c.spec) + BSON.calculateObjectSize(c.document) + (4 * 4); // Let's build the single pass buffer command var _index = 0; var _command = new Buffer(totalLengthOfCommand); // Write the header information to the buffer _command[_index + 3] = (totalLengthOfCommand >> 24) & 0xff; _command[_index + 2] = (totalLengthOfCommand >> 16) & 0xff; _command[_index + 1] = (totalLengthOfCommand >> 8) & 0xff; _command[_index] = totalLengthOfCommand & 0xff; // Adjust index _index = _index + 4; // Write the request ID _command[_index + 3] = (c.requestId >> 24) & 0xff; _command[_index + 2] = (c.requestId >> 16) & 0xff; _command[_index + 1] = (c.requestId >> 8) & 0xff; _command[_index] = c.requestId & 0xff; // Adjust index _index = _index + 4; // Write zero _command[_index++] = 0; _command[_index++] = 0; _command[_index++] = 0; _command[_index++] = 0; // Write the op_code for the command _command[_index + 3] = (Commands.OP_UPDATE >> 24) & 0xff; _command[_index + 2] = (Commands.OP_UPDATE >> 16) & 0xff; _command[_index + 1] = (Commands.OP_UPDATE >> 8) & 0xff; _command[_index] = Commands.OP_UPDATE & 0xff; // Adjust index _index = _index + 4; // Write zero _command[_index++] = 0; _command[_index++] = 0; _command[_index++] = 0; _command[_index++] = 0; // Write the collection name to the command _index = _index + _command.write(c.collectionName, _index, 'utf8') + 1; _command[_index - 1] = 0; // Write the update flags _command[_index + 3] = (c.flags >> 24) & 0xff; _command[_index + 2] = (c.flags >> 16) & 0xff; _command[_index + 1] = (c.flags >> 8) & 0xff; _command[_index] = c.flags & 0xff; // Adjust index _index = _index + 4; // Serialize the spec document var documentLength = BSON.serializeWithBufferAndIndex(c.spec, c.checkKeys, _command, _index) - _index + 1; // Write the length to the document _command[_index + 3] = (documentLength >> 24) & 0xff; _command[_index + 2] = (documentLength >> 16) & 0xff; _command[_index + 1] = (documentLength >> 8) & 0xff; _command[_index] = documentLength & 0xff; // Update index in buffer _index = _index + documentLength; // Add terminating 0 for the object _command[_index - 1] = 0; // Serialize the document var documentLength = BSON.serializeWithBufferAndIndex(c.document, c.checkKeys, _command, _index) - _index + 1; // Write the length to the document _command[_index + 3] = (documentLength >> 24) & 0xff; _command[_index + 2] = (documentLength >> 16) & 0xff; _command[_index + 1] = (documentLength >> 8) & 0xff; _command[_index] = documentLength & 0xff; // Update index in buffer _index = _index + documentLength; // Add terminating 0 for the object _command[_index - 1] = 0; return _command; }; remove = function(c) { // Calculate total length of the document var totalLengthOfCommand = 4 + Buffer.byteLength(c.collectionName) + 1 + 4 + BSON.calculateObjectSize(c.spec||c.selector) + (4 * 4); // Let's build the single pass buffer command var _index = 0; var _command = new Buffer(totalLengthOfCommand); // Write the header information to the buffer _command[_index + 3] = (totalLengthOfCommand >> 24) & 0xff; _command[_index + 2] = (totalLengthOfCommand >> 16) & 0xff; _command[_index + 1] = (totalLengthOfCommand >> 8) & 0xff; _command[_index] = totalLengthOfCommand & 0xff; // Adjust index _index = _index + 4; // Write the request ID _command[_index + 3] = (c.requestId >> 24) & 0xff; _command[_index + 2] = (c.requestId >> 16) & 0xff; _command[_index + 1] = (c.requestId >> 8) & 0xff; _command[_index] = c.requestId & 0xff; // Adjust index _index = _index + 4; // Write zero _command[_index++] = 0; _command[_index++] = 0; _command[_index++] = 0; _command[_index++] = 0; // Write the op_code for the command _command[_index + 3] = (Commands.OP_DELETE >> 24) & 0xff; _command[_index + 2] = (Commands.OP_DELETE >> 16) & 0xff; _command[_index + 1] = (Commands.OP_DELETE >> 8) & 0xff; _command[_index] = Commands.OP_DELETE & 0xff; // Adjust index _index = _index + 4; // Write zero _command[_index++] = 0; _command[_index++] = 0; _command[_index++] = 0; _command[_index++] = 0; // Write the collection name to the command _index = _index + _command.write(c.collectionName, _index, 'utf8') + 1; _command[_index - 1] = 0; // Write zero _command[_index++] = 0; _command[_index++] = 0; _command[_index++] = 0; _command[_index++] = 0; // Serialize the selector var documentLength = BSON.serializeWithBufferAndIndex(c.spec||c.selector, c.checkKeys, _command, _index) - _index + 1; // Write the length to the document _command[_index + 3] = (documentLength >> 24) & 0xff; _command[_index + 2] = (documentLength >> 16) & 0xff; _command[_index + 1] = (documentLength >> 8) & 0xff; _command[_index] = documentLength & 0xff; // Update index in buffer _index = _index + documentLength; // Add terminating 0 for the object _command[_index - 1] = 0; return _command; }; query = function(c) { // debug("======================================================= QUERY") // debug("================ " + BSON.calculateObjectSize(c.query)) // Calculate total length of the document var totalLengthOfCommand = 4 + Buffer.byteLength(c.collectionName) + 1 + 4 + 4 + BSON.calculateObjectSize(c.query) + (4 * 4); // Calculate extra fields size if(c.returnFieldSelector != null) { if(Object.keys(c.returnFieldSelector).length > 0) { totalLengthOfCommand += BSON.calculateObjectSize(c.returnFieldSelector); } } // Let's build the single pass buffer command var _index = 0; var _command = new Buffer(totalLengthOfCommand); // Write the header information to the buffer _command[_index + 3] = (totalLengthOfCommand >> 24) & 0xff; _command[_index + 2] = (totalLengthOfCommand >> 16) & 0xff; _command[_index + 1] = (totalLengthOfCommand >> 8) & 0xff; _command[_index] = totalLengthOfCommand & 0xff; // Adjust index _index = _index + 4; // Write the request ID _command[_index + 3] = (c.requestId >> 24) & 0xff; _command[_index + 2] = (c.requestId >> 16) & 0xff; _command[_index + 1] = (c.requestId >> 8) & 0xff; _command[_index] = c.requestId & 0xff; // Adjust index _index = _index + 4; // Write zero _command[_index++] = 0; _command[_index++] = 0; _command[_index++] = 0; _command[_index++] = 0; // Write the op_code for the command _command[_index + 3] = (Commands.OP_QUERY >> 24) & 0xff; _command[_index + 2] = (Commands.OP_QUERY >> 16) & 0xff; _command[_index + 1] = (Commands.OP_QUERY >> 8) & 0xff; _command[_index] = Commands.OP_QUERY & 0xff; // Adjust index _index = _index + 4; // Write the query options _command[_index + 3] = (c.queryOptions >> 24) & 0xff; _command[_index + 2] = (c.queryOptions >> 16) & 0xff; _command[_index + 1] = (c.queryOptions >> 8) & 0xff; _command[_index] = c.queryOptions & 0xff; // Adjust index _index = _index + 4; // Write the collection name to the command _index = _index + _command.write(c.collectionName, _index, 'utf8') + 1; _command[_index - 1] = 0; // Write the number of documents to skip _command[_index + 3] = (c.numberToSkip >> 24) & 0xff; _command[_index + 2] = (c.numberToSkip >> 16) & 0xff; _command[_index + 1] = (c.numberToSkip >> 8) & 0xff; _command[_index] = c.numberToSkip & 0xff; // Adjust index _index = _index + 4; // Write the number of documents to return _command[_index + 3] = (c.numberToReturn >> 24) & 0xff; _command[_index + 2] = (c.numberToReturn >> 16) & 0xff; _command[_index + 1] = (c.numberToReturn >> 8) & 0xff; _command[_index] = c.numberToReturn & 0xff; // Adjust index _index = _index + 4; // Serialize the query document straight to the buffer var documentLength = BSON.serializeWithBufferAndIndex(c.query, c.checkKeys, _command, _index) - _index + 1; // debug(inspect("===================== documentLength :: " + documentLength)) // Write the length to the document _command[_index + 3] = (documentLength >> 24) & 0xff; _command[_index + 2] = (documentLength >> 16) & 0xff; _command[_index + 1] = (documentLength >> 8) & 0xff; _command[_index] = documentLength & 0xff; // Update index in buffer _index = _index + documentLength; // Add terminating 0 for the object _command[_index - 1] = 0; // Push field selector if available if(c.returnFieldSelector != null) { if(Object.keys(c.returnFieldSelector).length > 0) { var documentLength = BSON.serializeWithBufferAndIndex(c.returnFieldSelector, c.checkKeys, _command, _index) - _index + 1; // Write the length to the document _command[_index + 3] = (documentLength >> 24) & 0xff; _command[_index + 2] = (documentLength >> 16) & 0xff; _command[_index + 1] = (documentLength >> 8) & 0xff; _command[_index] = documentLength & 0xff; // Update index in buffer _index = _index + documentLength; // Add terminating 0 for the object _command[_index - 1] = 0; } } // debug("------------------------------------------------------------------------") // debug(inspect(_command)) return _command; }; Commands.binary = function(cmd, op, id) { // Get the command data structure cmd.requestId = id; cmd.checkKeys = cmd.checkKeys == null ? true : cmd.checkKeys; var command = ''; switch(op) { case 2001: command = update(cmd); return command; break; case 2002: command = insert(cmd); return command; break; case 2004: command = query(cmd); return command; break; case 2005: command = more(cmd); return command; break; case 2006: command = remove(cmd); return command; break; case 2007: command = kill(cmd); return command; break; } // Total Size of command var totalSize = 4*4 + command.length; // Create the command with the standard header file //var hd = BinaryParser.fromInt(totalSize) + BinaryParser.fromInt(id) + BinaryParser.fromInt(0) + BinaryParser.fromInt(op); //var s = hd + command; //console.log(s.toString()); return BinaryParser.fromInt(totalSize) + BinaryParser.fromInt(id) + BinaryParser.fromInt(0) + BinaryParser.fromInt(op) + command; }; // OpCodes Commands.OP_REPLY = 1; Commands.OP_MSG = 1000; Commands.OP_UPDATE = 2001; Commands.OP_INSERT = 2002; Commands.OP_GET_BY_OID = 2003; Commands.OP_QUERY = 2004; Commands.OP_GET_MORE = 2005; Commands.OP_DELETE = 2006; Commands.OP_KILL_CURSORS = 2007; Commands.documents = [];