Skip to content

Commit

Permalink
SERVER-24611 Implement ClientMetadata class
Browse files Browse the repository at this point in the history
  • Loading branch information
markbenvenuto committed Aug 4, 2016
1 parent 931a227 commit ad27c92
Show file tree
Hide file tree
Showing 43 changed files with 1,325 additions and 65 deletions.
12 changes: 12 additions & 0 deletions jstests/core/client_metadata_ismaster.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Test that verifies client metadata behavior for isMaster

(function() {
"use strict";

// Verify that a isMaster request fails if it contains client metadata, and it is not first.
// The shell sends isMaster on the first connection
var result = db.runCommand({"isMaster": 1, "client": {"application": "foobar"}});
assert.commandFailed(result);
assert.eq(result.code, ErrorCodes.ClientMetadataCannotBeMutated, tojson(result));

})();
2 changes: 2 additions & 0 deletions jstests/noPassthrough/currentop_query.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@
assert.commandWorked(result);

if (result.inprog.length === 1) {
assert.eq(result.inprog[0].appName, "MongoDB Shell", tojson(result));

return true;
}

Expand Down
4 changes: 4 additions & 0 deletions src/mongo/base/error_codes.err
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,10 @@ error_code("WindowsPdhError", 179)
error_code("BadPerfCounterPath", 180)
error_code("AmbiguousIndexKeyPattern", 181)
error_code("InvalidViewDefinition", 182);
error_code("ClientMetadataMissingField", 183)
error_code("ClientMetadataAppNameTooLarge", 184)
error_code("ClientMetadataDocumentTooLarge", 185)
error_code("ClientMetadataCannotBeMutated", 186)

