diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/mongo/SConscript | 14 | ||||
-rw-r--r-- | src/mongo/db/cmdline.cpp | 13 | ||||
-rw-r--r-- | src/mongo/db/cmdline.h | 21 | ||||
-rw-r--r-- | src/mongo/db/commands/parameters.cpp | 202 | ||||
-rw-r--r-- | src/mongo/db/dbcommands_generic.cpp | 158 | ||||
-rw-r--r-- | src/mongo/db/repl.cpp | 71 | ||||
-rw-r--r-- | src/mongo/db/server_parameters.cpp | 64 | ||||
-rw-r--r-- | src/mongo/db/server_parameters.h | 110 | ||||
-rw-r--r-- | src/mongo/db/server_parameters_inline.h | 48 | ||||
-rw-r--r-- | src/mongo/db/server_parameters_test.cpp | 54 |
10 files changed, 536 insertions, 219 deletions
diff --git a/src/mongo/SConscript b/src/mongo/SConscript index bd4a4268de0..0c13b875ae9 100644 --- a/src/mongo/SConscript +++ b/src/mongo/SConscript @@ -163,6 +163,15 @@ env.CppUnitTest("processinfo_test", ["util/processinfo_test.cpp"], LIBDEPS=["processinfo"]) +env.StaticLibrary("server_parameters", + ["db/server_parameters.cpp"], + LIBDEPS=["foundation","bson"]) + +env.CppUnitTest("server_parameters_test", + [ "db/server_parameters_test.cpp" ], + LIBDEPS=["server_parameters"] ) + + env.StaticLibrary("fail_point", ["util/fail_point.cpp", "util/fail_point_registry.cpp", @@ -190,6 +199,7 @@ env.StaticLibrary("coredb", [ "db/commands/hashcmd.cpp", "db/commands/isself.cpp", "db/commands/server_status.cpp", + "db/commands/parameters.cpp", "db/pipeline/pipeline.cpp", "db/dbcommands_generic.cpp", "db/dbwebserver.cpp", @@ -232,7 +242,9 @@ env.StaticLibrary("coredb", [ "db/stats/top.cpp", "s/shardconnection.cpp", ], - LIBDEPS=['db/auth/auth', 'db/auth/serverauth']) + LIBDEPS=['db/auth/auth', + 'db/auth/serverauth', + 'server_parameters']) coreServerFiles = [ "db/common.cpp", "util/net/miniwebserver.cpp", diff --git a/src/mongo/db/cmdline.cpp b/src/mongo/db/cmdline.cpp index cd046c18e9f..105ac59435c 100644 --- a/src/mongo/db/cmdline.cpp +++ b/src/mongo/db/cmdline.cpp @@ -453,17 +453,4 @@ namespace { void printCommandLineOpts() { log() << "options: " << parsedOpts << endl; } - - map<string,ParameterValidator*>* pv_all(NULL); - - ParameterValidator::ParameterValidator( const string& name ) : _name( name ) { - if ( ! pv_all) - pv_all = new map<string,ParameterValidator*>(); - (*pv_all)[_name] = this; - } - - ParameterValidator* ParameterValidator::get( const string& name ) { - return mapFindWithDefault(*pv_all, name, static_cast<ParameterValidator*>(NULL)); - } - } diff --git a/src/mongo/db/cmdline.h b/src/mongo/db/cmdline.h index 0396ede067b..2b56b51f958 100644 --- a/src/mongo/db/cmdline.h +++ b/src/mongo/db/cmdline.h @@ -219,26 +219,5 @@ namespace mongo { extern CmdLine cmdLine; void printCommandLineOpts(); - - /** - * used for setParameter command - * so you can write validation code that lives with code using it - * rather than all in the command place - * also lets you have mongos or mongod specific code - * without pulling it all sorts of things - */ - class ParameterValidator { - public: - ParameterValidator( const std::string& name ); - virtual ~ParameterValidator() {} - - virtual bool isValid( BSONElement e , std::string& errmsg ) const = 0; - - static ParameterValidator * get( const std::string& name ); - - private: - const std::string _name; - }; - } diff --git a/src/mongo/db/commands/parameters.cpp b/src/mongo/db/commands/parameters.cpp new file mode 100644 index 00000000000..83b5efc1668 --- /dev/null +++ b/src/mongo/db/commands/parameters.cpp @@ -0,0 +1,202 @@ +// parameters.cpp + +/** +* Copyright (C) 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/>. +*/ + +#include "mongo/pch.h" +#include "mongo/db/commands.h" +#include "mongo/db/cmdline.h" +#include "mongo/client/dbclient_rs.h" +#include "mongo/db/server_parameters.h" + +namespace mongo { + + const char* fetchReplIndexPrefetchParam(); + + class CmdGet : public Command { + public: + CmdGet() : Command( "getParameter" ) { } + virtual bool slaveOk() const { return true; } + virtual bool adminOnly() const { return true; } + virtual LockType locktype() const { return NONE; } + virtual void addRequiredPrivileges(const std::string& dbname, + const BSONObj& cmdObj, + std::vector<Privilege>* out) { + ActionSet actions; + actions.addAction(ActionType::getParameter); + out->push_back(Privilege(AuthorizationManager::SERVER_RESOURCE_NAME, actions)); + } + virtual void help( stringstream &help ) const { + help << "get administrative option(s)\nexample:\n"; + help << "{ getParameter:1, notablescan:1 }\n"; + help << "supported so far:\n"; + help << " quiet\n"; + help << " notablescan\n"; + help << " logLevel\n"; + help << " syncdelay\n"; + help << "{ getParameter:'*' } to get everything\n"; + } + bool run(const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl ) { + bool all = *cmdObj.firstElement().valuestrsafe() == '*'; + + int before = result.len(); + + if( all || cmdObj.hasElement("quiet") ) { + result.append("quiet", cmdLine.quiet ); + } + if( all || cmdObj.hasElement("notablescan") ) { + result.append("notablescan", cmdLine.noTableScan); + } + if( all || cmdObj.hasElement("logLevel") ) { + result.append("logLevel", logLevel); + } + if( all || cmdObj.hasElement("syncdelay") ) { + result.append("syncdelay", cmdLine.syncdelay); + } + if (all || cmdObj.hasElement("replIndexPrefetch")) { + result.append("replIndexPrefetch", fetchReplIndexPrefetchParam()); + } + + const ServerParameter::Map& m = ServerParameterSet::getGlobal()->getMap(); + for ( ServerParameter::Map::const_iterator i = m.begin(); i != m.end(); ++i ) { + if ( all || cmdObj.hasElement( i->first.c_str() ) ) { + i->second->append( result ); + } + } + + if ( before == result.len() ) { + errmsg = "no option found to get"; + return false; + } + return true; + } + } cmdGet; + + // tempish + bool setParmsMongodSpecific(const string& dbname, BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool fromRepl ); + + class CmdSet : public Command { + public: + CmdSet() : Command( "setParameter" ) { } + virtual bool slaveOk() const { return true; } + virtual bool adminOnly() const { return true; } + virtual LockType locktype() const { return NONE; } + virtual void addRequiredPrivileges(const std::string& dbname, + const BSONObj& cmdObj, + std::vector<Privilege>* out) { + ActionSet actions; + actions.addAction(ActionType::setParameter); + out->push_back(Privilege(AuthorizationManager::SERVER_RESOURCE_NAME, actions)); + } + virtual void help( stringstream &help ) const { + help << "set administrative option(s)\n"; + help << "{ setParameter:1, <param>:<value> }\n"; + help << "supported so far:\n"; + help << " journalCommitInterval\n"; + help << " logLevel\n"; + help << " notablescan\n"; + help << " quiet\n"; + help << " syncdelay\n"; + } + bool run(const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl ) { + int s = 0; + bool found = setParmsMongodSpecific(dbname, cmdObj, errmsg, result, fromRepl); + if( cmdObj.hasElement("journalCommitInterval") ) { + if( !cmdLine.dur ) { + errmsg = "journaling is off"; + return false; + } + int x = (int) cmdObj["journalCommitInterval"].Number(); + verify( x > 1 && x < 500 ); + cmdLine.journalCommitInterval = x; + log() << "setParameter journalCommitInterval=" << x << endl; + s++; + } + if( cmdObj.hasElement("notablescan") ) { + verify( !cmdLine.isMongos() ); + if( s == 0 ) + result.append("was", cmdLine.noTableScan); + cmdLine.noTableScan = cmdObj["notablescan"].Bool(); + s++; + } + if( cmdObj.hasElement("quiet") ) { + if( s == 0 ) + result.append("was", cmdLine.quiet ); + cmdLine.quiet = cmdObj["quiet"].Bool(); + s++; + } + if( cmdObj.hasElement("syncdelay") ) { + verify( !cmdLine.isMongos() ); + if( s == 0 ) + result.append("was", cmdLine.syncdelay ); + cmdLine.syncdelay = cmdObj["syncdelay"].Number(); + s++; + } + if( cmdObj.hasElement( "logLevel" ) ) { + if( s == 0 ) + result.append("was", logLevel ); + logLevel = cmdObj["logLevel"].numberInt(); + s++; + } + if( cmdObj.hasElement( "traceExceptions" ) ) { + if( s == 0 ) result.append( "was", DBException::traceExceptions ); + DBException::traceExceptions = cmdObj["traceExceptions"].Bool(); + s++; + } + if( cmdObj.hasElement( "replMonitorMaxFailedChecks" ) ) { + if( s == 0 ) result.append( "was", ReplicaSetMonitor::getMaxFailedChecks() ); + ReplicaSetMonitor::setMaxFailedChecks( + cmdObj["replMonitorMaxFailedChecks"].numberInt() ); + s++; + } + + const ServerParameter::Map& m = ServerParameterSet::getGlobal()->getMap(); + BSONObjIterator i( cmdObj ); + i.next(); // skip past command name + while ( i.more() ) { + BSONElement e = i.next(); + ServerParameter::Map::const_iterator j = m.find( e.fieldName() ); + if ( j == m.end() ) + continue; + + if ( ! j->second->allowedToChangeAtRuntime() ) { + errmsg = str::stream() + << "not allowed to change [" + << e.fieldName() + << "] at runtime"; + return false; + } + + Status status = j->second->set( e ); + if ( status.isOK() ) { + s++; + continue; + } + errmsg = status.reason(); + result.append( "code", status.code() ); + return false; + } + + if( s == 0 && !found ) { + errmsg = "no option found to set, use help:true to see options "; + return false; + } + + return true; + } + } cmdSet; + +} diff --git a/src/mongo/db/dbcommands_generic.cpp b/src/mongo/db/dbcommands_generic.cpp index f0e762c053c..123fe1e314a 100644 --- a/src/mongo/db/dbcommands_generic.cpp +++ b/src/mongo/db/dbcommands_generic.cpp @@ -135,164 +135,6 @@ namespace mongo { } } cmdBuildInfo; - /** experimental. either remove or add support in repl sets also. in a repl set, getting this setting from the - repl set config could make sense. - */ - unsigned replApplyBatchSize = 1; - - const char* fetchReplIndexPrefetchParam(); - - class CmdGet : public Command { - public: - CmdGet() : Command( "getParameter" ) { } - virtual bool slaveOk() const { return true; } - virtual bool adminOnly() const { return true; } - virtual LockType locktype() const { return NONE; } - virtual void addRequiredPrivileges(const std::string& dbname, - const BSONObj& cmdObj, - std::vector<Privilege>* out) { - ActionSet actions; - actions.addAction(ActionType::getParameter); - out->push_back(Privilege(AuthorizationManager::SERVER_RESOURCE_NAME, actions)); - } - virtual void help( stringstream &help ) const { - help << "get administrative option(s)\nexample:\n"; - help << "{ getParameter:1, notablescan:1 }\n"; - help << "supported so far:\n"; - help << " quiet\n"; - help << " notablescan\n"; - help << " logLevel\n"; - help << " syncdelay\n"; - help << "{ getParameter:'*' } to get everything\n"; - } - bool run(const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl ) { - bool all = *cmdObj.firstElement().valuestrsafe() == '*'; - - int before = result.len(); - - if( all || cmdObj.hasElement("quiet") ) { - result.append("quiet", cmdLine.quiet ); - } - if( all || cmdObj.hasElement("notablescan") ) { - result.append("notablescan", cmdLine.noTableScan); - } - if( all || cmdObj.hasElement("logLevel") ) { - result.append("logLevel", logLevel); - } - if( all || cmdObj.hasElement("syncdelay") ) { - result.append("syncdelay", cmdLine.syncdelay); - } - if( all || cmdObj.hasElement("replApplyBatchSize") ) { - result.append("replApplyBatchSize", replApplyBatchSize); - } - if (all || cmdObj.hasElement("replIndexPrefetch")) { - result.append("replIndexPrefetch", fetchReplIndexPrefetchParam()); - } - if ( before == result.len() ) { - errmsg = "no option found to get"; - return false; - } - return true; - } - } cmdGet; - - // tempish - bool setParmsMongodSpecific(const string& dbname, BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool fromRepl ); - - class CmdSet : public Command { - public: - CmdSet() : Command( "setParameter" ) { } - virtual bool slaveOk() const { return true; } - virtual bool adminOnly() const { return true; } - virtual LockType locktype() const { return NONE; } - virtual void addRequiredPrivileges(const std::string& dbname, - const BSONObj& cmdObj, - std::vector<Privilege>* out) { - ActionSet actions; - actions.addAction(ActionType::setParameter); - out->push_back(Privilege(AuthorizationManager::SERVER_RESOURCE_NAME, actions)); - } - virtual void help( stringstream &help ) const { - help << "set administrative option(s)\n"; - help << "{ setParameter:1, <param>:<value> }\n"; - help << "supported so far:\n"; - help << " journalCommitInterval\n"; - help << " logLevel\n"; - help << " notablescan\n"; - help << " quiet\n"; - help << " syncdelay\n"; - } - bool run(const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl ) { - int s = 0; - bool found = setParmsMongodSpecific(dbname, cmdObj, errmsg, result, fromRepl); - if( cmdObj.hasElement("journalCommitInterval") ) { - if( !cmdLine.dur ) { - errmsg = "journaling is off"; - return false; - } - int x = (int) cmdObj["journalCommitInterval"].Number(); - verify( x > 1 && x < 500 ); - cmdLine.journalCommitInterval = x; - log() << "setParameter journalCommitInterval=" << x << endl; - s++; - } - if( cmdObj.hasElement("notablescan") ) { - verify( !cmdLine.isMongos() ); - if( s == 0 ) - result.append("was", cmdLine.noTableScan); - cmdLine.noTableScan = cmdObj["notablescan"].Bool(); - s++; - } - if( cmdObj.hasElement("quiet") ) { - if( s == 0 ) - result.append("was", cmdLine.quiet ); - cmdLine.quiet = cmdObj["quiet"].Bool(); - s++; - } - if( cmdObj.hasElement("syncdelay") ) { - verify( !cmdLine.isMongos() ); - if( s == 0 ) - result.append("was", cmdLine.syncdelay ); - cmdLine.syncdelay = cmdObj["syncdelay"].Number(); - s++; - } - if( cmdObj.hasElement( "logLevel" ) ) { - if( s == 0 ) - result.append("was", logLevel ); - logLevel = cmdObj["logLevel"].numberInt(); - s++; - } - if( cmdObj.hasElement( "replApplyBatchSize" ) ) { - if( s == 0 ) - result.append("was", replApplyBatchSize ); - BSONElement e = cmdObj["replApplyBatchSize"]; - ParameterValidator * v = ParameterValidator::get( e.fieldName() ); - verify( v ); - if ( ! v->isValid( e , errmsg ) ) - return false; - replApplyBatchSize = e.numberInt(); - s++; - } - if( cmdObj.hasElement( "traceExceptions" ) ) { - if( s == 0 ) result.append( "was", DBException::traceExceptions ); - DBException::traceExceptions = cmdObj["traceExceptions"].Bool(); - s++; - } - if( cmdObj.hasElement( "replMonitorMaxFailedChecks" ) ) { - if( s == 0 ) result.append( "was", ReplicaSetMonitor::getMaxFailedChecks() ); - ReplicaSetMonitor::setMaxFailedChecks( - cmdObj["replMonitorMaxFailedChecks"].numberInt() ); - s++; - } - - if( s == 0 && !found ) { - errmsg = "no option found to set, use help:true to see options "; - return false; - } - - return true; - } - } cmdSet; class PingCommand : public Command { public: diff --git a/src/mongo/db/repl.cpp b/src/mongo/db/repl.cpp index c3b326683ee..5a66836bc42 100644 --- a/src/mongo/db/repl.cpp +++ b/src/mongo/db/repl.cpp @@ -50,6 +50,7 @@ #include "pcrecpp.h" #include "mongo/db/commands/server_status.h" #include "mongo/db/instance.h" +#include "mongo/db/server_parameters.h" #include "mongo/db/queryutil.h" namespace mongo { @@ -803,7 +804,49 @@ namespace mongo { } } - extern unsigned replApplyBatchSize; + class ReplApplyBatchSize : public ServerParameter { + public: + ReplApplyBatchSize() + : ServerParameter( ServerParameterSet::getGlobal(), "replApplyBatchSize" ), + _value( 1 ) { + } + + int get() const { return _value; } + + virtual void append( BSONObjBuilder& b ) { + b.append( name(), _value ); + } + + virtual Status set( const BSONElement& newValuElement ) { + return set( newValuElement.numberInt() ); + } + + virtual Status set( int b ) { + if( b < 1 || b > 1024 ) { + return Status( ErrorCodes::BadValue, + "replApplyBatchSize has to be >= 1 and < 1024" ); + } + + if ( replSettings.slavedelay != 0 && b > 1 ) { + return Status( ErrorCodes::BadValue, + "can't use a batch size > 1 with slavedelay" ); + } + if ( ! replSettings.slave ) { + return Status( ErrorCodes::BadValue, + "can't set replApplyBatchSize on a non-slave machine" ); + } + + _value = b; + return Status::OK(); + } + + virtual Status setFromString( const string& str ) { + return set( atoi( str.c_str() ) ); + } + + int _value; + + } replApplyBatchSize; /* slave: pull some data from the master's oplog note: not yet in db mutex at this point. @@ -1008,7 +1051,7 @@ namespace mongo { BSONObj op = oplogReader.next(); - unsigned b = replApplyBatchSize; + int b = replApplyBatchSize.get(); bool justOne = b == 1; scoped_ptr<Lock::GlobalWrite> lk( justOne ? 0 : new Lock::GlobalWrite() ); while( 1 ) { @@ -1541,30 +1584,6 @@ namespace mongo { tp.join(); } - class ReplApplyBatchSizeValidator : public ParameterValidator { - public: - ReplApplyBatchSizeValidator() : ParameterValidator( "replApplyBatchSize" ) {} - - virtual bool isValid( BSONElement e , string& errmsg ) const { - int b = e.numberInt(); - if( b < 1 || b > 1024 ) { - errmsg = "replApplyBatchSize has to be >= 1 and < 1024"; - return false; - } - - if ( replSettings.slavedelay != 0 && b > 1 ) { - errmsg = "can't use a batch size > 1 with slavedelay"; - return false; - } - if ( ! replSettings.slave ) { - errmsg = "can't set replApplyBatchSize on a non-slave machine"; - return false; - } - - return true; - } - } replApplyBatchSizeValidator; - /** we allow queries to SimpleSlave's */ void replVerifyReadsOk(const ParsedQuery* pq) { if( replSet ) { diff --git a/src/mongo/db/server_parameters.cpp b/src/mongo/db/server_parameters.cpp new file mode 100644 index 00000000000..05565a79044 --- /dev/null +++ b/src/mongo/db/server_parameters.cpp @@ -0,0 +1,64 @@ +// server_parameters.cpp + +/** +* Copyright (C) 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/>. +*/ + +#include "mongo/pch.h" + +#include "mongo/db/server_parameters.h" + +namespace mongo { + + namespace { + ServerParameterSet* GLOBAL = NULL; + } + + ServerParameter::ServerParameter( ServerParameterSet* sps, const std::string& name ) + : _name( name ) { + + if ( sps ) { + sps->add( this ); + } + } + + ServerParameter::~ServerParameter() { + } + + ServerParameterSet* ServerParameterSet::getGlobal() { + if ( !GLOBAL ) { + GLOBAL = new ServerParameterSet(); + } + return GLOBAL; + } + + void ServerParameterSet::add( ServerParameter* sp ) { + ServerParameter*& x = _map[sp->name()]; + if ( x ) abort(); + x = sp; + } + + + // obviously this is a sample, not real + // below this is all samples and won't be in the real one + + ExportedServerParameter<int> logLevelParam( ServerParameterSet::getGlobal(), "logLevel", &logLevel ); + + string x = "a"; + ExportedServerParameter<string> xxx( ServerParameterSet::getGlobal(), "xxx", &x ); + + MONGO_EXPORT_SERVER_PARAMETER( y, string, "hh" ); + +} diff --git a/src/mongo/db/server_parameters.h b/src/mongo/db/server_parameters.h new file mode 100644 index 00000000000..c1368a979df --- /dev/null +++ b/src/mongo/db/server_parameters.h @@ -0,0 +1,110 @@ +// server_parameters.h + +/** +* Copyright (C) 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/>. +*/ + +#pragma once + +#include <string> +#include <map> + +#include "mongo/base/status.h" +#include "mongo/db/jsobj.h" + +namespace mongo { + + class ServerParameterSet; + + /** + * Lets you make server level settings easily configurable. + * Hooks into (set|get)Paramter, as well as command line processing + */ + class ServerParameter { + public: + typedef std::map< std::string, ServerParameter* > Map; + + ServerParameter( ServerParameterSet* sps, const std::string& name ); + virtual ~ServerParameter(); + + std::string name() const { return _name; } + + /** + * @return if you can set on command line or config file + */ + virtual bool allowedToChangeAtStartup() const { return true; } + + /** + * @param if you can use (get|set)Parameter + */ + virtual bool allowedToChangeAtRuntime() const { return true; } + + + virtual void append( BSONObjBuilder& b ) = 0; + + virtual Status set( const BSONElement& newValueElement ) = 0; + + virtual Status setFromString( const string& str ) = 0; + + private: + string _name; + }; + + class ServerParameterSet { + public: + typedef std::map< std::string, ServerParameter* > Map; + + void add( ServerParameter* sp ); + + const Map& getMap() const { return _map; } + + static ServerParameterSet* getGlobal(); + + private: + Map _map; + }; + + template<typename T> + class ExportedServerParameter : public ServerParameter { + public: + ExportedServerParameter( ServerParameterSet* sps, const std::string& name, T* value ) + : ServerParameter( sps, name ), _value( value ) {} + virtual ~ExportedServerParameter() {} + + virtual void append( BSONObjBuilder& b ) { + b.append( name(), *_value ); + } + + virtual Status set( const BSONElement& newValueElement ); + virtual Status set( const T& newValue ); + + virtual const T& get() const { return *_value; } + + virtual Status setFromString( const string& str ); + + protected: + + virtual Status validate( const T& potentialNewValue ){ return Status::OK(); } + + T* _value; // owned elsewhere + }; + +#define MONGO_EXPORT_SERVER_PARAMETER( NAME, TYPE, INITIAL_VALUE ) \ + TYPE NAME = INITIAL_VALUE; \ + ExportedServerParameter<TYPE> _##NAME( ServerParameterSet::getGlobal(), #NAME, &NAME ); + +} + +#include "server_parameters_inline.h" diff --git a/src/mongo/db/server_parameters_inline.h b/src/mongo/db/server_parameters_inline.h new file mode 100644 index 00000000000..6e8764e17dd --- /dev/null +++ b/src/mongo/db/server_parameters_inline.h @@ -0,0 +1,48 @@ +// server_parameters_inline.h + +#include "mongo/util/stringutils.h" + +namespace mongo { + + template<typename T> + inline Status ExportedServerParameter<T>::set( const BSONElement& newValueElement ) { + T newValue; + + if ( !newValueElement.coerce( &newValue) ) + return Status( ErrorCodes::BadValue, "can't set value" ); + + return set( newValue ); + } + + template<typename T> + inline Status ExportedServerParameter<T>::set( const T& newValue ) { + + Status v = validate( newValue ); + if ( !v.isOK() ) + return v; + + *_value = newValue; + return Status::OK(); + } + + template<> + inline Status ExportedServerParameter<int>::setFromString( const string& str ) { + return set( atoi(str.c_str() ) ); + } + + template<> + inline Status ExportedServerParameter<string>::setFromString( const string& str ) { + return set( str ); + } + + + template<> + inline Status ExportedServerParameter< vector<string> >::setFromString( const string& str ) { + vector<string> v; + splitStringDelim( str, &v, ',' ); + return set( v ); + } + + + +} diff --git a/src/mongo/db/server_parameters_test.cpp b/src/mongo/db/server_parameters_test.cpp new file mode 100644 index 00000000000..04fe1eaf2a5 --- /dev/null +++ b/src/mongo/db/server_parameters_test.cpp @@ -0,0 +1,54 @@ +// server_parameters_test.cpp + +#include "mongo/unittest/unittest.h" + +#include "mongo/db/server_parameters.h" + +namespace mongo { + + TEST( ServerParameters, Simple1 ) { + int f = 5; + ExportedServerParameter<int> ff( NULL, "ff", &f ); + ASSERT_EQUALS( "ff" , ff.name() ); + ASSERT_EQUALS( 5, ff.get() ); + + ff.set( 6 ); + ASSERT_EQUALS( 6, ff.get() ); + ASSERT_EQUALS( 6, f ); + + ff.set( BSON( "x" << 7 ).firstElement() ); + ASSERT_EQUALS( 7, ff.get() ); + ASSERT_EQUALS( 7, f ); + + ff.setFromString( "8" ); + ASSERT_EQUALS( 8, ff.get() ); + ASSERT_EQUALS( 8, f ); + + } + + TEST( ServerParameters, Vector1 ) { + vector<string> v; + + ExportedServerParameter< vector<string> > vv( NULL, "vv", &v ); + + BSONObj x = BSON( "x" << BSON_ARRAY( "a" << "b" << "c" ) ); + vv.set( x.firstElement() ); + + ASSERT_EQUALS( 3U, v.size() ); + ASSERT_EQUALS( "a", v[0] ); + ASSERT_EQUALS( "b", v[1] ); + ASSERT_EQUALS( "c", v[2] ); + + BSONObjBuilder b; + vv.append( b ); + BSONObj y = b.obj(); + ASSERT( x.firstElement().woCompare( y.firstElement(), false ) == 0 ); + + + vv.setFromString( "d,e" ); + ASSERT_EQUALS( 2U, v.size() ); + ASSERT_EQUALS( "d", v[0] ); + ASSERT_EQUALS( "e", v[1] ); + } + +} |