void LegacyReplicationCoordinator::prepareReplSetUpdatePositionCommandHandshakes( OperationContext* txn, std::vector<BSONObj>* handshakes) { invariant(getReplicationMode() == modeReplSet); boost::lock_guard<boost::mutex> lock(_mutex); // handshake obj for us BSONObjBuilder cmd; cmd.append("replSetUpdatePosition", 1); BSONObjBuilder sub (cmd.subobjStart("handshake")); sub.append("handshake", getMyRID(txn)); sub.append("member", theReplSet->selfId()); sub.append("config", theReplSet->myConfig().asBson()); sub.doneFast(); handshakes->push_back(cmd.obj()); // handshake objs for all chained members for (OIDMemberMap::const_iterator itr = _ridMemberMap.begin(); itr != _ridMemberMap.end(); ++itr) { BSONObjBuilder cmd; cmd.append("replSetUpdatePosition", 1); // outer handshake indicates this is a handshake command // inner is needed as part of the structure to be passed to gotHandshake BSONObjBuilder subCmd (cmd.subobjStart("handshake")); subCmd.append("handshake", itr->first); subCmd.append("member", itr->second->id()); subCmd.append("config", itr->second->config().asBson()); subCmd.doneFast(); handshakes->push_back(cmd.obj()); } }
void LegacyReplicationCoordinator::prepareReplSetUpdatePositionCommand( OperationContext* txn, BSONObjBuilder* cmdBuilder) { invariant(getReplicationMode() == modeReplSet); boost::lock_guard<boost::mutex> lock(_mutex); cmdBuilder->append("replSetUpdatePosition", 1); // create an array containing objects each member connected to us and for ourself BSONArrayBuilder arrayBuilder(cmdBuilder->subarrayStart("optimes")); OID myID = getMyRID(txn); { for (SlaveOpTimeMap::const_iterator itr = _slaveOpTimeMap.begin(); itr != _slaveOpTimeMap.end(); ++itr) { const OID& rid = itr->first; const BSONObj& config = mapFindWithDefault(_ridConfigMap, rid, BSONObj()); BSONObjBuilder entry(arrayBuilder.subobjStart()); entry.append("_id", rid); entry.append("optime", itr->second); // SERVER-14550 Even though the "config" field isn't used on the other end in 2.8, // we need to keep sending it for 2.6 compatibility. // TODO(spencer): Remove this after 2.8 is released. if (rid == myID) { entry.append("config", theReplSet->myConfig().asBson()); } else { entry.append("config", config); } } } }
Status LegacyReplicationCoordinator::setLastOptime(OperationContext* txn, const OID& rid, const OpTime& ts) { { boost::lock_guard<boost::mutex> lock(_mutex); if (ts <= mapFindWithDefault(_slaveOpTimeMap, rid, OpTime())) { // Only update if ts is newer than what we have already return Status::OK(); } BSONObj config = mapFindWithDefault(_ridConfigMap, rid, BSONObj()); LOG(2) << "received notification that node with RID " << rid << " and config " << config << " has reached optime: " << ts.toStringPretty(); if (rid != getMyRID(txn)) { // TODO(spencer): Remove this invariant for backwards compatibility invariant(!config.isEmpty()); // This is what updates the progress information used for satisfying write concern // and wakes up threads waiting for replication. if (!updateSlaveTracking(BSON("_id" << rid), config, ts)) { return Status(ErrorCodes::NodeNotFound, str::stream() << "could not update node with _id: " << config["_id"].Int() << " because it cannot be found in current ReplSetConfig"); } } // This updates the _slaveOpTimeMap which is used for forwarding slave progress // upstream in chained replication. LOG(2) << "Updating our knowledge of the replication progress for node with RID " << rid << " to be at optime " << ts; _slaveOpTimeMap[rid] = ts; } if (getReplicationMode() == modeReplSet && !getCurrentMemberState().primary()) { // pass along if we are not primary theReplSet->syncSourceFeedback.forwardSlaveProgress(); } return Status::OK(); }
void ReplicationCoordinatorImpl::prepareReplSetUpdatePositionCommandHandshakes( OperationContext* txn, std::vector<BSONObj>* handshakes) { boost::lock_guard<boost::mutex> lock(_mutex); // handshake obj for us BSONObjBuilder cmd; cmd.append("replSetUpdatePosition", 1); { BSONObjBuilder sub (cmd.subobjStart("handshake")); sub.append("handshake", getMyRID(txn)); sub.append("member", _thisMembersConfigIndex); // SERVER-14550 Even though the "config" field isn't used on the other end in 2.8, // we need to keep sending it for 2.6 compatibility. // TODO(spencer): Remove this after 2.8 is released. sub.append("config", _rsConfig.getMemberAt(_thisMembersConfigIndex).toBSON( _rsConfig.getTagConfig())); } handshakes->push_back(cmd.obj()); // handshake objs for all chained members for (SlaveInfoMap::const_iterator itr = _slaveInfoMap.begin(); itr != _slaveInfoMap.end(); ++itr) { BSONObjBuilder cmd; cmd.append("replSetUpdatePosition", 1); { BSONObjBuilder subCmd (cmd.subobjStart("handshake")); subCmd.append("handshake", itr->first); int memberID = itr->second.memberID; subCmd.append("member", memberID); // SERVER-14550 Even though the "config" field isn't used on the other end in 2.8, // we need to keep sending it for 2.6 compatibility. // TODO(spencer): Remove this after 2.8 is released. subCmd.append("config", _rsConfig.getMemberAt(memberID).toBSON(_rsConfig.getTagConfig())); } handshakes->push_back(cmd.obj()); } }
OpTime ReplicationCoordinatorImpl::_getLastOpApplied() { boost::lock_guard<boost::mutex> lk(_mutex); OperationContextNoop txn; return _slaveInfoMap[getMyRID(&txn)].opTime; }