# Non-sequential error codes (for compatibility only)
error_code("SocketException", 9001)
Expand Down
2 changes: 1 addition & 1 deletion src/mongo/client/connection_pool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ ConnectionPool::ConnectionList::iterator ConnectionPool::acquireConnection(
// the number of seconds with a fractional part.
conn->setSoTimeout(durationCount<Milliseconds>(timeout) / 1000.0);

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

if (isInternalAuthSet()) {
Expand Down
4 changes: 3 additions & 1 deletion src/mongo/client/connection_string.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,9 @@ class ConnectionString {
bool operator==(const ConnectionString& other) const;
bool operator!=(const ConnectionString& other) const;

DBClientBase* connect(std::string& errmsg, double socketTimeout = 0) const;
DBClientBase* connect(StringData applicationName,
std::string& errmsg,
double socketTimeout = 0) const;

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

Expand Down
9 changes: 6 additions & 3 deletions src/mongo/client/connection_string_connect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,21 +45,24 @@ namespace mongo {
stdx::mutex ConnectionString::_connectHookMutex;
ConnectionString::ConnectionHook* ConnectionString::_connectHook = NULL;

DBClientBase* ConnectionString::connect(std::string& errmsg, double socketTimeout) const {
DBClientBase* ConnectionString::connect(StringData applicationName,
std::string& errmsg,
double socketTimeout) const {
switch (_type) {
case MASTER: {
auto c = stdx::make_unique<DBClientConnection>(true);
c->setSoTimeout(socketTimeout);
LOG(1) << "creating new connection to:" << _servers[0];
if (!c->connect(_servers[0], errmsg)) {
if (!c->connect(_servers[0], applicationName, errmsg)) {
return 0;
}
LOG(1) << "connected connection!";
return c.release();
}

case SET: {
auto set = stdx::make_unique<DBClientReplicaSet>(_setName, _servers, socketTimeout);
auto set = stdx::make_unique<DBClientReplicaSet>(
_setName, _servers, applicationName, socketTimeout);
if (!set->connect()) {
errmsg = "connect failed to replica set ";
errmsg += toString();
Expand Down
4 changes: 2 additions & 2 deletions src/mongo/client/connpool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ DBClientBase* DBConnectionPool::get(const ConnectionString& url, double socketTi
}

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

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

string errmsg;
c = cs.connect(errmsg, socketTimeout);
c = cs.connect(StringData(), errmsg, socketTimeout);
if (!c)
throw SocketException(SocketException::CONNECT_ERROR,
host,
Expand Down
24 changes: 18 additions & 6 deletions src/mongo/client/dbclient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
#include "mongo/rpc/factory.h"
#include "mongo/rpc/get_status_from_command_result.h"
#include "mongo/rpc/metadata.h"
#include "mongo/rpc/metadata/client_metadata.h"
#include "mongo/rpc/reply_interface.h"
#include "mongo/rpc/request_builder_interface.h"
#include "mongo/s/stale_exception.h" // for RecvStaleConfigException
Expand All @@ -74,6 +75,7 @@
#include "mongo/util/password_digest.h"
#include "mongo/util/represent_as.h"
#include "mongo/util/time_support.h"
#include "mongo/util/version.h"

namespace mongo {

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

Status serializeStatus = ClientMetadata::serialize(
"MongoDB Internal Client", mongo::versionString, applicationName, &bob);
if (!serializeStatus.isOK()) {
return serializeStatus;
}

Date_t start{Date_t::now()};
auto result =
conn->runCommandWithMetadata("admin", "isMaster", rpc::makeEmptyMetadata(), bob.done());
Expand All @@ -754,22 +763,25 @@ executor::RemoteCommandResponse initWireVersion(DBClientConnection* conn) {

} // namespace

bool DBClientConnection::connect(const HostAndPort& server, std::string& errmsg) {
auto connectStatus = connect(server);
bool DBClientConnection::connect(const HostAndPort& server,
StringData applicationName,
std::string& errmsg) {
auto connectStatus = connect(server, applicationName);
if (!connectStatus.isOK()) {
errmsg = connectStatus.reason();
return false;
}
return true;
}

Status DBClientConnection::connect(const HostAndPort& serverAddress) {
Status DBClientConnection::connect(const HostAndPort& serverAddress, StringData applicationName) {
auto connectStatus = connectSocketOnly(serverAddress);
if (!connectStatus.isOK()) {
return connectStatus;
}

auto swIsMasterReply = initWireVersion(this);
_applicationName = applicationName.toString();
auto swIsMasterReply = initWireVersion(this, applicationName);
if (!swIsMasterReply.isOK()) {
_failed = true;
return swIsMasterReply.status;
Expand Down Expand Up @@ -903,7 +915,7 @@ void DBClientConnection::_checkConnection() {
LOG(_logLevel) << "trying reconnect to " << toString() << endl;
string errmsg;
_failed = false;
auto connectStatus = connect(_serverAddress);
auto connectStatus = connect(_serverAddress, _applicationName);
if (!connectStatus.isOK()) {
_failed = true;
LOG(_logLevel) << "reconnect " << toString() << " failed " << errmsg << endl;
Expand Down
6 changes: 4 additions & 2 deletions src/mongo/client/dbclient_rs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,9 @@ bool DBClientReplicaSet::_authPooledSecondaryConn = true;

DBClientReplicaSet::DBClientReplicaSet(const string& name,
const vector<HostAndPort>& servers,
StringData applicationName,
double so_timeout)
: _setName(name), _so_timeout(so_timeout) {
: _setName(name), _applicationName(applicationName.toString()), _so_timeout(so_timeout) {
_rsm =
ReplicaSetMonitor::createIfNeeded(name, set<HostAndPort>(servers.begin(), servers.end()));
}
Expand Down Expand Up @@ -303,7 +304,8 @@ DBClientConnection* DBClientReplicaSet::checkMaster() {
// Needs to perform a dynamic_cast because we need to set the replSet
// callback. We should eventually not need this after we remove the
// callback.
newConn = dynamic_cast<DBClientConnection*>(connStr.connect(errmsg, _so_timeout));
newConn = dynamic_cast<DBClientConnection*>(
connStr.connect(_applicationName, errmsg, _so_timeout));
} catch (const AssertionException& ex) {
errmsg = ex.toString();
}
Expand Down
2 changes: 2 additions & 0 deletions src/mongo/client/dbclient_rs.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class DBClientReplicaSet : public DBClientBase {
* connections. */
DBClientReplicaSet(const std::string& name,
const std::vector<HostAndPort>& servers,
StringData applicationName,
double so_timeout = 0);
virtual ~DBClientReplicaSet();

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

std::string _setName;
std::string _applicationName;
std::shared_ptr<ReplicaSetMonitor> _rsm;

HostAndPort _masterHost;
Expand Down
Loading

0 comments on commit ad27c92

Please sign in to comment.