/**
* Copyright (C) 2009-2015 MongoDB 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 .
*
* As a special exception, the copyright holders give permission to link the
* code of portions of this program with the OpenSSL library under certain
* conditions as described in each individual source file and distribute
* linked combinations including the program with the OpenSSL library. You
* must comply with the GNU Affero General Public License in all respects for
* all of the code used other than as permitted herein. If you modify file(s)
* with this exception, you may extend this exception to your version of the
* file(s), but you are not obligated to do so. If you do not wish to do so,
* delete this exception statement from your version. If you delete this
* exception statement from all source files in the program, then also delete
* it in the license file.
*/
#pragma once
#include
#include
#include "mongo/base/status_with.h"
#include "mongo/base/string_data.h"
#include "mongo/stdx/mutex.h"
#include "mongo/util/assert_util.h"
#include "mongo/util/net/hostandport.h"
namespace mongo {
class DBClientBase;
/**
* ConnectionString handles parsing different ways to connect to mongo and determining method
* samples:
* server
* server:port
* foo/server:port,server:port SET
*
* Typical use:
*
* ConnectionString cs(uassertStatusOK(ConnectionString::parse(url)));
* std::string errmsg;
* DBClientBase * conn = cs.connect( errmsg );
*/
class ConnectionString {
public:
enum ConnectionType { INVALID, MASTER, SET, CUSTOM, LOCAL };
ConnectionString() = default;
/**
* Constructs a connection string representing a replica set.
*/
static ConnectionString forReplicaSet(StringData setName, std::vector servers);
/**
* Constructs a local connection string.
*/
static ConnectionString forLocal();
/**
* Creates a MASTER connection string with the specified server.
*/
explicit ConnectionString(const HostAndPort& server);
/**
* Creates a connection string from an unparsed list of servers, type, and setName.
*/
ConnectionString(ConnectionType type, const std::string& s, const std::string& setName);
/**
* Creates a connection string from a pre-parsed list of servers, type, and setName.
*/
ConnectionString(ConnectionType type,
std::vector servers,
const std::string& setName);
ConnectionString(const std::string& s, ConnectionType connType);
bool isValid() const {
return _type != INVALID;
}
const std::string& toString() const {
return _string;
}
const std::string& getSetName() const {
return _setName;
}
const std::vector& getServers() const {
return _servers;
}
ConnectionType type() const {
return _type;
}
/**
* This returns true if this and other point to the same logical entity.
* For single nodes, thats the same address.
* For replica sets, thats just the same replica set name.
* For pair (deprecated) or sync cluster connections, that's the same hosts in any ordering.
*/
bool sameLogicalEndpoint(const ConnectionString& other) const;
DBClientBase* connect(std::string& errmsg, double socketTimeout = 0) const;
static StatusWith parse(const std::string& url);
static std::string typeToString(ConnectionType type);
//
// Allow overriding the default connection behavior
// This is needed for some tests, which otherwise would fail because they are unable to contact
// the correct servers.
//
class ConnectionHook {
public:
virtual ~ConnectionHook() {}
// Returns an alternative connection object for a string
virtual DBClientBase* connect(const ConnectionString& c,
std::string& errmsg,
double socketTimeout) = 0;
};
static void setConnectionHook(ConnectionHook* hook) {
stdx::lock_guard lk(_connectHookMutex);
_connectHook = hook;
}
static ConnectionHook* getConnectionHook() {
stdx::lock_guard lk(_connectHookMutex);
return _connectHook;
}
// Allows ConnectionStrings to be stored more easily in sets/maps
bool operator<(const ConnectionString& other) const {
return _string < other._string;
}
private:
/**
* Creates a SET connection string with the specified set name and servers.
*/
ConnectionString(StringData setName, std::vector servers);
/**
* Creates a connection string with the specified type. Used for creating LOCAL strings.
*/
explicit ConnectionString(ConnectionType connType);
void _fillServers(std::string s);
void _finishInit();
ConnectionType _type{INVALID};
std::vector _servers;
std::string _string;
std::string _setName;
static stdx::mutex _connectHookMutex;
static ConnectionHook* _connectHook;
};
} // namespace mongo