Skip to content

Commit ad27c92

Browse files
committed
SERVER-24611 Implement ClientMetadata class
1 parent 931a227 commit ad27c92

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1325
-65
lines changed
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Test that verifies client metadata behavior for isMaster
2+
3+
(function() {
4+
"use strict";
5+
6+
// Verify that a isMaster request fails if it contains client metadata, and it is not first.
7+
// The shell sends isMaster on the first connection
8+
var result = db.runCommand({"isMaster": 1, "client": {"application": "foobar"}});
9+
assert.commandFailed(result);
10+
assert.eq(result.code, ErrorCodes.ClientMetadataCannotBeMutated, tojson(result));
11+
12+
})();

jstests/noPassthrough/currentop_query.js

+2
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@
7171
assert.commandWorked(result);
7272

7373
if (result.inprog.length === 1) {
74+
assert.eq(result.inprog[0].appName, "MongoDB Shell", tojson(result));
75+
7476
return true;
7577
}
7678

src/mongo/base/error_codes.err

+4
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,10 @@ error_code("WindowsPdhError", 179)
181181
error_code("BadPerfCounterPath", 180)
182182
error_code("AmbiguousIndexKeyPattern", 181)
183183
error_code("InvalidViewDefinition", 182);
184+
error_code("ClientMetadataMissingField", 183)
185+
error_code("ClientMetadataAppNameTooLarge", 184)
186+
error_code("ClientMetadataDocumentTooLarge", 185)
187+
error_code("ClientMetadataCannotBeMutated", 186)
184188

185189
# Non-sequential error codes (for compatibility only)
186190
error_code("SocketException", 9001)

