1 
2 /**
3  *    Copyright (C) 2018-present MongoDB, Inc.
4  *
5  *    This program is free software: you can redistribute it and/or modify
6  *    it under the terms of the Server Side Public License, version 1,
7  *    as published by MongoDB, Inc.
8  *
9  *    This program is distributed in the hope that it will be useful,
10  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *    Server Side Public License for more details.
13  *
14  *    You should have received a copy of the Server Side Public License
15  *    along with this program. If not, see
16  *    <http://www.mongodb.com/licensing/server-side-public-license>.
17  *
18  *    As a special exception, the copyright holders give permission to link the
19  *    code of portions of this program with the OpenSSL library under certain
20  *    conditions as described in each individual source file and distribute
21  *    linked combinations including the program with the OpenSSL library. You
22  *    must comply with the Server Side Public License in all respects for
23  *    all of the code used other than as permitted herein. If you modify file(s)
24  *    with this exception, you may extend this exception to your version of the
25  *    file(s), but you are not obligated to do so. If you do not wish to do so,
26  *    delete this exception statement from your version. If you delete this
27  *    exception statement from all source files in the program, then also delete
28  *    it in the license file.
29  */
30 
31 #pragma once
32 
33 #include "mongo/util/time_support.h"
34 
35 namespace mongo {
36 namespace repl {
37 
38 /**
39  * Description of actions taken in response to a heartbeat.
40  *
41  * This includes when to schedule the next heartbeat to a target, and any other actions to
42  * take, such as scheduling an election or stepping down as primary.
43  */
44 class HeartbeatResponseAction {
45 public:
46     /**
47      * Actions taken based on heartbeat responses
48      */
49     enum Action {
50         NoAction,
51         Reconfig,
52         StartElection,
53         StepDownSelf,
54         StepDownRemotePrimary,
55         PriorityTakeover,
56         CatchupTakeover
57     };
58 
59     /**
60      * Makes a new action representing doing nothing.
61      */
62     static HeartbeatResponseAction makeNoAction();
63 
64     /**
65      * Makes a new action representing the instruction to reconfigure the current node.
66      */
67     static HeartbeatResponseAction makeReconfigAction();
68 
69     /**
70      * Makes a new action telling the current node to attempt to elect itself primary.
71      */
72     static HeartbeatResponseAction makeElectAction();
73 
74     /**
75      * Makes a new action telling the current node to schedule an event to attempt to elect itself
76      * primary after the appropriate priority takeover delay.
77      */
78     static HeartbeatResponseAction makePriorityTakeoverAction();
79 
80     /**
81      * Makes a new action telling the current node to schedule an event to attempt to elect itself
82      * primary after the appropriate catchup takeover delay.
83      */
84     static HeartbeatResponseAction makeCatchupTakeoverAction();
85 
86     /**
87      * Makes a new action telling the current node to step down as primary.
88      *
89      * It is an error to call this with primaryIndex != the index of the current node.
90      */
91     static HeartbeatResponseAction makeStepDownSelfAction(int primaryIndex);
92 
93     /**
94      * Makes a new action telling the current node to ask the specified remote node to step
95      * down as primary.
96      *
97      * It is an error to call this with primaryIndex == the index of the current node.
98      */
99     static HeartbeatResponseAction makeStepDownRemoteAction(int primaryIndex);
100 
101     /**
102      * Construct an action with unspecified action and a next heartbeat start date in the
103      * past.
104      */
105     HeartbeatResponseAction();
106 
107     /**
108      * Sets the date at which the next heartbeat should be scheduled.
109      */
110     void setNextHeartbeatStartDate(Date_t when);
111 
112     /**
113      * Sets whether or not the heartbeat response advanced the member's opTime.
114      */
115     void setAdvancedOpTime(bool advanced);
116 
117     /**
118      * Gets the action type of this action.
119      */
getAction()120     Action getAction() const {
121         return _action;
122     }
123 
124     /**
125      * Gets the time at which the next heartbeat should be scheduled.  If the
126      * time is not in the future, the next heartbeat should be scheduled immediately.
127      */
getNextHeartbeatStartDate()128     Date_t getNextHeartbeatStartDate() const {
129         return _nextHeartbeatStartDate;
130     }
131 
132     /**
133      * If getAction() returns StepDownSelf or StepDownPrimary, this is the index
134      * in the current replica set config of the node that ought to step down.
135      */
getPrimaryConfigIndex()136     int getPrimaryConfigIndex() const {
137         return _primaryIndex;
138     }
139 
140     /*
141      * Returns true if the heartbeat response resulting in our conception of the
142      * member's optime moving forward, so we need to recalculate lastCommittedOpTime.
143      */
getAdvancedOpTime()144     bool getAdvancedOpTime() const {
145         return _advancedOpTime;
146     }
147 
148 private:
149     Action _action;
150     int _primaryIndex;
151     Date_t _nextHeartbeatStartDate;
152     bool _advancedOpTime = false;
153 };
154 
155 }  // namespace repl
156 }  // namespace mongo
157