Files
mongo/db/repl/replset.h

176 lines
5.7 KiB
C
Raw Normal View History

2010-04-15 19:12:28 -04:00
// /db/repl/replset.h
2010-04-13 17:38:15 -04:00
/**
* Copyright (C) 2008 10gen 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
2010-04-15 19:12:28 -04:00
#include "../../util/concurrency/list.h"
2010-04-20 15:30:37 -04:00
#include "../../util/concurrency/value.h"
2010-04-18 13:05:57 -04:00
#include "../../util/hostandport.h"
2010-05-11 16:10:02 -04:00
#include "rstime.h"
2010-05-05 14:57:49 -04:00
#include "rs_config.h"
2010-04-15 19:12:28 -04:00
2010-04-13 17:38:15 -04:00
namespace mongo {
2010-04-21 21:19:37 -04:00
extern bool replSet; // true if using repl sets
extern class ReplSet *theReplSet; // null until initialized
2010-04-14 17:25:03 -04:00
2010-05-07 16:42:55 -04:00
extern Tee *rsLog;
2010-04-13 17:40:49 -04:00
/* information about the entire repl set, such as the various servers in the set, and their state */
2010-04-15 19:12:28 -04:00
/* note: We currently do not free mem when the set goes away - it is assumed the replset is a
singleton and long lived.
*/
2010-04-13 17:38:15 -04:00
class ReplSet {
public:
2010-05-13 17:18:17 -04:00
static enum StartupStatus { PRESTART=0, LOADINGCONFIG=1, BADCONFIG=2, EMPTYCONFIG=3, EMPTYUNREACHABLE=4, STARTED=5, SOON=6 } startupStatus;
2010-04-21 17:40:24 -04:00
static string startupStatusMsg;
2010-04-21 16:43:51 -04:00
2010-05-13 17:18:17 -04:00
enum State {
STARTUP,
PRIMARY,
SECONDARY,
RECOVERING,
FATAL,
STARTUP2,
UNKNOWN /* remote node not yet reached */
};
private:
State _myState;
public:
2010-05-12 16:03:09 -04:00
void fatal();
bool isMaster(const char *client);
void fillIsMaster(BSONObjBuilder&);
2010-05-07 15:35:16 -04:00
bool ok() const { return _myState != FATAL; }
2010-05-13 17:18:17 -04:00
State state() const { return _myState; }
string name() const { return _name; } /* @return replica set's logical name */
2010-04-14 17:25:03 -04:00
/* cfgString format is
replsetname/host1,host2:port,...
2010-04-21 16:43:51 -04:00
where :port is optional.
throws exception if a problem initializing.
*/
2010-04-14 14:57:04 -04:00
ReplSet(string cfgString);
2010-04-14 17:25:03 -04:00
2010-05-05 14:00:25 -04:00
/* call after constructing to start - returns fairly quickly after launching its threads */
2010-05-11 15:58:44 -04:00
void go() { _myState = STARTUP2; startHealthThreads(); }
2010-05-05 14:00:25 -04:00
2010-04-21 16:43:51 -04:00
// for replSetGetStatus command
2010-04-20 12:29:00 -04:00
void summarizeStatus(BSONObjBuilder&) const;
2010-05-05 16:33:35 -04:00
void summarizeAsHtml(stringstream&) const;
2010-05-13 17:18:17 -04:00
const ReplSetConfig& config() { return *_cfg; }
void receivedNewConfig(BSONObj);
2010-04-20 12:29:00 -04:00
2010-04-13 17:40:49 -04:00
private:
string _name;
2010-04-18 13:05:57 -04:00
const vector<HostAndPort> *_seeds;
2010-05-13 17:18:17 -04:00
ReplSetConfig *_cfg;
2010-04-15 19:12:28 -04:00
2010-04-21 16:43:51 -04:00
/** load our configuration from admin.replset. try seed machines too.
throws exception if a problem.
*/
void loadConfig();
2010-05-03 13:33:49 -04:00
void finishLoadingConfig(vector<ReplSetConfig>& v);
2010-05-13 17:18:17 -04:00
void setFrom(ReplSetConfig& c, bool save);
2010-04-21 16:43:51 -04:00
2010-05-06 21:50:52 -04:00
struct Consensus {
ReplSet &rs;
Consensus(ReplSet *t) : rs(*t) { }
2010-05-07 12:37:09 -04:00
int totalVotes() const;
2010-05-06 21:50:52 -04:00
bool aMajoritySeemsToBeUp() const;
2010-05-07 15:35:16 -04:00
bool electSelf();
2010-05-06 21:50:52 -04:00
} elect;
2010-04-20 12:29:00 -04:00
2010-05-06 17:25:50 -04:00
public:
2010-05-05 14:57:49 -04:00
struct Member : public List1<Member>::Base {
2010-05-12 16:03:09 -04:00
Member(HostAndPort h, int ord, const ReplSetConfig::MemberCfg *c);
const HostAndPort _h;
const unsigned _id; // ordinal
2010-05-07 17:49:24 -04:00
string fullName() const { return _h.toString(); }
2010-04-22 11:58:19 -04:00
double health() const { return _health; }
time_t upSince() const { return _upSince; }
time_t lastHeartbeat() const { return _lastHeartbeat; }
2010-05-05 16:33:35 -04:00
const ReplSetConfig::MemberCfg& config() const { return *_config; }
bool up() const { return health() > 0; }
void summarizeAsHtml(stringstream& s) const;
2010-05-11 15:58:44 -04:00
ReplSet::State state() const { return _state; }
2010-05-12 16:03:09 -04:00
DiagStr _lastHeartbeatErrMsg;
2010-04-22 11:58:19 -04:00
private:
friend class FeedbackThread; // feedbackthread is the primary writer to these objects
2010-05-05 14:57:49 -04:00
const ReplSetConfig::MemberCfg *_config; /* todo: when this changes??? */
2010-05-12 17:43:21 -04:00
2010-04-22 11:58:19 -04:00
bool _dead;
double _health;
time_t _lastHeartbeat;
time_t _upSince;
2010-05-11 15:58:44 -04:00
ReplSet::State _state;
2010-04-15 19:12:28 -04:00
};
2010-05-06 17:25:50 -04:00
2010-05-12 16:03:09 -04:00
const Member* currentPrimary() const { return _currentPrimary; }
2010-05-13 11:03:23 -04:00
const ReplSetConfig::MemberCfg& myConfig() const { return _self->config(); }
2010-05-12 16:03:09 -04:00
2010-05-06 17:25:50 -04:00
private:
2010-05-12 16:03:09 -04:00
const Member *_currentPrimary;
2010-05-07 15:35:16 -04:00
static string stateAsStr(State state);
static string stateAsHtml(State state);
2010-05-05 14:57:49 -04:00
Member *_self;
2010-05-05 16:33:35 -04:00
/* all members of the set EXCEPT self. */
2010-05-05 14:57:49 -04:00
List1<Member> _members;
2010-05-05 16:33:35 -04:00
Member* head() const { return _members.head(); }
2010-04-15 19:12:28 -04:00
2010-04-18 12:30:40 -04:00
void startHealthThreads();
friend class FeedbackThread;
2010-05-07 15:35:16 -04:00
2010-05-11 15:58:44 -04:00
public:
class Manager : boost::noncopyable {
ReplSet *_rs;
int _primary;
2010-05-12 17:43:21 -04:00
const Member* findOtherPrimary();
void noteARemoteIsPrimary(const Member *);
2010-05-11 15:58:44 -04:00
public:
Manager(ReplSet *rs);
void checkNewState();
} _mgr;
2010-04-13 17:38:15 -04:00
};
2010-05-12 16:03:09 -04:00
inline void ReplSet::fatal()
{ _myState = FATAL; log() << "replSet error fatal error, stopping replication" << rsLog; }
inline ReplSet::Member::Member(HostAndPort h, int ord, const ReplSetConfig::MemberCfg *c) :
_h(h), _id(ord), _config(c)
{
_dead = false;
_lastHeartbeat = 0;
_upSince = 0;
_health = -1.0;
_state = UNKNOWN;
}
inline bool ReplSet::isMaster(const char *client) {
/* todo replset */
return false;
}
2010-04-13 17:38:15 -04:00
}