Skip to content

Commit d22a337

Browse files
committed
Single buffer pass update command
1 parent 53f6eaf commit d22a337

File tree

4 files changed

+314
-123
lines changed

4 files changed

+314
-123
lines changed

lib/mongodb/commands/insert_command.js

Lines changed: 63 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@ var InsertCommand = exports.InsertCommand = function(db, collectionName, checkKe
1717
// OpCodes
1818
InsertCommand.OP_INSERT =2002;
1919

20-
// inherits(InsertCommand, InsertCommand);
21-
2220
InsertCommand.prototype.add = function(document) {
2321
this.documents.push(document);
2422
return this;
@@ -32,37 +30,16 @@ struct {
3230
BSON[] documents; // one or more documents to insert into the collection
3331
}
3432
*/
35-
InsertCommand.prototype.getCommandAsBuffers = function(buffers) {
36-
var collectionNameBuffers = InsertCommand.encodeCString(this.collectionName);
37-
// Add command to buffers
38-
buffers.push(InsertCommand.encodeInt(0), collectionNameBuffers[0], collectionNameBuffers[1]);
39-
// Basic command length
40-
var commandLength = 4 + collectionNameBuffers[0].length + 1;
41-
42-
for(var i = 0; i < this.documents.length; i++) {
43-
var command = this.db.bson_serializer.BSON.serialize(this.documents[i], this.checkKeys, true);
44-
commandLength += command.length;
45-
buffers.push(command);
46-
}
47-
48-
return commandLength;
49-
}
50-
5133
InsertCommand.prototype.toBinary = function() {
34+
//////////////////////////////////////////////////////////////////////////////////////
5235
// Calculate total length of the document
5336
var totalLengthOfCommand = 4 + Buffer.byteLength(this.collectionName) + 1 + (4 * 4);
54-
var documentLengths = [];
5537
// var docLength = 0
5638
for(var i = 0; i < this.documents.length; i++) {
5739
// Calculate size of document
58-
var documentLength = this.db.bson_serializer.BSON.calculateObjectSize(this.documents[i]);
59-
// Save the size for writing the command
60-
documentLengths.push(documentLength);
61-
// Add to total of command
62-
totalLengthOfCommand += documentLength
40+
totalLengthOfCommand += this.db.bson_serializer.BSON.calculateObjectSize(this.documents[i]);
6341
}
64-
65-
//////////////////////////////////////////////////////////////////////////////////////
42+
6643
// Let's build the single pass buffer command
6744
var _index = 0;
6845
var _command = new Buffer(totalLengthOfCommand);
@@ -99,13 +76,12 @@ InsertCommand.prototype.toBinary = function() {
9976
_command[_index++] = 0;
10077
// Write the collection name to the command
10178
_index = _index + _command.write(this.collectionName, _index, 'utf8') + 1;
79+
_command[_index - 1] = 0;
10280

10381
// Write all the bson documents to the buffer at the index offset
10482
for(var i = 0; i < this.documents.length; i++) {
10583
// Serialize the document straight to the buffer
10684
var documentLength = this.db.bson_serializer.BSON.serializeWithBufferAndIndex(this.documents[i], this.checkKeys, _command, _index) - _index + 1;
107-
// debug("============= documentLength = " + (documentLength - _index))
108-
10985
// Write the length to the document
11086
_command[_index + 3] = (documentLength >> 24) & 0xff;
11187
_command[_index + 2] = (documentLength >> 16) & 0xff;
@@ -117,71 +93,71 @@ InsertCommand.prototype.toBinary = function() {
11793
_command[_index - 1] = 0;
11894
}
11995

120-
// return _command;
96+
return _command;
12197

12298
//////////////////////////////////////////////////////////////////////////////////////
12399

124-
// Build list of Buffer objects to write out
125-
var buffers = [];
126-
127-
// Get the command op code
128-
var op_code = InsertCommand.OP_INSERT;
129-
var commandBuffers = [];
130-
131-
// Get the command data structure
132-
var commandLength = this.getCommandAsBuffers(commandBuffers);
133-
134-
135-
// Total Size of command
136-
var totalSize = 4 * 4 + commandLength;
137-
// Encode totalSize, requestId, responseId and opcode
138-
buffers.push(InsertCommand.encodeInt(totalSize), InsertCommand.encodeInt(this.requestId), InsertCommand.encodeInt(0), InsertCommand.encodeInt(op_code));
139-
140-
// Add the command items
141-
buffers = buffers.concat(commandBuffers);
142-
// Allocate single buffer for write
143-
var finalBuffer = new Buffer(totalSize);
144-
145-
var index = 0;
146-
147-
for(var i = 0; i < buffers.length; i++) {
148-
buffers[i].copy(finalBuffer, index);
149-
index = index + buffers[i].length;
150-
}
151-
152-
// debug("==================== finalBuffer.length = " + finalBuffer.length)
153-
// debug("==================== totalLengthOfCommand = " + totalLengthOfCommand)
154-
// debug("==================== totalSize = " + totalSize)
155-
// debug("==================== docLength = " + docLength)
156-
// debug("==================== commandLength = " + commandLength)
100+
// // Build list of Buffer objects to write out
101+
// var buffers = [];
102+
//
103+
// // Get the command op code
104+
// var op_code = InsertCommand.OP_INSERT;
105+
// var commandBuffers = [];
106+
//
107+
// // Get the command data structure
108+
// var commandLength = this.getCommandAsBuffers(commandBuffers);
109+
//
110+
//
111+
// // Total Size of command
112+
// var totalSize = 4 * 4 + commandLength;
113+
// // Encode totalSize, requestId, responseId and opcode
114+
// buffers.push(InsertCommand.encodeInt(totalSize), InsertCommand.encodeInt(this.requestId), InsertCommand.encodeInt(0), InsertCommand.encodeInt(op_code));
115+
//
116+
// // Add the command items
117+
// buffers = buffers.concat(commandBuffers);
118+
// // Allocate single buffer for write
119+
// var finalBuffer = new Buffer(totalSize);
120+
//
121+
// var index = 0;
157122
//
158-
// for(var i = 0; i < finalBuffer.length; i++) {
159-
// debug(i + " :: [" + _command[i] + "] = [" + finalBuffer[i] + "]" + (_command[i] != finalBuffer[i] ? " = FALSE" : ""))
123+
// for(var i = 0; i < buffers.length; i++) {
124+
// buffers[i].copy(finalBuffer, index);
125+
// index = index + buffers[i].length;
160126
// }
161-
162-
return finalBuffer;
127+
//
128+
// // debug("==================== finalBuffer.length = " + finalBuffer.length)
129+
// // debug("==================== totalLengthOfCommand = " + totalLengthOfCommand)
130+
// // debug("==================== totalSize = " + totalSize)
131+
// // debug("==================== docLength = " + docLength)
132+
// // debug("==================== commandLength = " + commandLength)
133+
// //
134+
// // for(var i = 0; i < finalBuffer.length; i++) {
135+
// // debug(i + " :: [" + _command[i] + "] = [" + finalBuffer[i] + "]" + (_command[i] != finalBuffer[i] ? " = FALSE" : ""))
136+
// // }
137+
//
138+
// return finalBuffer;
163139
};
164-
165-
InsertCommand.encodeInt = function(value) {
166-
var buffer = new Buffer(4);
167-
buffer[3] = (value >> 24) & 0xff;
168-
buffer[2] = (value >> 16) & 0xff;
169-
buffer[1] = (value >> 8) & 0xff;
170-
buffer[0] = value & 0xff;
171-
return buffer;
172-
}
173-
174-
InsertCommand.encodeIntInPlace = function(value, buffer, index) {
175-
buffer[index + 3] = (value >> 24) & 0xff;
176-
buffer[index + 2] = (value >> 16) & 0xff;
177-
buffer[index + 1] = (value >> 8) & 0xff;
178-
buffer[index] = value & 0xff;
179-
}
180-
181-
InsertCommand.encodeCString = function(string) {
182-
var buf = new Buffer(string, 'utf8');
183-
return [buf, new Buffer([0])];
184-
}
140+
//
141+
// InsertCommand.encodeInt = function(value) {
142+
// var buffer = new Buffer(4);
143+
// buffer[3] = (value >> 24) & 0xff;
144+
// buffer[2] = (value >> 16) & 0xff;
145+
// buffer[1] = (value >> 8) & 0xff;
146+
// buffer[0] = value & 0xff;
147+
// return buffer;
148+
// }
149+
//
150+
// InsertCommand.encodeIntInPlace = function(value, buffer, index) {
151+
// buffer[index + 3] = (value >> 24) & 0xff;
152+
// buffer[index + 2] = (value >> 16) & 0xff;
153+
// buffer[index + 1] = (value >> 8) & 0xff;
154+
// buffer[index] = value & 0xff;
155+
// }
156+
//
157+
// InsertCommand.encodeCString = function(string) {
158+
// var buf = new Buffer(string, 'utf8');
159+
// return [buf, new Buffer([0])];
160+
// }
185161

186162

187163

lib/mongodb/commands/query_command.js

Lines changed: 100 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ var BaseCommand = require('./base_command').BaseCommand,
88
Insert Document Command
99
**/
1010
var QueryCommand = exports.QueryCommand = function(db, collectionName, queryOptions, numberToSkip, numberToReturn, query, returnFieldSelector) {
11-
BaseCommand.call(this);
12-
1311
this.collectionName = collectionName;
1412
this.queryOptions = queryOptions;
1513
this.numberToSkip = numberToSkip;
@@ -19,11 +17,7 @@ var QueryCommand = exports.QueryCommand = function(db, collectionName, queryOpti
1917
this.db = db;
2018
};
2119

22-
inherits(QueryCommand, BaseCommand);
23-
24-
QueryCommand.prototype.getOpCode = function() {
25-
return BaseCommand.OP_QUERY;
26-
};
20+
QueryCommand.OP_QUERY = 2004;
2721

2822
/*
2923
struct {
@@ -36,32 +30,106 @@ struct {
3630
[ BSON returnFieldSelector; ] // OPTIONAL : selector indicating the fields to return. See below for details.
3731
}
3832
*/
39-
QueryCommand.prototype.getCommandAsBuffers = function(buffers) {
40-
var collectionNameBuffers = BaseCommand.encodeCString(this.collectionName);
41-
var queryCommand = this.db.bson_serializer.BSON.serialize(this.query, false, true);
42-
var totalObjectLength = 0;
33+
QueryCommand.prototype.toBinary = function() {
34+
//////////////////////////////////////////////////////////////////////////////////////
35+
// Calculate total length of the document
36+
var totalLengthOfCommand = 4 + Buffer.byteLength(this.collectionName) + 1 + 4 + 4 + this.db.bson_serializer.BSON.calculateObjectSize(this.query) + (4 * 4);
37+
// Calculate extra fields size
38+
if(this.returnFieldSelector != null) {
39+
if(Object.keys(this.returnFieldSelector).length > 0) {
40+
totalLengthOfCommand += this.db.bson_serializer.BSON.calculateObjectSize(this.returnFieldSelector);
41+
}
42+
}
43+
44+
// Let's build the single pass buffer command
45+
var _index = 0;
46+
var _command = new Buffer(totalLengthOfCommand);
47+
// Write the header information to the buffer
48+
_command[_index + 3] = (totalLengthOfCommand >> 24) & 0xff;
49+
_command[_index + 2] = (totalLengthOfCommand >> 16) & 0xff;
50+
_command[_index + 1] = (totalLengthOfCommand >> 8) & 0xff;
51+
_command[_index] = totalLengthOfCommand & 0xff;
52+
// Adjust index
53+
_index = _index + 4;
54+
// Write the request ID
55+
_command[_index + 3] = (this.requestId >> 24) & 0xff;
56+
_command[_index + 2] = (this.requestId >> 16) & 0xff;
57+
_command[_index + 1] = (this.requestId >> 8) & 0xff;
58+
_command[_index] = this.requestId & 0xff;
59+
// Adjust index
60+
_index = _index + 4;
61+
// Write zero
62+
_command[_index++] = 0;
63+
_command[_index++] = 0;
64+
_command[_index++] = 0;
65+
_command[_index++] = 0;
66+
// Write the op_code for the command
67+
_command[_index + 3] = (QueryCommand.OP_QUERY >> 24) & 0xff;
68+
_command[_index + 2] = (QueryCommand.OP_QUERY >> 16) & 0xff;
69+
_command[_index + 1] = (QueryCommand.OP_QUERY >> 8) & 0xff;
70+
_command[_index] = QueryCommand.OP_QUERY & 0xff;
71+
// Adjust index
72+
_index = _index + 4;
4373

44-
// Push basic options + query
45-
buffers.push(BaseCommand.encodeInt(this.queryOptions), collectionNameBuffers[0], collectionNameBuffers[1],
46-
BaseCommand.encodeInt(this.numberToSkip), BaseCommand.encodeInt(this.numberToReturn),
47-
queryCommand);
74+
// Write the query options
75+
_command[_index + 3] = (this.queryOptions >> 24) & 0xff;
76+
_command[_index + 2] = (this.queryOptions >> 16) & 0xff;
77+
_command[_index + 1] = (this.queryOptions >> 8) & 0xff;
78+
_command[_index] = this.queryOptions & 0xff;
79+
// Adjust index
80+
_index = _index + 4;
81+
82+
// Write the collection name to the command
83+
_index = _index + _command.write(this.collectionName, _index, 'utf8') + 1;
84+
_command[_index - 1] = 0;
85+
86+
// Write the number of documents to skip
87+
_command[_index + 3] = (this.numberToSkip >> 24) & 0xff;
88+
_command[_index + 2] = (this.numberToSkip >> 16) & 0xff;
89+
_command[_index + 1] = (this.numberToSkip >> 8) & 0xff;
90+
_command[_index] = this.numberToSkip & 0xff;
91+
// Adjust index
92+
_index = _index + 4;
93+
94+
// Write the number of documents to return
95+
_command[_index + 3] = (this.numberToReturn >> 24) & 0xff;
96+
_command[_index + 2] = (this.numberToReturn >> 16) & 0xff;
97+
_command[_index + 1] = (this.numberToReturn >> 8) & 0xff;
98+
_command[_index] = this.numberToReturn & 0xff;
99+
// Adjust index
100+
_index = _index + 4;
48101

49-
// Add up total length
50-
totalObjectLength += 4 + collectionNameBuffers[0].length + 1 + 4 + 4 + queryCommand.length;
102+
// Serialize the query document straight to the buffer
103+
var documentLength = this.db.bson_serializer.BSON.serializeWithBufferAndIndex(this.query, this.checkKeys, _command, _index) - _index + 1;
104+
// Write the length to the document
105+
_command[_index + 3] = (documentLength >> 24) & 0xff;
106+
_command[_index + 2] = (documentLength >> 16) & 0xff;
107+
_command[_index + 1] = (documentLength >> 8) & 0xff;
108+
_command[_index] = documentLength & 0xff;
109+
// Update index in buffer
110+
_index = _index + documentLength;
111+
// Add terminating 0 for the object
112+
_command[_index - 1] = 0;
51113

52114
// Push field selector if available
53115
if(this.returnFieldSelector != null) {
54-
var count = 0; for(var name in this.returnFieldSelector) { count += 1; }
55-
if(count > 0) {
56-
var fieldsCommand = this.db.bson_serializer.BSON.serialize(this.returnFieldSelector, false, true);
57-
totalObjectLength += fieldsCommand.length;
58-
buffers.push(fieldsCommand);
116+
if(Object.keys(this.returnFieldSelector).length > 0) {
117+
var documentLength = this.db.bson_serializer.BSON.serializeWithBufferAndIndex(this.returnFieldSelector, this.checkKeys, _command, _index) - _index + 1;
118+
// Write the length to the document
119+
_command[_index + 3] = (documentLength >> 24) & 0xff;
120+
_command[_index + 2] = (documentLength >> 16) & 0xff;
121+
_command[_index + 1] = (documentLength >> 8) & 0xff;
122+
_command[_index] = documentLength & 0xff;
123+
// Update index in buffer
124+
_index = _index + documentLength;
125+
// Add terminating 0 for the object
126+
_command[_index - 1] = 0;
59127
}
60128
}
61129

62-
// Return value
63-
return totalObjectLength
64-
}
130+
return _command;
131+
//////////////////////////////////////////////////////////////////////////////////////
132+
};
65133

66134
// Constants
67135
QueryCommand.OPTS_NONE = 0;
@@ -70,4 +138,10 @@ QueryCommand.OPTS_SLAVE = 4;
70138
QueryCommand.OPTS_OPLOG_REPLY = 8;
71139
QueryCommand.OPTS_NO_CURSOR_TIMEOUT = 16;
72140
QueryCommand.OPTS_AWAIT_DATA = 32;
73-
QueryCommand.OPTS_EXHAUST = 64;
141+
QueryCommand.OPTS_EXHAUST = 64;
142+
143+
var id = 1;
144+
QueryCommand.prototype.getRequestId = function() {
145+
if (!this.requestId) this.requestId = id++;
146+
return this.requestId;
147+
};

0 commit comments

Comments
 (0)