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
Lines changed: 12 additions & 0 deletions
Original file line numberOriginal file lineDiff 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

Lines changed: 2 additions & 0 deletions
Original file line numberOriginal file lineDiff line numberDiff line change
@@ -71,6 +71,8 @@
71
assert.commandWorked(result);
71
assert.commandWorked(result);
72

72

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

78

src/mongo/base/error_codes.err

Lines changed: 4 additions & 0 deletions
Original file line numberOriginal file lineDiff line numberDiff line change
@@ -181,6 +181,10 @@ error_code("WindowsPdhError", 179)
181
error_code("BadPerfCounterPath", 180)
181
error_code("BadPerfCounterPath", 180)
182
error_code("AmbiguousIndexKeyPattern", 181)
182
error_code("AmbiguousIndexKeyPattern", 181)
183
error_code("InvalidViewDefinition", 182);
183
error_code("InvalidViewDefinition", 182);
184+
error_code("ClientMetadataMissingField", 183)
185+
error_code("ClientMetadataAppNameTooLarge", 184)
186+
error_code("ClientMetadataDocumentTooLarge", 185)
187+
error_code("ClientMetadataCannotBeMutated", 186)
184

188

185
# Non-sequential error codes (for compatibility only)
189
# Non-sequential error codes (for compatibility only)
186
error_code("SocketException", 9001)
190
error_code("SocketException", 9001)

