diff options
author | Kaloian Manassiev <kaloian.manassiev@mongodb.com> | 2015-02-23 11:37:20 -0500 |
---|---|---|
committer | Kaloian Manassiev <kaloian.manassiev@mongodb.com> | 2015-03-03 10:53:07 -0500 |
commit | 41986e669a4ef32b38c433a2cfd0b70e872e6899 (patch) | |
tree | 675ec225c7e9fad5902a78e71efc2e6c9d167325 /src/mongo | |
parent | acea28520290e793c1ff9e6ed4117ff543c59a98 (diff) | |
download | mongo-41986e669a4ef32b38c433a2cfd0b70e872e6899.tar.gz |
SERVER-17151 ConfigCoordinator should not call fsync
This is expensive to do, especially with WiredTiger and is not a
deterministic check. This change replaces it with something cheaper, but
has the same outcome - validates that previous writes were successfully
journaled, which is an approximate predictor that subsequent writes have
high chance of succeeding.
Diffstat (limited to 'src/mongo')
32 files changed, 409 insertions, 853 deletions
diff --git a/src/mongo/SConscript b/src/mongo/SConscript index 683c959e7af..809c8c2d58f 100644 --- a/src/mongo/SConscript +++ b/src/mongo/SConscript @@ -827,23 +827,20 @@ env.Library('mongoscore', 's/upgrade', ]) -env.CppUnitTest("shard_key_pattern_test", [ "s/shard_key_pattern_test.cpp" ], +env.CppUnitTest("mongoscore_test", + ["s/shard_key_pattern_test.cpp", + "s/balancing_window_test.cpp", + "s/balancer_policy_tests.cpp", + ], LIBDEPS=["mongoscore", "coreshard", "mongocommon", "coreserver", "coredb"]) -env.CppUnitTest( "balancer_policy_test" , [ "s/balancer_policy_tests.cpp" ] , - LIBDEPS=["mongoscore", - "coreshard", - "mongocommon", - "coreserver", - "coredb", - "message_server_port"]) - env.CppUnitTest("dbclient_rs_test", [ "client/dbclient_rs_test.cpp" ], LIBDEPS=['clientdriver', 'mocklib']) + env.CppUnitTest("scoped_db_conn_test", [ "client/scoped_db_conn_test.cpp" ], LIBDEPS=[ "coredb", diff --git a/src/mongo/bson/bsonmisc.h b/src/mongo/bson/bsonmisc.h index 21cbc135b8c..483528d80e0 100644 --- a/src/mongo/bson/bsonmisc.h +++ b/src/mongo/bson/bsonmisc.h @@ -29,10 +29,8 @@ #pragma once -#include <boost/noncopyable.hpp> -#include <memory> - #include "mongo/bson/bsonelement.h" +#include "mongo/bson/bsonobj.h" namespace mongo { diff --git a/src/mongo/client/syncclusterconnection.cpp b/src/mongo/client/syncclusterconnection.cpp index 285c0baba26..762a2d69ea0 100644 --- a/src/mongo/client/syncclusterconnection.cpp +++ b/src/mongo/client/syncclusterconnection.cpp @@ -96,33 +96,29 @@ namespace mongo { _conns.clear(); } - bool SyncClusterConnection::prepare( string& errmsg ) { + bool SyncClusterConnection::prepare(string& errmsg) { _lastErrors.clear(); - return fsync( errmsg ); - } - bool SyncClusterConnection::fsync( string& errmsg ) { bool ok = true; errmsg = ""; - for ( size_t i=0; i<_conns.size(); i++ ) { + + for (size_t i = 0; i < _conns.size(); i++) { string singleErr; try { - // this is fsync=true - // which with journalling on is a journal commit - // without journalling, is a full fsync - _conns[i]->simpleCommand( "admin", NULL, "resetError" ); - singleErr = _conns[i]->getLastError( true ); + _conns[i]->simpleCommand("admin", NULL, "resetError"); + singleErr = _conns[i]->getLastError(true); - if ( singleErr.size() == 0 ) + if (singleErr.size() == 0) continue; } - catch ( DBException& e ) { + catch (DBException& e) { singleErr = e.toString(); } ok = false; errmsg += " " + _conns[i]->toString() + ":" + singleErr; } + return ok; } diff --git a/src/mongo/client/syncclusterconnection.h b/src/mongo/client/syncclusterconnection.h index d9f5ab3f2c8..6a99f59a364 100644 --- a/src/mongo/client/syncclusterconnection.h +++ b/src/mongo/client/syncclusterconnection.h @@ -78,11 +78,6 @@ namespace mongo { */ bool prepare( std::string& errmsg ); - /** - * runs fsync on all servers - */ - bool fsync( std::string& errmsg ); - // --- from DBClientInterface virtual BSONObj findOne(const std::string &ns, const Query& query, const BSONObj *fieldsToReturn, int queryOptions); diff --git a/src/mongo/db/auth/authz_manager_external_state_s.cpp b/src/mongo/db/auth/authz_manager_external_state_s.cpp index 20e47afaed1..5d70845324f 100644 --- a/src/mongo/db/auth/authz_manager_external_state_s.cpp +++ b/src/mongo/db/auth/authz_manager_external_state_s.cpp @@ -245,7 +245,7 @@ namespace mongo { const NamespaceString& collectionName, const BSONObj& document, const BSONObj& writeConcern) { - return clusterInsert(collectionName, document, writeConcern, NULL); + return clusterInsert(collectionName, document, NULL); } Status AuthzManagerExternalStateMongos::update(OperationContext* txn, @@ -262,7 +262,6 @@ namespace mongo { updatePattern, upsert, multi, - writeConcern, &response); if (res.isOK()) { @@ -279,7 +278,7 @@ namespace mongo { const BSONObj& writeConcern, int* numRemoved) { BatchedCommandResponse response; - Status res = clusterDelete(collectionName, query, 0 /* limit */, writeConcern, &response); + Status res = clusterDelete(collectionName, query, 0 /* limit */, &response); if (res.isOK()) { *numRemoved = response.getN(); diff --git a/src/mongo/db/write_concern_options.cpp b/src/mongo/db/write_concern_options.cpp index dd8b14cdb05..5c0102ebc4a 100644 --- a/src/mongo/db/write_concern_options.cpp +++ b/src/mongo/db/write_concern_options.cpp @@ -37,7 +37,6 @@ namespace mongo { const BSONObj WriteConcernOptions::Default = BSONObj(); const BSONObj WriteConcernOptions::Acknowledged(BSON("w" << W_NORMAL)); - const BSONObj WriteConcernOptions::AllConfigs = BSONObj(); const BSONObj WriteConcernOptions::Unacknowledged(BSON("w" << W_NONE)); static const BSONField<bool> mongosSecondaryThrottleField("_secondaryThrottle", true); diff --git a/src/mongo/db/write_concern_options.h b/src/mongo/db/write_concern_options.h index 31b0f556c30..445b6fab1db 100644 --- a/src/mongo/db/write_concern_options.h +++ b/src/mongo/db/write_concern_options.h @@ -44,7 +44,6 @@ namespace mongo { static const BSONObj Default; static const BSONObj Acknowledged; - static const BSONObj AllConfigs; static const BSONObj Unacknowledged; WriteConcernOptions() { reset(); } diff --git a/src/mongo/s/SConscript b/src/mongo/s/SConscript index ced76ef6768..8ff9e09e754 100644 --- a/src/mongo/s/SConscript +++ b/src/mongo/s/SConscript @@ -153,52 +153,12 @@ env.Library( ) env.CppUnitTest( - target='batched_command_response_test', + target='batch_write_types_test', source=[ 'write_ops/batched_command_response_test.cpp', - ], - LIBDEPS=[ - 'batch_write_types', - '$BUILD_DIR/mongo/db/common', - ] -) - -env.CppUnitTest( - target='batched_delete_request_test', - source=[ 'write_ops/batched_delete_request_test.cpp', - ], - LIBDEPS=[ - 'batch_write_types', - '$BUILD_DIR/mongo/db/common', - ] -) - -env.CppUnitTest( - target='batched_insert_request_test', - source=[ 'write_ops/batched_insert_request_test.cpp', - ], - LIBDEPS=[ - 'batch_write_types', - '$BUILD_DIR/mongo/db/common', - ] -) - -env.CppUnitTest( - target='batched_request_metadata_test', - source=[ 'write_ops/batched_request_metadata_test.cpp', - ], - LIBDEPS=[ - 'batch_write_types', - '$BUILD_DIR/mongo/db/common', - ] -) - -env.CppUnitTest( - target='batched_update_request_test', - source=[ 'write_ops/batched_update_request_test.cpp', ], LIBDEPS=[ @@ -231,32 +191,10 @@ env.Library( ) env.CppUnitTest( - target='write_op_test', + target='cluster_ops_test', source=[ 'write_ops/write_op_test.cpp', - ], - LIBDEPS=[ - 'base', - 'cluster_ops', - '$BUILD_DIR/mongo/db/common', - ] -) - -env.CppUnitTest( - target='batch_write_op_test', - source=[ 'write_ops/batch_write_op_test.cpp', - ], - LIBDEPS=[ - 'base', - 'cluster_ops', - '$BUILD_DIR/mongo/db/common', - ] -) - -env.CppUnitTest( - target='batch_write_exec_test', - source=[ 'write_ops/batch_write_exec_test.cpp', ], LIBDEPS=[ @@ -264,7 +202,7 @@ env.CppUnitTest( 'cluster_ops', '$BUILD_DIR/mongo/db/common', '$BUILD_DIR/mongo/clientdriver', - ], + ] ) env.CppUnitTest( @@ -308,22 +246,9 @@ env.Library( ) env.CppUnitTest( - target='batch_upconvert_test', + target='cluster_write_op_conversion_test', source=[ 'write_ops/batch_upconvert_test.cpp', - ], - LIBDEPS=[ - 'cluster_ops', - 'cluster_write_op_conversion', - '$BUILD_DIR/mongo/db/common', - '$BUILD_DIR/mongo/server_options', # DbMessage needs server options - "$BUILD_DIR/mongo/clientdriver", - ] -) - -env.CppUnitTest( - target='batch_downconvert_test', - source=[ 'write_ops/batch_downconvert_test.cpp', ], LIBDEPS=[ diff --git a/src/mongo/s/balance.cpp b/src/mongo/s/balance.cpp index e380a136191..418f63a7197 100644 --- a/src/mongo/s/balance.cpp +++ b/src/mongo/s/balance.cpp @@ -188,7 +188,6 @@ namespace mongo { MongosType::mongoVersion(versionString) )), true, // upsert false, // multi - WriteConcernOptions::Unacknowledged, NULL ); } @@ -262,11 +261,7 @@ namespace mongo { createActionlog = true; } - Status result = clusterInsert( ActionLogType::ConfigNS, - actionLog.toBSON(), - WriteConcernOptions::AllConfigs, - NULL ); - + Status result = clusterInsert(ActionLogType::ConfigNS, actionLog.toBSON(), NULL); if ( !result.isOK() ) { log() << "Error encountered while logging action from balancer " << result.reason(); @@ -446,7 +441,6 @@ namespace mongo { DistributionStatus status(shardInfo, shardToChunksMap.map()); - // load tags cursor = conn.query(TagsType::ConfigNS, QUERY(TagsType::ns(ns)).sort(TagsType::min())); diff --git a/src/mongo/s/balancing_window_test.cpp b/src/mongo/s/balancing_window_test.cpp new file mode 100644 index 00000000000..c24fe283318 --- /dev/null +++ b/src/mongo/s/balancing_window_test.cpp @@ -0,0 +1,94 @@ +/* Copyright 2012 10gen Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the GNU Affero General Public License in all respects + * for all of the code used other than as permitted herein. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you do not + * wish to do so, delete this exception statement from your version. If you + * delete this exception statement from all source files in the program, + * then also delete it in the license file. + */ + +#define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kDefault + +#include "mongo/s/grid.h" +#include "mongo/s/type_settings.h" +#include "mongo/unittest/unittest.h" +#include "mongo/util/log.h" + +namespace mongo { + + using std::string; + +namespace { + + TEST(BalancingWindow, Test) { + // T0 < T1 < now < T2 < T3 and Error + const string T0 = "9:00"; + const string T1 = "11:00"; + boost::posix_time::ptime now(currentDate(), + boost::posix_time::hours(13) + + boost::posix_time::minutes(48)); + const string T2 = "17:00"; + const string T3 = "21:30"; + const string E = "28:35"; + + // closed in the past + BSONObj w1 = BSON(SettingsType::balancerActiveWindow(BSON("start" << T0 << "stop" << T1))); + + // not opened until the future + BSONObj w2 = BSON(SettingsType::balancerActiveWindow(BSON("start" << T2 << "stop" << T3))); + + // open now + BSONObj w3 = BSON(SettingsType::balancerActiveWindow(BSON("start" << T1 << "stop" << T2))); + + // open since last day + BSONObj w4 = BSON(SettingsType::balancerActiveWindow(BSON("start" << T3 << "stop" << T2))); + + ASSERT(!Grid::_inBalancingWindow(w1, now)); + ASSERT(!Grid::_inBalancingWindow(w2, now)); + ASSERT(Grid::_inBalancingWindow(w3, now)); + ASSERT(Grid::_inBalancingWindow(w4, now)); + + // bad input should not stop the balancer + + // empty window + BSONObj w5; + + // missing stop + BSONObj w6 = BSON(SettingsType::balancerActiveWindow(BSON("start" << 1))); + + // missing start + BSONObj w7 = BSON(SettingsType::balancerActiveWindow(BSON("stop" << 1))); + + // active window marker missing + BSONObj w8 = BSON("wrongMarker" << 1 << "start" << 1 << "stop" << 1); + + // garbage in window + BSONObj w9 = BSON(SettingsType::balancerActiveWindow(BSON("start" << T3 << "stop" << E))); + + ASSERT(Grid::_inBalancingWindow(w5, now)); + ASSERT(Grid::_inBalancingWindow(w6, now)); + ASSERT(Grid::_inBalancingWindow(w7, now)); + ASSERT(Grid::_inBalancingWindow(w8, now)); + ASSERT(Grid::_inBalancingWindow(w9, now)); + } + +} // namespace +} // namespace mongo diff --git a/src/mongo/s/chunk.cpp b/src/mongo/s/chunk.cpp index 9814f97f6a3..6df0afcdbb2 100644 --- a/src/mongo/s/chunk.cpp +++ b/src/mongo/s/chunk.cpp @@ -745,7 +745,6 @@ namespace mongo { BSON("$set" << BSON(ChunkType::jumbo(true))), false, // upsert false, // multi - WriteConcernOptions::AllConfigs, NULL ); if ( !result.isOK() ) { @@ -1158,7 +1157,6 @@ namespace mongo { chunkObj, true, // upsert false, // multi - WriteConcernOptions::AllConfigs, NULL ); version.incMinor(); @@ -1447,7 +1445,6 @@ namespace mongo { Status result = clusterDelete( ChunkType::ConfigNS, BSON(ChunkType::ns(_ns)), 0 /* limit */, - WriteConcernOptions::AllConfigs, NULL ); // Make sure we're dropped on the config diff --git a/src/mongo/s/chunk.h b/src/mongo/s/chunk.h index 24d9689488e..46ab7bcf6c2 100644 --- a/src/mongo/s/chunk.h +++ b/src/mongo/s/chunk.h @@ -565,38 +565,6 @@ namespace mongo { friend class TestableChunkManager; }; - // like BSONObjCmp. for use as an STL comparison functor - // key-order in "order" argument must match key-order in shardkey - class ChunkCmp { - public: - ChunkCmp( const BSONObj &order = BSONObj() ) : _cmp( order ) {} - bool operator()( const Chunk &l, const Chunk &r ) const { - return _cmp(l.getMin(), r.getMin()); - } - bool operator()( const ptr<Chunk> l, const ptr<Chunk> r ) const { - return operator()(*l, *r); - } - - // Also support ChunkRanges - bool operator()( const ChunkRange &l, const ChunkRange &r ) const { - return _cmp(l.getMin(), r.getMin()); - } - bool operator()( const boost::shared_ptr<ChunkRange> l, const boost::shared_ptr<ChunkRange> r ) const { - return operator()(*l, *r); - } - private: - BSONObjCmp _cmp; - }; - - /* - struct chunk_lock { - chunk_lock( const Chunk* c ){ - - } - - Chunk _c; - }; - */ inline std::string Chunk::genID() const { return genID(_manager->getns(), _min); } bool setShardVersion( DBClientBase & conn, diff --git a/src/mongo/s/chunk_manager_targeter.cpp b/src/mongo/s/chunk_manager_targeter.cpp index 83ca4cfe07c..1981d9dfb6c 100644 --- a/src/mongo/s/chunk_manager_targeter.cpp +++ b/src/mongo/s/chunk_manager_targeter.cpp @@ -60,18 +60,13 @@ namespace mongo { return config.get(); } - ChunkManagerTargeter::ChunkManagerTargeter() : - _needsTargetingRefresh( false ), _stats( new TargeterStats ) { - } - - Status ChunkManagerTargeter::init( const NamespaceString& nss ) { + ChunkManagerTargeter::ChunkManagerTargeter(const NamespaceString& nss) + : _nss(nss), + _needsTargetingRefresh(false) { - _nss = nss; - - // - // Get the latest metadata information from the cache - // + } + Status ChunkManagerTargeter::init() { DBConfigPtr config; string errMsg; @@ -399,8 +394,9 @@ namespace mongo { // Track autosplit stats for sharded collections // Note: this is only best effort accounting and is not accurate. - if (estDataSize > 0) - _stats->chunkSizeDelta[chunk->getMin()] += estDataSize; + if (estDataSize > 0) { + _stats.chunkSizeDelta[chunk->getMin()] += estDataSize; + } Shard shard = chunk->getShard(); *endpoint = new ShardEndpoint(shard.getName(), @@ -646,7 +642,7 @@ namespace mongo { } const TargeterStats* ChunkManagerTargeter::getStats() const { - return _stats.get(); + return &_stats; } Status ChunkManagerTargeter::refreshIfNeeded( bool *wasChanged ) { diff --git a/src/mongo/s/chunk_manager_targeter.h b/src/mongo/s/chunk_manager_targeter.h index b082ad62eec..aaa115b044b 100644 --- a/src/mongo/s/chunk_manager_targeter.h +++ b/src/mongo/s/chunk_manager_targeter.h @@ -40,7 +40,13 @@ namespace mongo { - struct TargeterStats; + class Grid; + + struct TargeterStats { + // Map of chunk shard minKey -> approximate delta. This is used for deciding + // whether a chunk might need splitting or not. + std::map<BSONObj, int> chunkSizeDelta; + }; /** * NSTargeter based on a ChunkManager implementation. Wraps all exception codepaths and @@ -51,7 +57,7 @@ namespace mongo { class ChunkManagerTargeter : public NSTargeter { public: - ChunkManagerTargeter(); + ChunkManagerTargeter(const NamespaceString& nss); /** * Initializes the ChunkManagerTargeter with the latest targeting information for the @@ -59,7 +65,7 @@ namespace mongo { * * Returns !OK if the information could not be initialized. */ - Status init( const NamespaceString& nss ); + Status init(); const NamespaceString& getNS() const; @@ -101,7 +107,6 @@ namespace mongo { private: // Different ways we can refresh metadata - // TODO: Improve these ways. enum RefreshType { // No refresh is needed RefreshType_None, @@ -111,6 +116,9 @@ namespace mongo { RefreshType_ReloadDatabase }; + typedef std::map<std::string, ChunkVersion> ShardVersionMap; + + /** * Performs an actual refresh from the config server. */ @@ -140,7 +148,14 @@ namespace mongo { long long estDataSize, ShardEndpoint** endpoint) const; - NamespaceString _nss; + // Full namespace of the collection for this targeter + const NamespaceString _nss; + + // Stores whether we need to check the remote server on refresh + bool _needsTargetingRefresh; + + // Represents only the view and not really part of the targeter state. + mutable TargeterStats _stats; // Zero or one of these are filled at all times // If sharded, _manager, if unsharded, _primary, on error, neither @@ -148,20 +163,7 @@ namespace mongo { ShardPtr _primary; // Map of shard->remote shard version reported from stale errors - typedef std::map<std::string, ChunkVersion> ShardVersionMap; ShardVersionMap _remoteShardVersions; - - // Stores whether we need to check the remote server on refresh - bool _needsTargetingRefresh; - - // Represents only the view and not really part of the targeter state. - mutable boost::scoped_ptr<TargeterStats> _stats; - }; - - struct TargeterStats { - // Map of chunk shard minKey -> approximate delta. This is used for deciding - // whether a chunk might need splitting or not. - std::map<BSONObj, int> chunkSizeDelta; }; } // namespace mongo diff --git a/src/mongo/s/cluster_client_internal.cpp b/src/mongo/s/cluster_client_internal.cpp index b0b4fc53f81..42e285bbc65 100644 --- a/src/mongo/s/cluster_client_internal.cpp +++ b/src/mongo/s/cluster_client_internal.cpp @@ -394,7 +394,6 @@ namespace mongo { Status result = clusterInsert( ChangelogType::ConfigNS, changelog.toBSON(), - WriteConcernOptions::AllConfigs, NULL ); if ( !result.isOK() ) { diff --git a/src/mongo/s/cluster_write.cpp b/src/mongo/s/cluster_write.cpp index ec66e80b790..c34189df99a 100644 --- a/src/mongo/s/cluster_write.cpp +++ b/src/mongo/s/cluster_write.cpp @@ -37,6 +37,7 @@ #include "mongo/base/init.h" #include "mongo/base/status.h" +#include "mongo/db/write_concern_options.h" #include "mongo/s/chunk_manager_targeter.h" #include "mongo/s/config.h" #include "mongo/s/dbclient_multi_command.h" @@ -100,6 +101,14 @@ namespace mongo { return indexDoc.obj(); } + + void clusterWrite(const BatchedCommandRequest& request, + BatchedCommandResponse* response, + bool autoSplit) { + + ClusterWriter writer(autoSplit, 0); + writer.write(request, response); + } } /** @@ -195,16 +204,13 @@ namespace mongo { Status clusterInsert( const string& ns, const BSONObj& doc, - const BSONObj& writeConcern, BatchedCommandResponse* response ) { auto_ptr<BatchedInsertRequest> insert( new BatchedInsertRequest() ); insert->addToDocuments( doc ); BatchedCommandRequest request( insert.release() ); request.setNS( ns ); - if ( !writeConcern.isEmpty() ) { - request.setWriteConcern( writeConcern ); - } + request.setWriteConcern(WriteConcernOptions::Acknowledged); BatchedCommandResponse dummyResponse; @@ -221,7 +227,6 @@ namespace mongo { const BSONObj& update, bool upsert, bool multi, - const BSONObj& writeConcern, BatchedCommandResponse* response ) { auto_ptr<BatchedUpdateDocument> updateDoc( new BatchedUpdateDocument() ); updateDoc->setQuery( query ); @@ -231,10 +236,7 @@ namespace mongo { auto_ptr<BatchedUpdateRequest> updateRequest( new BatchedUpdateRequest() ); updateRequest->addToUpdates( updateDoc.release() ); - - if ( !writeConcern.isEmpty() ) { - updateRequest->setWriteConcern( writeConcern ); - } + updateRequest->setWriteConcern(WriteConcernOptions::Acknowledged); BatchedCommandRequest request( updateRequest.release() ); request.setNS( ns ); @@ -252,7 +254,6 @@ namespace mongo { Status clusterDelete( const string& ns, const BSONObj& query, int limit, - const BSONObj& writeConcern, BatchedCommandResponse* response ) { auto_ptr<BatchedDeleteDocument> deleteDoc( new BatchedDeleteDocument ); deleteDoc->setQuery( query ); @@ -260,10 +261,7 @@ namespace mongo { auto_ptr<BatchedDeleteRequest> deleteRequest( new BatchedDeleteRequest() ); deleteRequest->addToDeletes( deleteDoc.release() ); - - if ( !writeConcern.isEmpty() ) { - deleteRequest->setWriteConcern( writeConcern ); - } + deleteRequest->setWriteConcern(WriteConcernOptions::Acknowledged); BatchedCommandRequest request( deleteRequest.release() ); request.setNS( ns ); @@ -281,21 +279,12 @@ namespace mongo { Status clusterCreateIndex( const string& ns, BSONObj keys, bool unique, - const BSONObj& writeConcern, BatchedCommandResponse* response ) { return clusterInsert( NamespaceString( ns ).getSystemIndexesCollection(), createIndexDoc( ns, keys, unique ), - writeConcern, response ); } - void clusterWrite( const BatchedCommandRequest& request, - BatchedCommandResponse* response, - bool autoSplit ) { - ClusterWriter writer( autoSplit, 0 ); - writer.write( request, response ); - } - bool validConfigWC( const BSONObj& writeConcern ) { BSONElement elem(writeConcern["w"]); @@ -368,9 +357,6 @@ namespace mongo { // Config writes and shard writes are done differently string dbName = nss.db().toString(); if ( dbName == "config" || dbName == "admin" ) { - - bool verboseWC = request.isVerboseWC(); - // We only support batch sizes of one for config writes if ( request.sizeWriteOps() != 1 ) { toBatchError( Status( ErrorCodes::InvalidOptions, @@ -393,7 +379,7 @@ namespace mongo { // We need to support "best-effort" writes for pings to the config server. // {w:0} (!verbose) writes are interpreted as best-effort in this case - they may still // error, but do not do the initial fsync check. - configWrite( request, response, verboseWC ); + configWrite(request, response); } else { shardWrite( request, response ); @@ -411,8 +397,8 @@ namespace mongo { void ClusterWriter::shardWrite( const BatchedCommandRequest& request, BatchedCommandResponse* response ) { - ChunkManagerTargeter targeter; - Status targetInitStatus = targeter.init( request.getTargetingNSS() ); + ChunkManagerTargeter targeter(request.getTargetingNSS()); + Status targetInitStatus = targeter.init(); if ( !targetInitStatus.isOK() ) { @@ -434,9 +420,8 @@ namespace mongo { _stats->setShardStats( exec.releaseStats() ); } - void ClusterWriter::configWrite( const BatchedCommandRequest& request, - BatchedCommandResponse* response, - bool fsyncCheck ) { + void ClusterWriter::configWrite(const BatchedCommandRequest& request, + BatchedCommandResponse* response) { DBClientMultiCommand dispatcher; vector<ConnectionString> configHosts = getConfigHosts(); @@ -454,7 +439,7 @@ namespace mongo { } ConfigCoordinator exec( &dispatcher, configHosts ); - exec.executeBatch( request, response, fsyncCheck ); + exec.executeBatch(request, response); } void ClusterWriterStats::setShardStats( BatchWriteExecStats* shardStats ) { diff --git a/src/mongo/s/cluster_write.h b/src/mongo/s/cluster_write.h index a4144fff252..8f64009773a 100644 --- a/src/mongo/s/cluster_write.h +++ b/src/mongo/s/cluster_write.h @@ -50,12 +50,8 @@ namespace mongo { private: - void configWrite( const BatchedCommandRequest& request, - BatchedCommandResponse* response, - bool fsyncCheck ); - - void shardWrite( const BatchedCommandRequest& request, - BatchedCommandResponse* response ); + void configWrite(const BatchedCommandRequest& request, BatchedCommandResponse* response); + void shardWrite(const BatchedCommandRequest& request, BatchedCommandResponse* response); bool _autoSplit; int _timeoutMillis; @@ -81,21 +77,17 @@ namespace mongo { }; /** - * Note: response can NEVER be NULL. - */ - void clusterWrite( const BatchedCommandRequest& request, - BatchedCommandResponse* response, - bool autoSplit ); - - /** + * Used only for writes to the config server, config and admin databases. + * * Note: response can be NULL if you don't care about the write statistics. */ Status clusterInsert( const std::string& ns, const BSONObj& doc, - const BSONObj& writeConcern, BatchedCommandResponse* response ); /** + * Used only for writes to the config server, config and admin databases. + * * Note: response can be NULL if you don't care about the write statistics. */ Status clusterUpdate( const std::string& ns, @@ -103,25 +95,26 @@ namespace mongo { const BSONObj& update, bool upsert, bool multi, - const BSONObj& writeConcern, BatchedCommandResponse* response ); /** + * Used only for writes to the config server, config and admin databases. + * * Note: response can be NULL if you don't care about the write statistics. */ Status clusterDelete( const std::string& ns, const BSONObj& query, int limit, - const BSONObj& writeConcern, BatchedCommandResponse* response ); /** + * Used only for writes to the config server, config and admin databases. + * * Note: response can be NULL if you don't care about the write statistics. */ Status clusterCreateIndex( const std::string& ns, BSONObj keys, bool unique, - const BSONObj& writeConcern, BatchedCommandResponse* response ); } // namespace mongo diff --git a/src/mongo/s/commands/cluster_explain_cmd.cpp b/src/mongo/s/commands/cluster_explain_cmd.cpp index ea80aa75d3b..e2289e048e7 100644 --- a/src/mongo/s/commands/cluster_explain_cmd.cpp +++ b/src/mongo/s/commands/cluster_explain_cmd.cpp @@ -28,73 +28,110 @@ #include "mongo/platform/basic.h" -#include "mongo/s/commands/cluster_explain_cmd.h" - +#include "mongo/db/commands.h" #include "mongo/db/query/explain.h" namespace mongo { - using std::string; - - static ClusterExplainCmd cmdExplainCluster; - - Status ClusterExplainCmd::checkAuthForCommand(ClientBasic* client, - const std::string& dbname, - const BSONObj& cmdObj) { - if (Object != cmdObj.firstElement().type()) { - return Status(ErrorCodes::BadValue, "explain command requires a nested object"); - } - - BSONObj explainObj = cmdObj.firstElement().Obj(); - - Command* commToExplain = Command::findCommand(explainObj.firstElementFieldName()); - if (NULL == commToExplain) { - mongoutils::str::stream ss; - ss << "unknown command: " << explainObj.firstElementFieldName(); - return Status(ErrorCodes::CommandNotFound, ss); + /** + * Implements the explain command on mongos. + * + * "Old-style" explains (i.e. queries which have the $explain flag set), do not run + * through this path. Such explains will be supported for backwards compatibility, + * and must succeed in multiversion clusters. + * + * "New-style" explains use the explain command. When the explain command is routed + * through mongos, it is forwarded to all relevant shards. If *any* shard does not + * support a new-style explain, then the entire explain will fail (i.e. new-style + * explains cannot be used in multiversion clusters). + */ + class ClusterExplainCmd : public Command { + MONGO_DISALLOW_COPYING(ClusterExplainCmd); + public: + ClusterExplainCmd() : Command("explain") { } + + virtual bool isWriteCommandForConfigServer() const { return false; } + + /** + * Running an explain on a secondary requires explicitly setting slaveOk. + */ + virtual bool slaveOk() const { return false; } + virtual bool slaveOverrideOk() const { return true; } + + virtual bool maintenanceOk() const { return false; } + + virtual bool adminOnly() const { return false; } + + virtual void help(std::stringstream& help) const { + help << "explain database reads and writes"; } - return commToExplain->checkAuthForCommand(client, dbname, explainObj); - } - - bool ClusterExplainCmd::run(OperationContext* txn, const string& dbName, - BSONObj& cmdObj, - int options, - string& errmsg, - BSONObjBuilder& result, - bool fromRepl) { - // Should never get explain commands issued from replication. - if (fromRepl) { - Status commandStat(ErrorCodes::IllegalOperation, - "explain command should not be from repl"); - return appendCommandStatus(result, commandStat); - } - - ExplainCommon::Verbosity verbosity; - Status parseStatus = ExplainCommon::parseCmdBSON(cmdObj, &verbosity); - if (!parseStatus.isOK()) { - return appendCommandStatus(result, parseStatus); - } - - // This is the nested command which we are explaining. - BSONObj explainObj = cmdObj.firstElement().Obj(); - - const std::string cmdName = explainObj.firstElementFieldName(); - Command* commToExplain = Command::findCommand(cmdName); - if (NULL == commToExplain) { - mongoutils::str::stream ss; - ss << "Explain failed due to unknown command: " << cmdName; - Status explainStatus(ErrorCodes::CommandNotFound, ss); - return appendCommandStatus(result, explainStatus); + /** + * You are authorized to run an explain if you are authorized to run + * the command that you are explaining. The auth check is performed recursively + * on the nested command. + */ + virtual Status checkAuthForCommand(ClientBasic* client, + const std::string& dbname, + const BSONObj& cmdObj) { + + if (Object != cmdObj.firstElement().type()) { + return Status(ErrorCodes::BadValue, "explain command requires a nested object"); + } + + BSONObj explainObj = cmdObj.firstElement().Obj(); + + Command* commToExplain = Command::findCommand(explainObj.firstElementFieldName()); + if (NULL == commToExplain) { + mongoutils::str::stream ss; + ss << "unknown command: " << explainObj.firstElementFieldName(); + return Status(ErrorCodes::CommandNotFound, ss); + } + + return commToExplain->checkAuthForCommand(client, dbname, explainObj); } - // Actually call the nested command's explain(...) method. - Status explainStatus = commToExplain->explain(txn, dbName, explainObj, verbosity, &result); - if (!explainStatus.isOK()) { - return appendCommandStatus(result, explainStatus); + virtual bool run(OperationContext* txn, const std::string& dbName, + BSONObj& cmdObj, + int options, + std::string& errmsg, + BSONObjBuilder& result, + bool fromRepl) { + + // Should never get explain commands issued from replication. + if (fromRepl) { + Status commandStat(ErrorCodes::IllegalOperation, + "explain command should not be from repl"); + return appendCommandStatus(result, commandStat); + } + + ExplainCommon::Verbosity verbosity; + Status parseStatus = ExplainCommon::parseCmdBSON(cmdObj, &verbosity); + if (!parseStatus.isOK()) { + return appendCommandStatus(result, parseStatus); + } + + // This is the nested command which we are explaining. + BSONObj explainObj = cmdObj.firstElement().Obj(); + + const std::string cmdName = explainObj.firstElementFieldName(); + Command* commToExplain = Command::findCommand(cmdName); + if (NULL == commToExplain) { + mongoutils::str::stream ss; + ss << "Explain failed due to unknown command: " << cmdName; + Status explainStatus(ErrorCodes::CommandNotFound, ss); + return appendCommandStatus(result, explainStatus); + } + + // Actually call the nested command's explain(...) method. + Status explainStatus = commToExplain->explain(txn, dbName, explainObj, verbosity, &result); + if (!explainStatus.isOK()) { + return appendCommandStatus(result, explainStatus); + } + + return true; } - return true; - } + } cmdExplainCluster; } // namespace mongo diff --git a/src/mongo/s/commands/cluster_explain_cmd.h b/src/mongo/s/commands/cluster_explain_cmd.h deleted file mode 100644 index f7388cd1188..00000000000 --- a/src/mongo/s/commands/cluster_explain_cmd.h +++ /dev/null @@ -1,86 +0,0 @@ -/** - * Copyright (C) 2014 MongoDB Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - * As a special exception, the copyright holders give permission to link the - * code of portions of this program with the OpenSSL library under certain - * conditions as described in each individual source file and distribute - * linked combinations including the program with the OpenSSL library. You - * must comply with the GNU Affero General Public License in all respects for - * all of the code used other than as permitted herein. If you modify file(s) - * with this exception, you may extend this exception to your version of the - * file(s), but you are not obligated to do so. If you do not wish to do so, - * delete this exception statement from your version. If you delete this - * exception statement from all source files in the program, then also delete - * it in the license file. - */ - -#pragma once - -#include "mongo/db/commands.h" - -namespace mongo { - - /** - * Implements the explain command on mongos. - * - * "Old-style" explains (i.e. queries which have the $explain flag set), do not run - * through this path. Such explains will be supported for backwards compatibility, - * and must succeed in multiversion clusters. - * - * "New-style" explains use the explain command. When the explain command is routed - * through mongos, it is forwarded to all relevant shards. If *any* shard does not - * support a new-style explain, then the entire explain will fail (i.e. new-style - * explains cannot be used in multiversion clusters). - */ - class ClusterExplainCmd : public Command { - MONGO_DISALLOW_COPYING(ClusterExplainCmd); - public: - ClusterExplainCmd() : Command("explain") { } - - virtual bool isWriteCommandForConfigServer() const { return false; } - - /** - * Running an explain on a secondary requires explicitly setting slaveOk. - */ - virtual bool slaveOk() const { return false; } - virtual bool slaveOverrideOk() const { return true; } - - virtual bool maintenanceOk() const { return false; } - - virtual bool adminOnly() const { return false; } - - virtual void help( std::stringstream& help ) const { - help << "explain database reads and writes"; - } - - /** - * You are authorized to run an explain if you are authorized to run - * the command that you are explaining. The auth check is performed recursively - * on the nested command. - */ - virtual Status checkAuthForCommand(ClientBasic* client, - const std::string& dbname, - const BSONObj& cmdObj); - - virtual bool run(OperationContext* txn, const std::string& dbName, - BSONObj& cmdObj, - int options, - std::string& errmsg, - BSONObjBuilder& result, - bool fromRepl); - - }; - -} // namespace mongo diff --git a/src/mongo/s/commands/cluster_find_cmd.cpp b/src/mongo/s/commands/cluster_find_cmd.cpp index 4d819207f43..e9b2901deab 100644 --- a/src/mongo/s/commands/cluster_find_cmd.cpp +++ b/src/mongo/s/commands/cluster_find_cmd.cpp @@ -28,9 +28,8 @@ #include "mongo/platform/basic.h" -#include "mongo/s/commands/cluster_find_cmd.h" - #include "mongo/db/auth/authorization_session.h" +#include "mongo/db/commands.h" #include "mongo/s/cluster_explain.h" #include "mongo/s/strategy.h" #include "mongo/util/timer.h" @@ -41,71 +40,102 @@ namespace mongo { using std::string; using std::vector; - static ClusterFindCmd cmdFindCluster; + /** + * Implements the find command on mongos. + * + * TODO: this is just a placeholder. It needs to be implemented for real under SERVER-15176. + */ + class ClusterFindCmd : public Command { + MONGO_DISALLOW_COPYING(ClusterFindCmd); + public: + ClusterFindCmd() : Command("find") { } + + virtual bool isWriteCommandForConfigServer() const { return false; } + + virtual bool slaveOk() const { return false; } + + virtual bool slaveOverrideOk() const { return true; } - Status ClusterFindCmd::checkAuthForCommand(ClientBasic* client, - const std::string& dbname, - const BSONObj& cmdObj) { - AuthorizationSession* authzSession = client->getAuthorizationSession(); - ResourcePattern pattern = parseResourcePattern(dbname, cmdObj); + virtual bool maintenanceOk() const { return false; } - if (authzSession->isAuthorizedForActionsOnResource(pattern, ActionType::find)) { - return Status::OK(); + virtual bool adminOnly() const { return false; } + + virtual void help(std::stringstream& help) const { + help << "query for documents"; } - return Status(ErrorCodes::Unauthorized, "unauthorized"); - } - - Status ClusterFindCmd::explain(OperationContext* txn, - const std::string& dbname, - const BSONObj& cmdObj, - ExplainCommon::Verbosity verbosity, - BSONObjBuilder* out) const { - const string fullns = parseNs(dbname, cmdObj); - - // Parse the command BSON to a LiteParsedQuery. - LiteParsedQuery* rawLpq; - bool isExplain = true; - Status lpqStatus = LiteParsedQuery::make(fullns, cmdObj, isExplain, &rawLpq); - if (!lpqStatus.isOK()) { - return lpqStatus; + /** + * In order to run the find command, you must be authorized for the "find" action + * type on the collection. + */ + virtual Status checkAuthForCommand(ClientBasic* client, + const std::string& dbname, + const BSONObj& cmdObj) { + + AuthorizationSession* authzSession = client->getAuthorizationSession(); + ResourcePattern pattern = parseResourcePattern(dbname, cmdObj); + + if (authzSession->isAuthorizedForActionsOnResource(pattern, ActionType::find)) { + return Status::OK(); + } + + return Status(ErrorCodes::Unauthorized, "unauthorized"); + } + + virtual Status explain(OperationContext* txn, + const std::string& dbname, + const BSONObj& cmdObj, + ExplainCommon::Verbosity verbosity, + BSONObjBuilder* out) const { + + const string fullns = parseNs(dbname, cmdObj); + + // Parse the command BSON to a LiteParsedQuery. + LiteParsedQuery* rawLpq; + bool isExplain = true; + Status lpqStatus = LiteParsedQuery::make(fullns, cmdObj, isExplain, &rawLpq); + if (!lpqStatus.isOK()) { + return lpqStatus; + } + auto_ptr<LiteParsedQuery> lpq(rawLpq); + + BSONObjBuilder explainCmdBob; + ClusterExplain::wrapAsExplain(cmdObj, verbosity, &explainCmdBob); + + // We will time how long it takes to run the commands on the shards. + Timer timer; + + vector<Strategy::CommandResult> shardResults; + STRATEGY->commandOp(dbname, + explainCmdBob.obj(), + lpq->getOptions().toInt(), + fullns, + lpq->getFilter(), + &shardResults); + + long long millisElapsed = timer.millis(); + + const char* mongosStageName = ClusterExplain::getStageNameForReadOp(shardResults, cmdObj); + + return ClusterExplain::buildExplainResult(shardResults, + mongosStageName, + millisElapsed, + out); } - auto_ptr<LiteParsedQuery> lpq(rawLpq); - - BSONObjBuilder explainCmdBob; - ClusterExplain::wrapAsExplain(cmdObj, verbosity, &explainCmdBob); - - // We will time how long it takes to run the commands on the shards. - Timer timer; - - vector<Strategy::CommandResult> shardResults; - STRATEGY->commandOp(dbname, - explainCmdBob.obj(), - lpq->getOptions().toInt(), - fullns, - lpq->getFilter(), - &shardResults); - - long long millisElapsed = timer.millis(); - - const char* mongosStageName = ClusterExplain::getStageNameForReadOp(shardResults, cmdObj); - - return ClusterExplain::buildExplainResult(shardResults, - mongosStageName, - millisElapsed, - out); - } - - bool ClusterFindCmd::run(OperationContext* txn, const string& dbName, - BSONObj& cmdObj, - int options, - string& errmsg, - BSONObjBuilder& result, - bool fromRepl) { - // Currently only explains of finds run through the find command. Queries that are not - // explained use the legacy OP_QUERY path. - errmsg = "find command not yet implemented"; - return false; - } + + virtual bool run(OperationContext* txn, + const std::string& dbname, + BSONObj& cmdObj, int options, + std::string& errmsg, + BSONObjBuilder& result, + bool fromRepl) { + + // Currently only explains of finds run through the find command. Queries that are not + // explained use the legacy OP_QUERY path. + errmsg = "find command not yet implemented"; + return false; + } + + } cmdFindCluster; } // namespace mongo diff --git a/src/mongo/s/commands/cluster_find_cmd.h b/src/mongo/s/commands/cluster_find_cmd.h deleted file mode 100644 index c62dd402907..00000000000 --- a/src/mongo/s/commands/cluster_find_cmd.h +++ /dev/null @@ -1,82 +0,0 @@ -/** - * Copyright (C) 2014 MongoDB Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - * As a special exception, the copyright holders give permission to link the - * code of portions of this program with the OpenSSL library under certain - * conditions as described in each individual source file and distribute - * linked combinations including the program with the OpenSSL library. You - * must comply with the GNU Affero General Public License in all respects for - * all of the code used other than as permitted herein. If you modify file(s) - * with this exception, you may extend this exception to your version of the - * file(s), but you are not obligated to do so. If you do not wish to do so, - * delete this exception statement from your version. If you delete this - * exception statement from all source files in the program, then also delete - * it in the license file. - */ - -#pragma once - -#include "mongo/db/commands.h" - -namespace mongo { - - /** - * Implements the find command on mongos. - * - * TODO: this is just a placeholder. It needs to be implemented for real under SERVER-15176. - */ - class ClusterFindCmd : public Command { - MONGO_DISALLOW_COPYING(ClusterFindCmd); - public: - ClusterFindCmd() : Command("find") { } - - virtual bool isWriteCommandForConfigServer() const { return false; } - - virtual bool slaveOk() const { return false; } - - virtual bool slaveOverrideOk() const { return true; } - - virtual bool maintenanceOk() const { return false; } - - virtual bool adminOnly() const { return false; } - - virtual void help(std::stringstream& help) const { - help << "query for documents"; - } - - /** - * In order to run the find command, you must be authorized for the "find" action - * type on the collection. - */ - virtual Status checkAuthForCommand(ClientBasic* client, - const std::string& dbname, - const BSONObj& cmdObj); - - virtual Status explain(OperationContext* txn, - const std::string& dbname, - const BSONObj& cmdObj, - ExplainCommon::Verbosity verbosity, - BSONObjBuilder* out) const; - - virtual bool run(OperationContext* txn, - const std::string& dbname, - BSONObj& cmdObj, int options, - std::string& errmsg, - BSONObjBuilder& result, - bool fromRepl); - - }; - -} // namespace mongo diff --git a/src/mongo/s/commands_admin.cpp b/src/mongo/s/commands_admin.cpp index 01d760ce407..5f0831d598f 100644 --- a/src/mongo/s/commands_admin.cpp +++ b/src/mongo/s/commands_admin.cpp @@ -688,13 +688,7 @@ namespace mongo { // Only need to call ensureIndex on primary shard, since indexes get copied to // receiving shard whenever a migrate occurs. else { - // call ensureIndex with cache=false, see SERVER-1691 - Status result = clusterCreateIndex( ns, - proposedKey, - careAboutUnique, - WriteConcernOptions::Default, - NULL ); - + Status result = clusterCreateIndex(ns, proposedKey, careAboutUnique, NULL); if ( !result.isOK() ) { errmsg = str::stream() << "ensureIndex failed to create index on " << "primary shard: " << result.reason(); @@ -1443,7 +1437,6 @@ namespace mongo { newStatus, false /* do no upsert */, false /* multi */, - WriteConcernOptions::AllConfigs, NULL ); if ( !status.isOK() ) { @@ -1461,7 +1454,6 @@ namespace mongo { Status status = clusterDelete( DatabaseType::ConfigNS, BSON(DatabaseType::name("local")), 0 /* limit */, - WriteConcernOptions::AllConfigs, NULL ); if ( !status.isOK() ) { @@ -1498,7 +1490,6 @@ namespace mongo { Status status = clusterDelete( ShardType::ConfigNS, searchDoc, 0, // limit - WriteConcernOptions::AllConfigs, NULL ); if ( !status.isOK() ) { diff --git a/src/mongo/s/config.cpp b/src/mongo/s/config.cpp index c5ac31d36cb..4d95f66ff74 100644 --- a/src/mongo/s/config.cpp +++ b/src/mongo/s/config.cpp @@ -138,7 +138,6 @@ namespace mongo { val.obj(), true /* upsert */, false /* multi */, - WriteConcernOptions::AllConfigs, NULL); if ( !result.isOK() ) { @@ -602,7 +601,6 @@ namespace mongo { n, true, // upsert false, // multi - WriteConcernOptions::AllConfigs, &response ); if ( !result.isOK() ) { @@ -668,7 +666,6 @@ namespace mongo { Status result = clusterDelete( DatabaseType::ConfigNS, BSON( DatabaseType::name( _name )), 0 /* limit */, - WriteConcernOptions::AllConfigs, NULL ); if ( !result.isOK() ) { @@ -1113,7 +1110,6 @@ namespace mongo { Status result = clusterInsert( SettingsType::ConfigNS, BSON( SettingsType::key("chunksize") << SettingsType::chunksize(chunkSize)), - WriteConcernOptions::AllConfigs, NULL ); if (!result.isOK()) { warning() << "couldn't set chunkSize on config db" << causedBy(result); @@ -1124,7 +1120,6 @@ namespace mongo { Status result = clusterCreateIndex( ChunkType::ConfigNS, BSON( ChunkType::ns() << 1 << ChunkType::min() << 1 ), true, // unique - WriteConcernOptions::AllConfigs, NULL ); if (!result.isOK()) { @@ -1136,7 +1131,6 @@ namespace mongo { ChunkType::shard() << 1 << ChunkType::min() << 1 ), true, // unique - WriteConcernOptions::AllConfigs, NULL ); if (!result.isOK()) { @@ -1148,7 +1142,6 @@ namespace mongo { BSON( ChunkType::ns() << 1 << ChunkType::DEPRECATED_lastmod() << 1 ), true, // unique - WriteConcernOptions::AllConfigs, NULL ); if (!result.isOK()) { @@ -1158,7 +1151,6 @@ namespace mongo { result = clusterCreateIndex( ShardType::ConfigNS, BSON( ShardType::host() << 1 ), true, // unique - WriteConcernOptions::AllConfigs, NULL ); if (!result.isOK()) { @@ -1168,7 +1160,6 @@ namespace mongo { result = clusterCreateIndex(LocksType::ConfigNS, BSON(LocksType::lockID() << 1), false, // unique - WriteConcernOptions::AllConfigs, NULL); if (!result.isOK()) { @@ -1179,7 +1170,6 @@ namespace mongo { BSON( LocksType::state() << 1 << LocksType::process() << 1 ), false, // unique - WriteConcernOptions::AllConfigs, NULL ); if (!result.isOK()) { @@ -1190,7 +1180,6 @@ namespace mongo { result = clusterCreateIndex( LockpingsType::ConfigNS, BSON( LockpingsType::ping() << 1 ), false, // unique - WriteConcernOptions::AllConfigs, NULL ); if (!result.isOK()) { @@ -1201,7 +1190,6 @@ namespace mongo { result = clusterCreateIndex(TagsType::ConfigNS, BSON(TagsType::ns() << 1 << TagsType::min() << 1), true, // unique - WriteConcernOptions::AllConfigs, NULL); if (!result.isOK()) { @@ -1266,7 +1254,6 @@ namespace mongo { Status result = clusterInsert( ChangelogType::ConfigNS, msg, - WriteConcernOptions::AllConfigs, NULL ); if ( !result.isOK() ) { @@ -1296,7 +1283,6 @@ namespace mongo { BSON("$set" << BSON(ShardType::host(newConnectionString))), false, // upsert false, // multi - WriteConcernOptions::AllConfigs, NULL); if ( !result.isOK() ) { diff --git a/src/mongo/s/config.h b/src/mongo/s/config.h index 4284ecf463e..d3626baada5 100644 --- a/src/mongo/s/config.h +++ b/src/mongo/s/config.h @@ -138,8 +138,8 @@ namespace mongo { ChunkManagerPtr shardCollection(const std::string& ns, const ShardKeyPattern& fieldsAndOrder, bool unique, - std::vector<BSONObj>* initPoints = 0, - std::vector<Shard>* initShards = 0); + std::vector<BSONObj>* initPoints, + std::vector<Shard>* initShards = NULL); /** @return true if there was sharding info to remove @@ -214,15 +214,15 @@ namespace mongo { mutable mongo::mutex _hitConfigServerLock; }; + class ConfigServer : public DBConfig { public: - ConfigServer(); ~ConfigServer(); bool ok( bool checkConsistency = false ); - virtual std::string modelServer() { + std::string modelServer() { uassert( 10190 , "ConfigServer not setup" , _primary.ok() ); return _primary.getConnString(); } diff --git a/src/mongo/s/config_upgrade_helpers.cpp b/src/mongo/s/config_upgrade_helpers.cpp index bb60f91a7be..cff2c04e054 100644 --- a/src/mongo/s/config_upgrade_helpers.cpp +++ b/src/mongo/s/config_upgrade_helpers.cpp @@ -298,7 +298,6 @@ namespace mongo { BSON("$set" << setUpgradeIdObj.done()), false, // upsert false, // multi - WriteConcernOptions::AllConfigs, NULL); if ( !result.isOK() ) { @@ -318,7 +317,6 @@ namespace mongo { BSON("$set" << setUpgradeStateObj.done()), false, // upsert false, // multi - WriteConcernOptions::AllConfigs, NULL); log() << "entered critical section for config upgrade" << endl; @@ -359,7 +357,6 @@ namespace mongo { BSON("$set" << setObj.done() << "$unset" << unsetObj.done()), false, // upsert false, // multi, - WriteConcernOptions::AllConfigs, NULL); if ( !result.isOK() ) { diff --git a/src/mongo/s/config_upgrade_v0_to_v6.cpp b/src/mongo/s/config_upgrade_v0_to_v6.cpp index e27b85eebc8..f9011b41cea 100644 --- a/src/mongo/s/config_upgrade_v0_to_v6.cpp +++ b/src/mongo/s/config_upgrade_v0_to_v6.cpp @@ -85,7 +85,6 @@ namespace mongo { versionInfo.toBSON(), true /* upsert */, false /* multi */, - WriteConcernOptions::AllConfigs, NULL); if ( !result.isOK() ) { diff --git a/src/mongo/s/config_upgrade_v5_to_v6.cpp b/src/mongo/s/config_upgrade_v5_to_v6.cpp index 11afb8e65fb..52ec6e43f5b 100644 --- a/src/mongo/s/config_upgrade_v5_to_v6.cpp +++ b/src/mongo/s/config_upgrade_v5_to_v6.cpp @@ -175,7 +175,6 @@ namespace mongo { result = clusterCreateIndex(LocksType::ConfigNS, BSON(LocksType::lockID() << 1), false, // unique - WriteConcernOptions::AllConfigs, NULL); if (!result.isOK()) { diff --git a/src/mongo/s/grid.cpp b/src/mongo/s/grid.cpp index f70431ffc6c..2e44fec54f4 100644 --- a/src/mongo/s/grid.cpp +++ b/src/mongo/s/grid.cpp @@ -43,7 +43,6 @@ #include "mongo/db/namespace_string.h" #include "mongo/db/write_concern.h" #include "mongo/s/cluster_write.h" -#include "mongo/s/grid.h" #include "mongo/s/mongos_options.h" #include "mongo/s/shard.h" #include "mongo/s/type_collection.h" @@ -52,7 +51,6 @@ #include "mongo/s/type_shard.h" #include "mongo/util/fail_point_service.h" #include "mongo/util/log.h" -#include "mongo/util/startup_test.h" #include "mongo/util/stringutils.h" namespace mongo { @@ -442,7 +440,6 @@ namespace mongo { Status result = clusterInsert( ShardType::ConfigNS, shardDoc, - WriteConcernOptions::AllConfigs, NULL ); if ( !result.isOK() ) { @@ -648,69 +645,4 @@ namespace mongo { } Grid grid; - - - // unit tests - - class BalancingWindowUnitTest : public StartupTest { - public: - void run() { - - if (!isMongos()) - return; - - // T0 < T1 < now < T2 < T3 and Error - const string T0 = "9:00"; - const string T1 = "11:00"; - boost::posix_time::ptime now( currentDate(), boost::posix_time::hours( 13 ) + boost::posix_time::minutes( 48 ) ); - const string T2 = "17:00"; - const string T3 = "21:30"; - const string E = "28:35"; - - // closed in the past - BSONObj w1 = BSON( SettingsType::balancerActiveWindow( BSON( "start" << T0 << - "stop" << T1 ) ) ); - // not opened until the future - BSONObj w2 = BSON( SettingsType::balancerActiveWindow( BSON( "start" << T2 << - "stop" << T3 ) ) ); - // open now - BSONObj w3 = BSON( SettingsType::balancerActiveWindow( BSON( "start" << T1 << - "stop" << T2 ) ) ); - // open since last day - BSONObj w4 = BSON( SettingsType::balancerActiveWindow( BSON( "start" << T3 << - "stop" << T2 ) ) ); - - verify( ! Grid::_inBalancingWindow( w1 , now ) ); - verify( ! Grid::_inBalancingWindow( w2 , now ) ); - verify( Grid::_inBalancingWindow( w3 , now ) ); - verify( Grid::_inBalancingWindow( w4 , now ) ); - - // bad input should not stop the balancer - - // empty window - BSONObj w5; - - // missing stop - BSONObj w6 = BSON( SettingsType::balancerActiveWindow( BSON( "start" << 1 ) ) ); - - // missing start - BSONObj w7 = BSON( SettingsType::balancerActiveWindow( BSON( "stop" << 1 ) ) ); - - // active window marker missing - BSONObj w8 = BSON( "wrongMarker" << 1 << "start" << 1 << "stop" << 1 ); - - // garbage in window - BSONObj w9 = BSON( SettingsType::balancerActiveWindow( BSON( "start" << T3 << - "stop" << E ) ) ); - - verify( Grid::_inBalancingWindow( w5 , now ) ); - verify( Grid::_inBalancingWindow( w6 , now ) ); - verify( Grid::_inBalancingWindow( w7 , now ) ); - verify( Grid::_inBalancingWindow( w8 , now ) ); - verify( Grid::_inBalancingWindow( w9 , now ) ); - - LOG(1) << "BalancingWidowObjTest passed" << endl; - } - } BalancingWindowObjTest; - } diff --git a/src/mongo/s/grid.h b/src/mongo/s/grid.h index e7a3f1221d5..a63d0e970d9 100644 --- a/src/mongo/s/grid.h +++ b/src/mongo/s/grid.h @@ -36,10 +36,11 @@ #include "mongo/util/concurrency/mutex.h" #include "mongo/s/config.h" // DBConfigPtr -#include "mongo/s/type_settings.h" namespace mongo { + class SettingsType; + /** * stores meta-information about the grid * TODO: used shard_ptr for DBConfig pointers diff --git a/src/mongo/s/strategy.cpp b/src/mongo/s/strategy.cpp index 90c29a897d0..19cbc5d11d0 100644 --- a/src/mongo/s/strategy.cpp +++ b/src/mongo/s/strategy.cpp @@ -26,8 +26,6 @@ * then also delete it in the license file. */ -// strategy_sharded.cpp - #define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kSharding #include "mongo/platform/basic.h" @@ -472,9 +470,9 @@ namespace mongo { // Note that this implementation will not handle targeting retries and does not completely // emulate write behavior - ChunkManagerTargeter targeter; - Status status = - targeter.init(NamespaceString(targetingBatchItem.getRequest()->getTargetingNS())); + ChunkManagerTargeter targeter(NamespaceString( + targetingBatchItem.getRequest()->getTargetingNS())); + Status status = targeter.init(); if (!status.isOK()) return status; diff --git a/src/mongo/s/write_ops/config_coordinator.cpp b/src/mongo/s/write_ops/config_coordinator.cpp index 66b1d6723c2..6d8e0c25241 100644 --- a/src/mongo/s/write_ops/config_coordinator.cpp +++ b/src/mongo/s/write_ops/config_coordinator.cpp @@ -26,17 +26,19 @@ * it in the license file. */ +#define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kSharding + #include "mongo/s/write_ops/config_coordinator.h" #include "mongo/base/owned_pointer_vector.h" +#include "mongo/db/field_parser.h" #include "mongo/db/lasterror.h" #include "mongo/db/namespace_string.h" #include "mongo/s/write_ops/batched_command_request.h" #include "mongo/s/write_ops/batched_command_response.h" +#include "mongo/util/log.h" #include "mongo/util/net/message.h" -#include "mongo/db/field_parser.h" - namespace mongo { using std::string; @@ -49,162 +51,6 @@ namespace mongo { namespace { - // - // Types to handle the reachability fsync checks - // - - /** - * A BSON serializable object representing an fsync command request - */ - class FsyncRequest : public BSONSerializable { - MONGO_DISALLOW_COPYING(FsyncRequest); - public: - - FsyncRequest() { - } - - bool isValid( std::string* errMsg ) const { - return true; - } - - /** Returns the BSON representation of the entry. */ - BSONObj toBSON() const { - return BSON( "fsync" << true ); - } - - bool parseBSON( const BSONObj& source, std::string* errMsg ) { - // Not implemented - dassert( false ); - return false; - } - - void clear() { - // Not implemented - dassert( false ); - } - - string toString() const { - return toBSON().toString(); - } - }; - - /** - * A BSON serializable object representing an fsync command response - */ - class FsyncResponse : public BSONSerializable { - MONGO_DISALLOW_COPYING(FsyncResponse); - public: - - static const BSONField<int> ok; - static const BSONField<int> errCode; - static const BSONField<string> errMessage; - - FsyncResponse() { - clear(); - } - - bool isValid( std::string* errMsg ) const { - return _isOkSet; - } - - BSONObj toBSON() const { - BSONObjBuilder builder; - - if ( _isOkSet ) builder << ok( _ok ); - if ( _isErrCodeSet ) builder << errCode( _errCode ); - if ( _isErrMessageSet ) builder << errMessage( _errMessage ); - - return builder.obj(); - } - - bool parseBSON( const BSONObj& source, std::string* errMsg ) { - - FieldParser::FieldState result; - - result = FieldParser::extractNumber( source, ok, &_ok, errMsg ); - if ( result == FieldParser::FIELD_INVALID ) - return false; - _isOkSet = result != FieldParser::FIELD_NONE; - - result = FieldParser::extract( source, errCode, &_errCode, errMsg ); - if ( result == FieldParser::FIELD_INVALID ) - return false; - _isErrCodeSet = result != FieldParser::FIELD_NONE; - - result = FieldParser::extract( source, errMessage, &_errMessage, errMsg ); - if ( result == FieldParser::FIELD_INVALID ) - return false; - _isErrMessageSet = result != FieldParser::FIELD_NONE; - - return true; - } - - void clear() { - _ok = false; - _isOkSet = false; - - _errCode = 0; - _isErrCodeSet = false; - - _errMessage = ""; - _isErrMessageSet = false; - } - - string toString() const { - return toBSON().toString(); - } - - int getOk() { - dassert( _isOkSet ); - return _ok; - } - - void setOk( int ok ) { - _ok = ok; - _isOkSet = true; - } - - int getErrCode() { - if ( _isErrCodeSet ) { - return _errCode; - } - else { - return errCode.getDefault(); - } - } - - void setErrCode( int errCode ) { - _errCode = errCode; - _isErrCodeSet = true; - } - - const string& getErrMessage() { - dassert( _isErrMessageSet ); - return _errMessage; - } - - void setErrMessage( StringData errMsg ) { - _errMessage = errMsg.toString(); - _isErrMessageSet = true; - } - - private: - - int _ok; - bool _isOkSet; - - int _errCode; - bool _isErrCodeSet; - - string _errMessage; - bool _isErrMessageSet; - - }; - - const BSONField<int> FsyncResponse::ok( "ok" ); - const BSONField<int> FsyncResponse::errCode( "code" ); - const BSONField<string> FsyncResponse::errMessage( "errmsg" ); - /** * A BSON serializable object representing a setShardVersion command request. */ @@ -380,10 +226,6 @@ namespace mongo { BatchedCommandResponse response; }; - struct ConfigFsyncResponse { - ConnectionString configHost; - FsyncResponse response; - }; } // @@ -398,12 +240,6 @@ namespace mongo { dassert( response->isValid( NULL ) ); } - static void buildFsyncErrorFrom( const Status& status, FsyncResponse* response ) { - response->setOk( false ); - response->setErrCode( static_cast<int>( status.code() ) ); - response->setErrMessage( status.reason() ); - } - static bool areResponsesEqual( const BatchedCommandResponse& responseA, const BatchedCommandResponse& responseB ) { @@ -469,14 +305,6 @@ namespace mongo { "config responses: " + builder.obj().toString() ); } - static void combineFsyncErrors( const vector<ConfigFsyncResponse*>& responses, - BatchedCommandResponse* clientResponse ) { - - clientResponse->setOk( false ); - clientResponse->setErrCode( ErrorCodes::RemoteValidationError ); - clientResponse->setErrMessage( "could not verify config servers were " - "active and reachable before write" ); - } bool ConfigCoordinator::_checkConfigString(BatchedCommandResponse* clientResponse) { // @@ -549,65 +377,57 @@ namespace mongo { * is probably the next step. */ void ConfigCoordinator::executeBatch( const BatchedCommandRequest& clientRequest, - BatchedCommandResponse* clientResponse, - bool fsyncCheck ) { + BatchedCommandResponse* clientResponse) { NamespaceString nss( clientRequest.getNS() ); dassert( nss.db() == "config" || nss.db() == "admin" ); - dassert( clientRequest.sizeWriteOps() == 1u ); - - if ( fsyncCheck ) { - - // - // Sanity check that all configs are still reachable using fsync, preserving legacy - // behavior - // - - OwnedPointerVector<ConfigFsyncResponse> fsyncResponsesOwned; - vector<ConfigFsyncResponse*>& fsyncResponses = fsyncResponsesOwned.mutableVector(); + dassert(clientRequest.sizeWriteOps() == 1u); - // - // Send side - // + // This is an opportunistic check that all config servers look healthy by calling + // getLastError on each one of them. If there was some form of write/journaling error, get + // last error would fail. + { + for (vector<ConnectionString>::iterator it = _configHosts.begin(); + it != _configHosts.end(); + ++it) { - for ( vector<ConnectionString>::iterator it = _configHosts.begin(); - it != _configHosts.end(); ++it ) { - ConnectionString& configHost = *it; - FsyncRequest fsyncRequest; - _dispatcher->addCommand( configHost, "admin", fsyncRequest ); + _dispatcher->addCommand(*it, + "admin", + RawBSONSerializable(BSON("getLastError" << true << + "fsync" << true))); } _dispatcher->sendAll(); - // - // Recv side - // + bool error = false; + while (_dispatcher->numPending()) { + ConnectionString host; + RawBSONSerializable response; - bool fsyncError = false; - while ( _dispatcher->numPending() > 0 ) { + Status status = _dispatcher->recvAny(&host, &response); + if (status.isOK()) { + BSONObj obj = response.toBSON(); - fsyncResponses.push_back( new ConfigFsyncResponse() ); - ConfigFsyncResponse& fsyncResponse = *fsyncResponses.back(); - Status dispatchStatus = _dispatcher->recvAny( &fsyncResponse.configHost, - &fsyncResponse.response ); + LOG(3) << "Response " << obj.toString(); - // We've got to recv everything, no matter what - if ( !dispatchStatus.isOK() ) { - fsyncError = true; - buildFsyncErrorFrom( dispatchStatus, &fsyncResponse.response ); + // If the ok field is anything other than 1, count it as error + if (!obj["ok"].trueValue()) { + error = true; + } } - else if ( !fsyncResponse.response.getOk() ) { - fsyncError = true; + else { + error = true; } } - if ( fsyncError ) { - combineFsyncErrors( fsyncResponses, clientResponse ); + // All responses should have been gathered by this point + if (error) { + clientResponse->setOk(false); + clientResponse->setErrCode(ErrorCodes::RemoteValidationError); + clientResponse->setErrMessage("Could not verify that config servers were active" + " and reachable before write"); return; } - else { - fsyncResponsesOwned.clear(); - } } if (!_checkConfigString(clientResponse)) { diff --git a/src/mongo/s/write_ops/config_coordinator.h b/src/mongo/s/write_ops/config_coordinator.h index f90c5b83dc4..90fd24f694e 100644 --- a/src/mongo/s/write_ops/config_coordinator.h +++ b/src/mongo/s/write_ops/config_coordinator.h @@ -43,9 +43,7 @@ namespace mongo { ConfigCoordinator( MultiCommandDispatch* dispatcher, const std::vector<ConnectionString>& configHosts ); - void executeBatch( const BatchedCommandRequest& request, - BatchedCommandResponse* response, - bool fsyncCheck ); + void executeBatch(const BatchedCommandRequest& request, BatchedCommandResponse* response); private: |