Skip to content

Commit

Permalink
Some minor write concern fixes, Added mongoclient and mongoclient sin…
Browse files Browse the repository at this point in the history
…gle server
  • Loading branch information
christkv committed Nov 8, 2012
1 parent 2fa8b19 commit afdd8a8
Show file tree
Hide file tree
Showing 6 changed files with 195 additions and 15 deletions.
14 changes: 11 additions & 3 deletions lib/mongodb/collection.js
Expand Up @@ -1053,8 +1053,6 @@ Collection.prototype.ensureIndex = function ensureIndex (fieldOrSpec, options, c
options = {};
}

// Collect errorOptions
var errorOptions = _getWriteConcern(this, options, callback);
// Execute create index
this.db.ensureIndex(this.collectionName, fieldOrSpec, options, callback);
};
Expand Down Expand Up @@ -1663,8 +1661,18 @@ var _getWriteConcern = function(self, options, callback) {
if(errorOptions
&& (errorOptions == true || errorOptions.w >= 1)
&& typeof callback !== 'function') throw new Error("safe cannot be used without a callback");

// Clean up the options ensuring no invalid data is there
var finalOptions = {};
if(errorOptions.w) finalOptions.w = errorOptions.w;
if(errorOptions.fsync) finalOptions.fsync = errorOptions.fsync;
if(errorOptions.journal) finalOptions.journal = errorOptions.journal;
if(errorOptions.wtimeout) finalOptions.wtimeout = errorOptions.wtimeout;
if(errorOptions == true) finalOptions.w = 1;
if(typeof errorOptions == 'object' && Object.keys(errorOptions).length == 0) finalOptions.w = 1;

// Return the error options
return errorOptions;
return finalOptions;
}