src/mongo/client/connection_pool.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberOriginal file lineDiff line numberDiff line change
@@ -184,7 +184,7 @@ ConnectionPool::ConnectionList::iterator ConnectionPool::acquireConnection(
184
// the number of seconds with a fractional part.
184
// the number of seconds with a fractional part.
185
conn->setSoTimeout(durationCount<Milliseconds>(timeout) / 1000.0);
185
conn->setSoTimeout(durationCount<Milliseconds>(timeout) / 1000.0);
186

186

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

189

190
if (isInternalAuthSet()) {
190
if (isInternalAuthSet()) {

src/mongo/client/connection_string.h

Lines changed: 3 additions & 1 deletion
Original file line numberOriginal file lineDiff line numberDiff line change
@@ -116,7 +116,9 @@ class ConnectionString {
116
bool operator==(const ConnectionString& other) const;
116
bool operator==(const ConnectionString& other) const;
117
bool operator!=(const ConnectionString& other) const;
117
bool operator!=(const ConnectionString& other) const;
118

118

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

122

121
static StatusWith<ConnectionString> parse(const std::string& url);
123
static StatusWith<ConnectionString> parse(const std::string& url);
122

124

src/mongo/client/connection_string_connect.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberOriginal file lineDiff line numberDiff line change
@@ -45,21 +45,24 @@ namespace mongo {
45
stdx::mutex ConnectionString::_connectHookMutex;
45
stdx::mutex ConnectionString::_connectHookMutex;
46
ConnectionString::ConnectionHook* ConnectionString::_connectHook = NULL;
46
ConnectionString::ConnectionHook* ConnectionString::_connectHook = NULL;
47

47

48-
DBClientBase* ConnectionString::connect(std::string& errmsg, double socketTimeout) const {
48+
DBClientBase* ConnectionString::connect(StringData applicationName,
49+
std::string& errmsg,
50+
double socketTimeout) const {
49
switch (_type) {
51
switch (_type) {
50
case MASTER: {
52
case MASTER: {
51
auto c = stdx::make_unique<DBClientConnection>(true);
53
auto c = stdx::make_unique<DBClientConnection>(true);
52
c->setSoTimeout(socketTimeout);
54
c->setSoTimeout(socketTimeout);
53
LOG(1) << "creating new connection to:" << _servers[0];
55
LOG(1) << "creating new connection to:" << _servers[0];
54-
if (!c->connect(_servers[0], errmsg)) {
56+
if (!c->connect(_servers[0], applicationName, errmsg)) {
55
return 0;
57
return 0;
56
}
58
}
57
LOG(1) << "connected connection!";
59
LOG(1) << "connected connection!";
58
return c.release();
60
return c.release();
59
}
61
}
60

62

61
case SET: {
63
case SET: {
62-
auto set = stdx::make_unique<DBClientReplicaSet>(_setName, _servers, socketTimeout);
64+
auto set = stdx::make_unique<DBClientReplicaSet>(
65+
_setName, _servers, applicationName, socketTimeout);
63
if (!set->connect()) {
66
if (!set->connect()) {
64
errmsg = "connect failed to replica set ";
67
errmsg = "connect failed to replica set ";
65
errmsg += toString();
68
errmsg += toString();

src/mongo/client/connpool.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberOriginal file lineDiff line numberDiff line change
@@ -235,7 +235,7 @@ DBClientBase* DBConnectionPool::get(const ConnectionString& url, double socketTi
235
}
235
}
236

236

237
string errmsg;
237
string errmsg;
238-
c = url.connect(errmsg, socketTimeout);
238+
c = url.connect(StringData(), errmsg, socketTimeout);
239
uassert(13328, _name + ": connect failed " + url.toString() + " : " + errmsg, c);
239
uassert(13328, _name + ": connect failed " + url.toString() + " : " + errmsg, c);
240

240

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

257

258
string errmsg;
258
string errmsg;
259-
c = cs.connect(errmsg, socketTimeout);
259+
c = cs.connect(StringData(), errmsg, socketTimeout);
260
if (!c)
260
if (!c)
261
throw SocketException(SocketException::CONNECT_ERROR,
261
throw SocketException(SocketException::CONNECT_ERROR,
262
host,
262
host,

src/mongo/client/dbclient.cpp

Lines changed: 18 additions & 6 deletions
Original file line numberOriginal file lineDiff line numberDiff line change
@@ -55,6 +55,7 @@
55
#include "mongo/rpc/factory.h"
55
#include "mongo/rpc/factory.h"
56
#include "mongo/rpc/get_status_from_command_result.h"
56
#include "mongo/rpc/get_status_from_command_result.h"
57
#include "mongo/rpc/metadata.h"
57
#include "mongo/rpc/metadata.h"
58+
#include "mongo/rpc/metadata/client_metadata.h"
58
#include "mongo/rpc/reply_interface.h"
59
#include "mongo/rpc/reply_interface.h"
59
#include "mongo/rpc/request_builder_interface.h"
60
#include "mongo/rpc/request_builder_interface.h"
60
#include "mongo/s/stale_exception.h" // for RecvStaleConfigException
61
#include "mongo/s/stale_exception.h" // for RecvStaleConfigException
@@ -74,6 +75,7 @@
74
#include "mongo/util/password_digest.h"
75
#include "mongo/util/password_digest.h"
75
#include "mongo/util/represent_as.h"
76
#include "mongo/util/represent_as.h"
76
#include "mongo/util/time_support.h"
77
#include "mongo/util/time_support.h"
78+
#include "mongo/util/version.h"
77

79

78
namespace mongo {
80
namespace mongo {
79

81

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

736

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

763

755
} // namespace
764
} // namespace
756

765

757-
bool DBClientConnection::connect(const HostAndPort& server, std::string& errmsg) {
766+
bool DBClientConnection::connect(const HostAndPort& server,
758-
auto connectStatus = connect(server);
767+
StringData applicationName,
768+
std::string& errmsg) {
769+
auto connectStatus = connect(server, applicationName);
759
if (!connectStatus.isOK()) {
770
if (!connectStatus.isOK()) {
760
errmsg = connectStatus.reason();
771
errmsg = connectStatus.reason();
761
return false;
772
return false;
762
}
773
}
763
return true;
774
return true;
764
}
775
}
765

776

766-
Status DBClientConnection::connect(const HostAndPort& serverAddress) {
777+
Status DBClientConnection::connect(const HostAndPort& serverAddress, StringData applicationName) {
767
auto connectStatus = connectSocketOnly(serverAddress);
778
auto connectStatus = connectSocketOnly(serverAddress);
768
if (!connectStatus.isOK()) {
779
if (!connectStatus.isOK()) {
769
return connectStatus;
780
return connectStatus;
770
}
781
}
771

782

772-
auto swIsMasterReply = initWireVersion(this);
783+
_applicationName = applicationName.toString();
784+
auto swIsMasterReply = initWireVersion(this, applicationName);
773
if (!swIsMasterReply.isOK()) {
785
if (!swIsMasterReply.isOK()) {
774
_failed = true;
786
_failed = true;
775
return swIsMasterReply.status;
787
return swIsMasterReply.status;
@@ -903,7 +915,7 @@ void DBClientConnection::_checkConnection() {
903
LOG(_logLevel) << "trying reconnect to " << toString() << endl;
915
LOG(_logLevel) << "trying reconnect to " << toString() << endl;
904
string errmsg;
916
string errmsg;
905
_failed = false;
917
_failed = false;
906-
auto connectStatus = connect(_serverAddress);
918+
auto connectStatus = connect(_serverAddress, _applicationName);
907
if (!connectStatus.isOK()) {
919
if (!connectStatus.isOK()) {
908
_failed = true;
920
_failed = true;
909
LOG(_logLevel) << "reconnect " << toString() << " failed " << errmsg << endl;
921
LOG(_logLevel) << "reconnect " << toString() << " failed " << errmsg << endl;

src/mongo/client/dbclient_rs.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberOriginal file lineDiff line numberDiff line change
@@ -135,8 +135,9 @@ bool DBClientReplicaSet::_authPooledSecondaryConn = true;
135

135

136
DBClientReplicaSet::DBClientReplicaSet(const string& name,
136
DBClientReplicaSet::DBClientReplicaSet(const string& name,
137
const vector<HostAndPort>& servers,
137
const vector<HostAndPort>& servers,
138+
StringData applicationName,
138
double so_timeout)
139
double so_timeout)
139-
: _setName(name), _so_timeout(so_timeout) {
140+
: _setName(name), _applicationName(applicationName.toString()), _so_timeout(so_timeout) {
140
_rsm =
141
_rsm =
141
ReplicaSetMonitor::createIfNeeded(name, set<HostAndPort>(servers.begin(), servers.end()));
142
ReplicaSetMonitor::createIfNeeded(name, set<HostAndPort>(servers.begin(), servers.end()));
142
}
143
}
@@ -303,7 +304,8 @@ DBClientConnection* DBClientReplicaSet::checkMaster() {
303
// Needs to perform a dynamic_cast because we need to set the replSet
304
// Needs to perform a dynamic_cast because we need to set the replSet
304
// callback. We should eventually not need this after we remove the
305
// callback. We should eventually not need this after we remove the
305
// callback.
306
// callback.
306-
newConn = dynamic_cast<DBClientConnection*>(connStr.connect(errmsg, _so_timeout));
307+
newConn = dynamic_cast<DBClientConnection*>(
308+
connStr.connect(_applicationName, errmsg, _so_timeout));
307
} catch (const AssertionException& ex) {
309
} catch (const AssertionException& ex) {
308
errmsg = ex.toString();
310
errmsg = ex.toString();
309
}
311
}

src/mongo/client/dbclient_rs.h

Lines changed: 2 additions & 0 deletions
Original file line numberOriginal file lineDiff line numberDiff line change
@@ -59,6 +59,7 @@ class DBClientReplicaSet : public DBClientBase {
59
* connections. */
59
* connections. */
60
DBClientReplicaSet(const std::string& name,
60
DBClientReplicaSet(const std::string& name,
61
const std::vector<HostAndPort>& servers,
61
const std::vector<HostAndPort>& servers,
62+
StringData applicationName,
62
double so_timeout = 0);
63
double so_timeout = 0);
63
virtual ~DBClientReplicaSet();
64
virtual ~DBClientReplicaSet();
64

65

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

297

297
std::string _setName;
298
std::string _setName;
299+
std::string _applicationName;
298
std::shared_ptr<ReplicaSetMonitor> _rsm;
300
std::shared_ptr<ReplicaSetMonitor> _rsm;
299

301

300
HostAndPort _masterHost;
302
HostAndPort _masterHost;

0 commit comments

Comments
 (0)