src/mongo/client/connection_pool.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ ConnectionPool::ConnectionList::iterator ConnectionPool::acquireConnection(
184184
// the number of seconds with a fractional part.
185185
conn->setSoTimeout(durationCount<Milliseconds>(timeout) / 1000.0);
186186

187-
uassertStatusOK(conn->connect(target));
187+
uassertStatusOK(conn->connect(target, StringData()));
188188
conn->port().setTag(conn->port().getTag() | _messagingPortTags);
189189

190190
if (isInternalAuthSet()) {

src/mongo/client/connection_string.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,9 @@ class ConnectionString {
116116
bool operator==(const ConnectionString& other) const;
117117
bool operator!=(const ConnectionString& other) const;
118118

119-
DBClientBase* connect(std::string& errmsg, double socketTimeout = 0) const;
119+
DBClientBase* connect(StringData applicationName,
120+
std::string& errmsg,
121+
double socketTimeout = 0) const;
120122

121123
static StatusWith<ConnectionString> parse(const std::string& url);
122124

src/mongo/client/connection_string_connect.cpp

+6-3
Original file line numberDiff line numberDiff line change
@@ -45,21 +45,24 @@ namespace mongo {
4545
stdx::mutex ConnectionString::_connectHookMutex;
4646
ConnectionString::ConnectionHook* ConnectionString::_connectHook = NULL;
4747

48-
DBClientBase* ConnectionString::connect(std::string& errmsg, double socketTimeout) const {
48+
DBClientBase* ConnectionString::connect(StringData applicationName,
49+
std::string& errmsg,
50+
double socketTimeout) const {
4951
switch (_type) {
5052
case MASTER: {
5153
auto c = stdx::make_unique<DBClientConnection>(true);
5254
c->setSoTimeout(socketTimeout);
5355
LOG(1) << "creating new connection to:" << _servers[0];
54-
if (!c->connect(_servers[0], errmsg)) {
56+
if (!c->connect(_servers[0], applicationName, errmsg)) {
5557
return 0;
5658
}
5759
LOG(1) << "connected connection!";
5860
return c.release();
5961
}
6062

6163
case SET: {
62-
auto set = stdx::make_unique<DBClientReplicaSet>(_setName, _servers, socketTimeout);
64+
auto set = stdx::make_unique<DBClientReplicaSet>(
65+
_setName, _servers, applicationName, socketTimeout);
6366
if (!set->connect()) {
6467
errmsg = "connect failed to replica set ";
6568
errmsg += toString();

src/mongo/client/connpool.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ DBClientBase* DBConnectionPool::get(const ConnectionString& url, double socketTi
235235
}
236236

237237
string errmsg;
238-
c = url.connect(errmsg, socketTimeout);
238+
c = url.connect(StringData(), errmsg, socketTimeout);
239239
uassert(13328, _name + ": connect failed " + url.toString() + " : " + errmsg, c);
240240

241241
return _finishCreate(url.toString(), socketTimeout, c);
@@ -256,7 +256,7 @@ DBClientBase* DBConnectionPool::get(const string& host, double socketTimeout) {
256256
const ConnectionString cs(uassertStatusOK(ConnectionString::parse(host)));
257257

258258
string errmsg;
259-
c = cs.connect(errmsg, socketTimeout);
259+
c = cs.connect(StringData(), errmsg, socketTimeout);
260260
if (!c)
261261
throw SocketException(SocketException::CONNECT_ERROR,
262262
host,

src/mongo/client/dbclient.cpp

+18-6
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
#include "mongo/rpc/factory.h"
5656
#include "mongo/rpc/get_status_from_command_result.h"
5757
#include "mongo/rpc/metadata.h"
58+
#include "mongo/rpc/metadata/client_metadata.h"
5859
#include "mongo/rpc/reply_interface.h"
5960
#include "mongo/rpc/request_builder_interface.h"
6061
#include "mongo/s/stale_exception.h" // for RecvStaleConfigException
@@ -74,6 +75,7 @@
7475
#include "mongo/util/password_digest.h"
7576
#include "mongo/util/represent_as.h"
7677
#include "mongo/util/time_support.h"
78+
#include "mongo/util/version.h"
7779

7880
namespace mongo {
7981

@@ -712,7 +714,8 @@ class ScopedForceOpQuery {
712714
/**
713715
* Initializes the wire version of conn, and returns the isMaster reply.
714716
*/
715-
executor::RemoteCommandResponse initWireVersion(DBClientConnection* conn) {
717+
executor::RemoteCommandResponse initWireVersion(DBClientConnection* conn,
718+
StringData applicationName) {
716719
try {
717720
// We need to force the usage of OP_QUERY on this command, even if we have previously
718721
// detected support for OP_COMMAND on a connection. This is necessary to handle the case
@@ -731,6 +734,12 @@ executor::RemoteCommandResponse initWireVersion(DBClientConnection* conn) {
731734
bob.append("hostInfo", sb.str());
732735
}
733736

737+
Status serializeStatus = ClientMetadata::serialize(
738+
"MongoDB Internal Client", mongo::versionString, applicationName, &bob);
739+
if (!serializeStatus.isOK()) {
740+
return serializeStatus;
741+
}
742+
734743
Date_t start{Date_t::now()};
735744
auto result =
736745
conn->runCommandWithMetadata("admin", "isMaster", rpc::makeEmptyMetadata(), bob.done());
@@ -754,22 +763,25 @@ executor::RemoteCommandResponse initWireVersion(DBClientConnection* conn) {
754763

755764
} // namespace
756765

757-
bool DBClientConnection::connect(const HostAndPort& server, std::string& errmsg) {
758-
auto connectStatus = connect(server);
766+
bool DBClientConnection::connect(const HostAndPort& server,
767+
StringData applicationName,
768+
std::string& errmsg) {
769+
auto connectStatus = connect(server, applicationName);
759770
if (!connectStatus.isOK()) {
760771
errmsg = connectStatus.reason();
761772
return false;
762773
}
763774
return true;
764775
}
765776

766-
Status DBClientConnection::connect(const HostAndPort& serverAddress) {
777+
Status DBClientConnection::connect(const HostAndPort& serverAddress, StringData applicationName) {
767778
auto connectStatus = connectSocketOnly(serverAddress);
768779
if (!connectStatus.isOK()) {
769780
return connectStatus;
770781
}
771782

772-
auto swIsMasterReply = initWireVersion(this);
783+
_applicationName = applicationName.toString();
784+
auto swIsMasterReply = initWireVersion(this, applicationName);
773785
if (!swIsMasterReply.isOK()) {
774786
_failed = true;
775787
return swIsMasterReply.status;
@@ -903,7 +915,7 @@ void DBClientConnection::_checkConnection() {
903915
LOG(_logLevel) << "trying reconnect to " << toString() << endl;
904916
string errmsg;
905917
_failed = false;
906-
auto connectStatus = connect(_serverAddress);
918+
auto connectStatus = connect(_serverAddress, _applicationName);
907919
if (!connectStatus.isOK()) {
908920
_failed = true;
909921
LOG(_logLevel) << "reconnect " << toString() << " failed " << errmsg << endl;

src/mongo/client/dbclient_rs.cpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,9 @@ bool DBClientReplicaSet::_authPooledSecondaryConn = true;
135135

136136
DBClientReplicaSet::DBClientReplicaSet(const string& name,
137137
const vector<HostAndPort>& servers,
138+
StringData applicationName,
138139
double so_timeout)
139-
: _setName(name), _so_timeout(so_timeout) {
140+
: _setName(name), _applicationName(applicationName.toString()), _so_timeout(so_timeout) {
140141
_rsm =
141142
ReplicaSetMonitor::createIfNeeded(name, set<HostAndPort>(servers.begin(), servers.end()));
142143
}
@@ -303,7 +304,8 @@ DBClientConnection* DBClientReplicaSet::checkMaster() {
303304
// Needs to perform a dynamic_cast because we need to set the replSet
304305
// callback. We should eventually not need this after we remove the
305306
// callback.
306-
newConn = dynamic_cast<DBClientConnection*>(connStr.connect(errmsg, _so_timeout));
307+
newConn = dynamic_cast<DBClientConnection*>(
308+
connStr.connect(_applicationName, errmsg, _so_timeout));
307309
} catch (const AssertionException& ex) {
308310
errmsg = ex.toString();
309311
}

src/mongo/client/dbclient_rs.h

+2
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ class DBClientReplicaSet : public DBClientBase {
5959
* connections. */
6060
DBClientReplicaSet(const std::string& name,
6161
const std::vector<HostAndPort>& servers,
62+
StringData applicationName,
6263
double so_timeout = 0);
6364
virtual ~DBClientReplicaSet();
6465

@@ -295,6 +296,7 @@ class DBClientReplicaSet : public DBClientBase {
295296
ReplicaSetMonitorPtr _getMonitor();
296297

297298
std::string _setName;
299+
std::string _applicationName;
298300
std::shared_ptr<ReplicaSetMonitor> _rsm;
299301

300302
HostAndPort _masterHost;

0 commit comments

Comments
 (0)