/**
Expand Down
30 changes: 19 additions & 11 deletions lib/mongodb/db.js
Expand Up @@ -63,7 +63,6 @@ inherits(CallbackStore, EventEmitter);
* @param {Object} [options] additional options for the collection.
*/
function Db(databaseName, serverConfig, options) {

if(!(this instanceof Db)) return new Db(databaseName, serverConfig, options);

EventEmitter.call(this);
Expand Down Expand Up @@ -758,11 +757,11 @@ Db.prototype.addUser = function(username, password, options, callback) {
options = args.length ? args.shift() : {};

// Figure out the safe mode settings
var safe = self.safe != null && self.safe == false ? true : self.safe;
var safe = self.safe != null && self.safe == false ? {w: 1} : self.safe;
// Override with options passed in if applicable
safe = options != null && options['safe'] != null ? options['safe'] : safe;
// Ensure it's at least set to safe
safe = safe == null ? true : safe;
safe = safe == null ? {w: 1} : safe;

// Use node md5 generator
var md5 = crypto.createHash('md5');
Expand Down Expand Up @@ -819,11 +818,11 @@ Db.prototype.removeUser = function(username, options, callback) {
options = args.length ? args.shift() : {};

// Figure out the safe mode settings
var safe = self.safe != null && self.safe == false ? true : self.safe;
var safe = self.safe != null && self.safe == false ? {w: 1} : self.safe;
// Override with options passed in if applicable
safe = options != null && options['safe'] != null ? options['safe'] : safe;
// Ensure it's at least set to safe
safe = safe == null ? true : safe;
safe = safe == null ? {w: 1} : safe;

// Fetch a user collection
var collection = this.collection(DbCommand.SYSTEM_USER_COLLECTION);
Expand Down Expand Up @@ -871,11 +870,11 @@ Db.prototype.createCollection = function(collectionName, options, callback) {
var self = this;

// Figure out the safe mode settings
var safe = self.safe != null && self.safe == false ? true : self.safe;
var safe = self.safe != null && self.safe == false ? {w: 1} : self.safe;
// Override with options passed in if applicable
safe = options != null && options['safe'] != null ? options['safe'] : safe;
// Ensure it's at least set to safe
safe = safe == null ? true : safe;
safe = safe == null ? {w: 1} : safe;

// Check if we have the name
this.collectionNames(collectionName, function(err, collections) {
Expand Down Expand Up @@ -1862,12 +1861,12 @@ var __executeInsertCommand = function(self, db_command, options, callback) {
return callback(connection);
}

// We are expecting a check right after the actual operation
if(safe != null && safe != false && safe.w != -1) {
var errorOptions = _getWriteConcern(self, options, callback);
if(errorOptions.w > 0 || errorOptions.journal || errorOptions.fsync) {
// db command is now an array of commands (original command + lastError)
db_command = [db_command, DbCommand.createGetLastErrorCommand(safe, self)];
// Register the handler in the data structure
self._registerHandler(db_command[1], raw, connection, callback);
self._registerHandler(db_command[1], raw, connection, callback);
}
}

Expand Down Expand Up @@ -2175,8 +2174,17 @@ var _getWriteConcern = function(self, options, callback) {
if(errorOptions
&& (errorOptions == true || errorOptions.w >= 1)
&& typeof callback !== 'function') throw new Error("safe cannot be used without a callback");

// Clean up the options ensuring no invalid data is there
var finalOptions = {};
if(errorOptions.w) finalOptions.w = errorOptions.w;
if(errorOptions.fsync) finalOptions.fsync = errorOptions.fsync;
if(errorOptions.journal) finalOptions.journal = errorOptions.journal;
if(errorOptions.wtimeout) finalOptions.wtimeout = errorOptions.wtimeout;
if(errorOptions == true) finalOptions.w = 1;
if(typeof errorOptions == 'object' && Object.keys(errorOptions).length == 0) finalOptions.w = 1;
// Return the error options
return errorOptions;
return finalOptions;
}


Expand Down
1 change: 1 addition & 0 deletions lib/mongodb/index.js
Expand Up @@ -15,6 +15,7 @@ try {
, 'connection/repl_set'
, 'cursor'
, 'db'
, 'mongo_client'
, 'gridfs/grid'
, 'gridfs/chunk'
, 'gridfs/gridstore'].forEach(function (path) {
Expand Down
47 changes: 47 additions & 0 deletions lib/mongodb/mongo_client.js
@@ -0,0 +1,47 @@
// var inherits = require('util').inherits
var Db = require('./db').Db;

var MongoClient = function MongoClient(serverConfig, options) {
options = options == null ? {} : options;
// If no write concern is set set the default to w:1
if(options != null && !options.safe && !options.journal && !options.w && !options.fsync) {
options.w = 1;
}

// The internal db instance we are wrapping
var _db = new Db('test', serverConfig, options);
// Self reference
var self = this;

// Open command for the MongoClient
MongoClient.prototype.open = function(callback) {
_db.open(function(err, db) {
if(err) return callback(err, null);
callback(null, self);
})
}

// Close command for the MongoClient
MongoClient.prototype.close = function(callback) {
_db.close(callback);
}

// Get a db object
MongoClient.prototype.db = function(dbName) {
return _db.db(dbName);
}
}

MongoClient.connect = function(url, options, callback) {
Db.connect(url, options, function(err, db) {
if(err) return callback(err, null);
// If no write concern is set set the default to w:1
if(db.options != null && !db.options.safe && !db.options.journal && !db.options.w && !db.options.fsync) {
db.options.w = 1;
}
// Return the db
callback(null, db);
});
}

exports.MongoClient = MongoClient;
2 changes: 1 addition & 1 deletion test/collection_test.js
Expand Up @@ -1040,7 +1040,7 @@ exports.shouldCorrectlySaveDocumentWithNestedArray = function(test) {
db.open(function(err, db) {
db.createCollection("save_error_on_save_test", function(err, collection) {
// Create unique index for username
collection.createIndex([['username', 1]], true, function(err, result) {
collection.createIndex([['username', 1]], {safe:true}, function(err, result) {
var doc = {
email: 'email@email.com',
encrypted_password: 'password',
Expand Down
116 changes: 116 additions & 0 deletions test/mongo_client_test.js
@@ -0,0 +1,116 @@
var mongodb = process.env['TEST_NATIVE'] != null ? require('../lib/mongodb').native() : require('../lib/mongodb').pure();
var useSSL = process.env['USE_SSL'] != null ? true : false;
var native_parser = (process.env['TEST_NATIVE'] != null);

var testCase = require('nodeunit').testCase,
debug = require('util').debug,
inspect = require('util').inspect,
nodeunit = require('nodeunit'),
gleak = require('../dev/tools/gleak'),
Db = mongodb.Db,
Cursor = mongodb.Cursor,
Collection = mongodb.Collection,
Server = mongodb.Server,
MongoClient = mongodb.MongoClient;

var MONGODB = 'integration_tests';
var client = null;

/**
* Retrieve the server information for the current
* instance of the db client
*
* @ignore
*/
exports.setUp = function(callback) {
var self = exports;
client = new Db(MONGODB, new Server("127.0.0.1", 27017, {auto_reconnect: true, poolSize: 4, ssl:useSSL}), {safe:false, native_parser: (process.env['TEST_NATIVE'] != null)});
client.open(function(err, db_p) {
if(numberOfTestsRun == (Object.keys(self).length)) {
// If first test drop the db
client.dropDatabase(function(err, done) {
callback();
});
} else {
return callback();
}
});
}

/**
* Retrieve the server information for the current
* instance of the db client
*
* @ignore
*/
exports.tearDown = function(callback) {
var self = this;
numberOfTestsRun = numberOfTestsRun - 1;
// Close connection
client.close();
callback();
}

// MongoClient interface
// .open
// .close
// .db
// .connect
exports['Should correctly connect using MongoClient to a single server'] = function(test) {
var mongoclient = new MongoClient(new Server("localhost", 27017, {ssl:useSSL}), {native_parser: (process.env['TEST_NATIVE'] != null)});
mongoclient.open(function(err, mongoclient) {

// Get the first db and do an update document on it
var db = mongoclient.db("integration_tests");
db.collection('mongoclient_test').update({a:1}, {b:1}, {upsert:true}, function(err, result) {
test.equal(null, err);
test.equal(1, result);

// Get another db and do an update document on it
var db2 = mongoclient.db("integration_tests2");
db2.collection('mongoclient_test').update({a:1}, {b:1}, {upsert:true}, function(err, result) {
test.equal(null, err);
test.equal(1, result);

mongoclient.close();
test.done();
});
});
});
}

exports['Should correctly connect using MongoClient to a single server using connect'] = function(test) {
var options = {native_parser: (process.env['TEST_NATIVE'] != null)};
// Connect using the connection string
MongoClient.connect("mongodb://localhost:27017/integration_tests", options, function(err, db) {
test.equal(null, err);

db.collection('mongoclient_test').update({a:1}, {b:1}, {upsert:true}, function(err, result) {
test.equal(null, err);
test.equal(1, result);

db.close();
test.done();
});
});
}

/**
* Retrieve the server information for the current
* instance of the db client
*
* @ignore
*/
exports.noGlobalsLeaked = function(test) {
var leaks = gleak.detectNew();
test.equal(0, leaks.length, "global var leak detected: " + leaks.join(', '));
test.done();
}

/**
* Retrieve the server information for the current
* instance of the db client
*
* @ignore
*/
var numberOfTestsRun = Object.keys(this).length - 2;

0 comments on commit afdd8a8

Please sign in to comment.