Skip to content

Commit bcd0d24

Browse files
committed
CXX-274 Backport server r2.6.3..r2.6.4 changes
1 parent 2f94619 commit bcd0d24

15 files changed

+384
-123
lines changed

SConstruct

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ add_option( "no-glibc-check" , "don't check for new versions of glibc" , 0 , Fal
223223
add_option( "mm", "use main memory instead of memory mapped files" , 0 , True )
224224
add_option( "asio" , "Use Asynchronous IO (NOT READY YET)" , 0 , True )
225225
add_option( "ssl" , "Enable SSL" , 0 , True )
226+
add_option( "ssl-fips-capability", "Enable the ability to activate FIPS 140-2 mode", 0, True );
226227

227228
# library choices
228229
add_option( "usev8" , "use v8 for javascript" , 0 , True )
@@ -909,6 +910,8 @@ if has_option( "ssl" ):
909910
else:
910911
env.Append( LIBS=["ssl"] )
911912
env.Append( LIBS=["crypto"] )
913+
if has_option("ssl-fips-capability"):
914+
env.Append( CPPDEFINES=["MONGO_SSL_FIPS"] )
912915

913916
try:
914917
umask = os.umask(022)

src/SConscript.client

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ clientHeaders = [
207207
'mongo/platform/float_utils.h',
208208
'mongo/platform/hash_namespace.h',
209209
'mongo/platform/process_id.h',
210+
'mongo/platform/random.h',
210211
'mongo/platform/unordered_map.h',
211212
'mongo/platform/windows_basic.h',
212213
'mongo/util/allocator.h',

src/mongo/SConscript

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ unittests = [
4040
'client/dbclient_rs_test',
4141
'client/scoped_db_conn_test',
4242
'client/replica_set_monitor_test',
43+
'db/dbmessage_test',
4344
'dbtests/jsobjtests',
4445
'dbtests/jsontests',
4546
'dbtests/mock_dbclient_conn_test',

src/mongo/base/error_codes.err

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ error_code("NoProgressMade", 82)
8585
error_code("RemoteResultsUnavailable", 83)
8686
error_code("IndexOptionsConflict", 85 )
8787
error_code("IndexKeySpecsConflict", 86 )
88+
error_code("OutdatedClient", 101)
89+
error_code("IncompatibleAuditMetadata", 102)
8890

8991
# Non-sequential error codes (for compatibility only)
9092
error_code("NetworkTimeout", 89)

src/mongo/bson/bson-inl.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -737,11 +737,16 @@ namespace mongo {
737737
s << __oid() << "')";
738738
break;
739739
case BinData:
740-
s << "BinData";
741-
if (full) {
740+
s << "BinData(" << binDataType() << ", ";
741+
{
742742
int len;
743-
const char* data = binDataClean(len);
744-
s << '(' << binDataType() << ", " << toHex(data, len) << ')';
743+
const char *data = binDataClean(len);
744+
if ( !full && len > 80 ) {
745+
s << toHex(data, 70) << "...)";
746+
}
747+
else {
748+
s << toHex(data, len) << ")";
749+
}
745750
}
746751
break;
747752
case Timestamp:

src/mongo/client/dbclient.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,25 @@ namespace mongo {
546546
return mongo::createPasswordDigest(username, clearTextPassword);
547547
}
548548

549+
namespace {
550+
class RunCommandHookOverrideGuard {
551+
MONGO_DISALLOW_COPYING(RunCommandHookOverrideGuard);
552+
public:
553+
RunCommandHookOverrideGuard(DBClientWithCommands* cli,
554+
const DBClientWithCommands::RunCommandHookFunc& hookFunc)
555+
: _cli(cli), _oldHookFunc(cli->getRunCommandHook()) {
556+
cli->setRunCommandHook(hookFunc);
557+
}
558+
~RunCommandHookOverrideGuard() {
559+
_cli->setRunCommandHook(_oldHookFunc);
560+
}
561+
private:
562+
DBClientWithCommands* const _cli;
563+
DBClientWithCommands::RunCommandHookFunc const _oldHookFunc;
564+
};
565+
} // namespace
549566
void DBClientWithCommands::_auth(const BSONObj& params) {
567+
RunCommandHookOverrideGuard hookGuard(this, RunCommandHookFunc());
550568
std::string mechanism;
551569

552570
uassertStatusOK(bsonExtractStringField(params,

src/mongo/client/dbclient_rs.cpp

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -144,9 +144,15 @@ namespace {
144144
// --------------------------------
145145

146146
const size_t DBClientReplicaSet::MAX_RETRY = 3;
147-
148-
DBClientReplicaSet::DBClientReplicaSet( const string& name , const vector<HostAndPort>& servers, double so_timeout )
149-
: _setName( name ), _so_timeout( so_timeout ) {
147+
int DBClientReplicaSet::reevaluatePercentage = 0;
148+
149+
DBClientReplicaSet::DBClientReplicaSet(
150+
const string& name,
151+
const vector<HostAndPort>& servers,
152+
double so_timeout):
153+
_setName(name),
154+
_so_timeout(so_timeout),
155+
_nodeSelectOracle(static_cast<int64_t>(time(0))) {
150156
ReplicaSetMonitor::createIfNeeded( name, set<HostAndPort>(servers.begin(), servers.end()) );
151157
}
152158

@@ -647,7 +653,7 @@ namespace {
647653

648654
DBClientConnection* DBClientReplicaSet::selectNodeUsingTags(
649655
shared_ptr<ReadPreferenceSetting> readPref) {
650-
if (checkLastHost(readPref.get())) {
656+
if (!shouldReevaluate() && checkLastHost(readPref.get())) {
651657

652658
LOG( 3 ) << "dbclient_rs selecting compatible last used node " << _lastSlaveOkHost
653659
<< endl;
@@ -973,6 +979,14 @@ namespace {
973979
_lastSlaveOkConn.reset();
974980
}
975981

982+
bool DBClientReplicaSet::shouldReevaluate() {
983+
if (_nodeSelectOracle.nextInt32(100) < reevaluatePercentage) {
984+
return true;
985+
}
986+
987+
return false;
988+
}
989+
976990
// trying to optimize for the common dont-care-about-tags case.
977991
static const BSONArray tagsMatchesAll = BSON_ARRAY(BSONObj());
978992
TagSet::TagSet() : _tags(tagsMatchesAll) {}

src/mongo/client/dbclient_rs.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
#include "mongo/client/dbclientinterface.h"
2424
#include "mongo/client/export_macros.h"
25+
#include "mongo/platform/random.h"
2526
#include "mongo/util/net/hostandport.h"
2627

2728
namespace mongo {
@@ -45,6 +46,12 @@ namespace mongo {
4546
using DBClientBase::update;
4647
using DBClientBase::remove;
4748

49+
// For internal use only. The desired probability for reevaluating node
50+
// selection given a read preference, expressed in percentage. Any value
51+
// less than 0 will be treated as 0% and any value greater than 100 will
52+
// be treated as 100%.
53+
static int reevaluatePercentage;
54+
4855
/** Call connect() after constructing. autoReconnect is always on for DBClientReplicaSet connections. */
4956
DBClientReplicaSet( const string& name , const vector<HostAndPort>& servers, double so_timeout=0 );
5057
virtual ~DBClientReplicaSet();
@@ -212,6 +219,13 @@ namespace mongo {
212219
// Throws a DBException if the monitor doesn't exist and there isn't a cached seed to use.
213220
ReplicaSetMonitorPtr _getMonitor() const;
214221

222+
/**
223+
* Returns true if this connection should re-evaluate the node selection for
224+
* a given read preference, regardless of it's compatibility with the currently
225+
* cached connection.
226+
*/
227+
bool shouldReevaluate();
228+
215229
string _setName;
216230

217231
HostAndPort _masterHost;
@@ -237,6 +251,11 @@ namespace mongo {
237251
// not sure if/how we should handle
238252
std::map<string, BSONObj> _auths; // dbName -> auth parameters
239253

254+
// For v2.6 only.
255+
// Random generator to be used to determine whether this connection object
256+
// should re-evaluate node selection from scratch.
257+
PseudoRandom _nodeSelectOracle;
258+
240259
protected:
241260

242261
/**

src/mongo/db/dbmessage.cpp

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,107 @@ namespace mongo {
5353
return ss.str();
5454
}
5555

56+
DbMessage::DbMessage(const Message& msg) : _msg(msg), _nsStart(NULL), _mark(NULL), _nsLen(0) {
57+
// for received messages, Message has only one buffer
58+
_theEnd = _msg.singleData()->_data + _msg.singleData()->dataLen();
59+
_nextjsobj = _msg.singleData()->_data;
60+
61+
_reserved = readAndAdvance<int>();
62+
63+
// Read packet for NS
64+
if (messageShouldHaveNs()) {
65+
66+
// Limit = buffer size of message -
67+
// (first int4 in message which is either flags or a zero constant)
68+
size_t limit = _msg.singleData()->dataLen() - sizeof(int);
69+
70+
_nsStart = _nextjsobj;
71+
_nsLen = strnlen(_nsStart, limit);
72+
73+
// Validate there is room for a null byte in the buffer
74+
// Strings can be zero length
75+
uassert(18633, "Failed to parse ns string", _nsLen <= (limit - 1));
76+
77+
_nextjsobj += _nsLen + 1; // skip namespace + null
78+
}
79+
}
80+
81+
const char * DbMessage::getns() const {
82+
verify(messageShouldHaveNs());
83+
return _nsStart;
84+
}
85+
86+
int DbMessage::getQueryNToReturn() const {
87+
verify(messageShouldHaveNs());
88+
const char* p = _nsStart + _nsLen + 1;
89+
checkRead<int>(p, 2);
90+
91+
return ((reinterpret_cast<const int*>(p)))[1];
92+
}
93+
94+
int DbMessage::pullInt() {
95+
return readAndAdvance<int>();
96+
}
97+
98+
long long DbMessage::pullInt64() {
99+
return readAndAdvance<long long>();
100+
}
101+
102+
const long long* DbMessage::getArray(size_t count) const {
103+
checkRead<long long>(_nextjsobj, count);
104+
return reinterpret_cast<const long long*>(_nextjsobj);
105+
}
106+
107+
BSONObj DbMessage::nextJsObj() {
108+
massert(10304,
109+
"Client Error: Remaining data too small for BSON object",
110+
_nextjsobj != NULL && _theEnd - _nextjsobj >= 5);
111+
112+
if (serverGlobalParams.objcheck) {
113+
Status status = validateBSON(_nextjsobj, _theEnd - _nextjsobj);
114+
massert(10307,
115+
str::stream() << "Client Error: bad object in message: " << status.reason(),
116+
status.isOK());
117+
}
118+
119+
BSONObj js(_nextjsobj);
120+
verify(js.objsize() >= 5);
121+
verify(js.objsize() <= (_theEnd - _nextjsobj));
122+
123+
_nextjsobj += js.objsize();
124+
if (_nextjsobj >= _theEnd)
125+
_nextjsobj = NULL;
126+
return js;
127+
}
128+
129+
void DbMessage::markReset(const char * toMark = NULL) {
130+
if (toMark == NULL) {
131+
toMark = _mark;
132+
}
133+
134+
verify(toMark);
135+
_nextjsobj = toMark;
136+
}
137+
138+
template<typename T>
139+
void DbMessage::checkRead(const char* start, size_t count) const {
140+
if ((_theEnd - start) < static_cast<int>(sizeof(T) * count)) {
141+
uassert(18634, "Not enough data to read", false);
142+
}
143+
}
144+
145+
template<typename T>
146+
T DbMessage::read() const {
147+
checkRead<T>(_nextjsobj, 1);
148+
149+
return *(reinterpret_cast<const T*>(_nextjsobj));
150+
}
151+
152+
template<typename T> T DbMessage::readAndAdvance() {
153+
T t = read<T>();
154+
_nextjsobj += sizeof(T);
155+
return t;
156+
}
56157

57158
void replyToQuery(int queryResultFlags,
58159
AbstractMessagingPort* p, Message& requestMsg,

0 commit comments

Comments
 (0)