00001
00017 #pragma once
00018
00019 #include "db.h"
00020 #include "dbhelpers.h"
00021 #include "json.h"
00022 #include "../client/dbclient.h"
00023 #include "repl.h"
00024 #include "cmdline.h"
00025 #include "repl/rs.h"
00026
00027 namespace mongo {
00028
00029 extern const char *replAllDead;
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 class ReplPair {
00043 public:
00044 enum ReplState {
00045 State_CantArb = -3,
00046 State_Confused = -2,
00047 State_Negotiating = -1,
00048 State_Slave = 0,
00049 State_Master = 1
00050 };
00051
00052 int state;
00053 ThreadSafeString info;
00054 string arbHost;
00055 int remotePort;
00056 string remoteHost;
00057 string remote;
00058
00059
00060 string getInfo() {
00061 stringstream ss;
00062 ss << " state: ";
00063 if ( state == 1 ) ss << "1 State_Master ";
00064 else if ( state == 0 ) ss << "0 State_Slave";
00065 else
00066 ss << "<b>" << state << "</b>";
00067 ss << '\n';
00068 ss << " info: " << info << '\n';
00069 ss << " arbhost: " << arbHost << '\n';
00070 ss << " remote: " << remoteHost << ':' << remotePort << '\n';
00071
00072 return ss.str();
00073 }
00074
00075 ReplPair(const char *remoteEnd, const char *arbiter);
00076 virtual ~ReplPair() {}
00077
00078 bool dominant(const string& myname) {
00079 if ( myname == remoteHost )
00080 return cmdLine.port > remotePort;
00081 return myname > remoteHost;
00082 }
00083
00084 void setMasterLocked( int n, const char *_comment = "" ) {
00085 dblock p;
00086 setMaster( n, _comment );
00087 }
00088
00089 void setMaster(int n, const char *_comment = "");
00090
00091
00092 int negotiate(DBClientConnection *conn, string method);
00093
00094
00095 void arbitrate();
00096
00097 virtual
00098 DBClientConnection *newClientConnection() const {
00099 return new DBClientConnection();
00100 }
00101 };
00102
00103 extern ReplPair *replPair;
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114 inline bool _isMaster() {
00115 if( replSet ) {
00116 if( theReplSet )
00117 return theReplSet->isPrimary();
00118 return false;
00119 }
00120
00121 if( ! replSettings.slave )
00122 return true;
00123
00124 if ( replAllDead )
00125 return false;
00126
00127 if ( replPair ) {
00128 if( replPair->state == ReplPair::State_Master )
00129 return true;
00130 }
00131 else {
00132 if( replSettings.master ) {
00133
00134
00135 return true;
00136 }
00137 }
00138
00139 if ( cc().isGod() )
00140 return true;
00141
00142 return false;
00143 }
00144 inline bool isMaster(const char *client = 0) {
00145 if( _isMaster() )
00146 return true;
00147 if ( !client ) {
00148 Database *database = cc().database();
00149 assert( database );
00150 client = database->name.c_str();
00151 }
00152 return strcmp( client, "local" ) == 0;
00153 }
00154
00155 inline void notMasterUnless(bool expr) {
00156 uassert( 10107 , "not master" , expr );
00157 }
00158
00159
00160
00161
00162
00163 inline void replVerifyReadsOk(ParsedQuery& pq) {
00164 if( replSet ) {
00165
00166 if( isMaster() ) return;
00167 uassert(13435, "not master and slaveok=false", pq.hasOption(QueryOption_SlaveOk));
00168 uassert(13436, "not master or secondary, can't read", theReplSet && theReplSet->isSecondary() );
00169 }
00170 else {
00171 notMasterUnless(isMaster() || pq.hasOption(QueryOption_SlaveOk) || replSettings.slave == SimpleSlave );
00172 }
00173 }
00174
00175 inline bool isMasterNs( const char *ns ) {
00176 char cl[ 256 ];
00177 nsToDatabase( ns, cl );
00178 return isMaster( cl );
00179 }
00180
00181 inline ReplPair::ReplPair(const char *remoteEnd, const char *arb) {
00182 state = -1;
00183 remote = remoteEnd;
00184 remotePort = CmdLine::DefaultDBPort;
00185 remoteHost = remoteEnd;
00186 const char *p = strchr(remoteEnd, ':');
00187 if ( p ) {
00188 remoteHost = string(remoteEnd, p-remoteEnd);
00189 remotePort = atoi(p+1);
00190 uassert( 10125 , "bad port #", remotePort > 0 && remotePort < 0x10000 );
00191 if ( remotePort == CmdLine::DefaultDBPort )
00192 remote = remoteHost;
00193 }
00194
00195 uassert( 10126 , "arbiter parm is missing, use '-' for none", arb);
00196 arbHost = arb;
00197 uassert( 10127 , "arbiter parm is empty", !arbHost.empty());
00198 }
00199
00200
00201
00202
00203 class PairSync {
00204 int initialsynccomplete;
00205 public:
00206 PairSync() {
00207 initialsynccomplete = -1;
00208 }
00209
00210
00211 void init() {
00212 BSONObj o;
00213 initialsynccomplete = 0;
00214 if ( Helpers::getSingleton("local.pair.sync", o) )
00215 initialsynccomplete = 1;
00216 }
00217
00218 bool initialSyncCompleted() {
00219 return initialsynccomplete != 0;
00220 }
00221
00222 void setInitialSyncCompleted() {
00223 BSONObj o = fromjson("{\"initialsynccomplete\":1}");
00224 Helpers::putSingleton("local.pair.sync", o);
00225 initialsynccomplete = 1;
00226 tlog() << "pair: initial sync complete" << endl;
00227 }
00228
00229 void setInitialSyncCompletedLocking() {
00230 if ( initialsynccomplete == 1 )
00231 return;
00232 dblock lk;
00233 setInitialSyncCompleted();
00234 }
00235 };
00236
00237
00238 }