The official documentation of MongoDB describes how to use the correct format of the connection string to support single server and replica-set server, and claims that the official driver supports both.
Http://docs.mongodb.org/manual/reference/connection-string/
But in fact, the C ++ driver still follows the old method, and there are few descriptions in this document. Through this discussion, we can see how annoying the MongoDB C ++ driver is.
Http://stackoverflow.com/questions/14629281/c-driver-mongodb-connection-options
I am using the C ++ driver of MongoDB 2.4.1. By checking the source code, I found the method used.
In mongo-cxx-driver-v2.4.1/src/Mongo/client/dbclientinterface. in the H file, there are comments in the connectionstring Class header. It is strange that it can be seen in official site documents, but there is no line break, which looks particularly disgusting. Http://api.mongodb.org/cplusplus/2.4.3/classmongo_1_1_connection_string.html#details
/** * ConnectionString handles parsing different ways to connect to mongo and determining method * samples: * server * server:port * foo/server:port,server:port SET * server,server,server SYNC * Warning - you usually don't want "SYNC", it's used * for some special things such as sharding config servers. * See syncclusterconnection.h for more info. * * tyipcal use * string errmsg, * ConnectionString cs = ConnectionString::parse( url , errmsg ); * if ( ! cs.isValid() ) throw "bad: " + errmsg; * DBClientBase * conn = cs.connect( errmsg ); */ class ConnectionString { public: enum ConnectionType { INVALID , MASTER , PAIR , SET , SYNC, CUSTOM }; ConnectionString() { _type = INVALID; }
Here set refers to replica-set, which is used to parse strings through connctionstring: parse.
So what about the source code of connectionstring: parse? In the dbclient. cpp file:
ConnectionString ConnectionString::parse( const string& host , string& errmsg ) { string::size_type i = host.find( '/' ); if ( i != string::npos && i != 0) { // replica set return ConnectionString( SET , host.substr( i + 1 ) , host.substr( 0 , i ) ); } int numCommas = str::count( host , ',' ); if( numCommas == 0 ) return ConnectionString( HostAndPort( host ) ); if ( numCommas == 1 ) return ConnectionString( PAIR , host ); if ( numCommas == 2 ) return ConnectionString( SYNC , host ); errmsg = (string)"invalid hostname [" + host + "]"; return ConnectionString(); // INVALID }
That is to say, first find the first diagonal line, and then use the previous line as the replica-Set Name, and use it as the host name.
I need a way to switch from single server to replica-set through configuration. This is very simple, because the only change is the string in the configuration file.
Now let's take a look at the single server situation. I have the following Configuration:
"uri" : "localhost:27017"
Then create your own pai_session object.
shared_ptr<mongo_session> mongo_session_factory::get_session() { configuration& config = app_singleton_holder::Instance().config(); string error_message; mongo::ConnectionString host = mongo::ConnectionString::parse(config.mongo_uri, error_message); if (!host.isValid()) { throw "bad: " + error_message; } shared_ptr<mongo_session> s(new mongo_session(host)); return s;}
I mentioned in my previous blog about the cmd_session class. Here I have modified a little bit and take a look at the. h file:
#ifndef _MONGO_SESSION_H#define _MONGO_SESSION_H#include <string>#include <mongo/client/connpool.h>class mongo_session { public: /** * construct ScopedDBConnection instance and keep it as member variable */ mongo_session(mongo::ConnectionString const& host, double socketTimeout=0); /** * release connction back to pool */ ~mongo_session(); /** * Get one connection from pool */ mongo::DBClientBase& get(); private: std::auto_ptr<mongo::ScopedDbConnection> con_;};#endif
Take a look at the. cpp file:
#include "helper/mongo_session.h"using namespace mongo;mongo_session::mongo_session(mongo::ConnectionString const& host, double socketTimeout): con_(mongo::ScopedDbConnection::getScopedDbConnection(host, socketTimeout)) { }mongo_session::~mongo_session(){ con_->done();}DBClientBase& mongo_session::get(){ return con_->conn();}
Test that the Single Server can be connected normally.
Modify the Configuration:
"uri" : "rs1/d1:27017,d2:27017,d3:27017"
RS1 is my replica-Set Name
D1, D2, and D3 are the host names of the three MongoDB instances.
27017 is the port number.
After the terminal is started, the following information is displayed:
Thu May 9 19:37:56.947 starting new replica set monitor for replica set rs1 with seed of d1:27017,d2:27017,d3:27017Thu May 9 19:37:56.949 successfully connected to seed d1:27017 for replica set rs1Thu May 9 19:37:56.950 changing hosts to { 0: "d1:27017", 1: "d3:27017", 2: "d2:27017" } from rs1/Thu May 9 19:37:56.950 trying to add new host d1:27017 to replica set rs1Thu May 9 19:37:56.952 successfully connected to new host d1:27017 in replica set rs1Thu May 9 19:37:56.952 trying to add new host d2:27017 to replica set rs1Thu May 9 19:37:56.953 successfully connected to new host d2:27017 in replica set rs1Thu May 9 19:37:56.953 trying to add new host d3:27017 to replica set rs1Thu May 9 19:37:56.956 successfully connected to new host d3:27017 in replica set rs1Thu May 9 19:37:56.960 Primary for replica set rs1 changed to d1:27017Thu May 9 19:37:56.967 replica set monitor for replica set rs1 started, address is rs1/d1:27017,d2:27017,d3:27017Thu May 9 19:37:56.967 [ReplicaSetMonitorWatcher] starting
The above indicates that the current connection is successful and D1 is being used as primary.
Test the program. Everything works normally.
The conclusion is that the official documentation of MongoDB C ++ is really disgusting. These C ++ programmers may be talented, but they are far from well-regulated Java communities. You can only view their code and comments to find out how to use them.