raft_core.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2015 Pavel Kirienko <pavel.kirienko@gmail.com>
3  */
4 
5 #ifndef UAVCAN_PROTOCOL_DYNAMIC_NODE_ID_SERVER_DISTRIBUTED_RAFT_CORE_HPP_INCLUDED
6 #define UAVCAN_PROTOCOL_DYNAMIC_NODE_ID_SERVER_DISTRIBUTED_RAFT_CORE_HPP_INCLUDED
7 
8 #include <cstdlib>
10 #include <uavcan/debug.hpp>
12 #include <uavcan/node/timer.hpp>
19 // UAVCAN types
20 #include <uavcan/protocol/dynamic_node_id/server/AppendEntries.hpp>
21 #include <uavcan/protocol/dynamic_node_id/server/RequestVote.hpp>
22 
23 namespace uavcan
24 {
25 namespace dynamic_node_id_server
26 {
27 namespace distributed
28 {
33 {
34 public:
38  virtual void handleLogCommitOnLeader(const Entry& committed_entry) = 0;
39 
45  virtual void handleLocalLeadershipChange(bool local_node_is_leader) = 0;
46 
47  virtual ~IRaftLeaderMonitor() { }
48 };
49 
64 class RaftCore : private TimerBase
65 {
66 public:
68  {
72  };
73 
74 private:
78 
81 
85 
88 
90  {
93 
95  : prev_log_index(0)
96  , num_entries(0)
97  { }
98  };
99 
100  /*
101  * Constants
102  */
104 
107 
108  /*
109  * States
110  */
114 
118 
121 
123 
124  /*
125  * Transport
126  */
131 
132  /*
133  * Methods
134  */
135  void trace(TraceCode event, int64_t argument) { tracer_.onEvent(event, argument); }
136 
137  INode& getNode() { return append_entries_srv_.getNode(); }
138  const INode& getNode() const { return append_entries_srv_.getNode(); }
139 
140  void checkInvariants() const
141  {
142  // Commit index
144 
145  // Term
150 
151  // Elections
153  persistent_state_.getVotedFor() == getNode().getNodeID());
155 
156  // Transport
157  UAVCAN_ASSERT(append_entries_client_.getNumPendingCalls() <= 1);
162  (!append_entries_client_.hasPendingCalls() && !request_vote_client_.hasPendingCalls()));
163  }
164 
166  {
168 
169  static const int32_t randomization_range_msec = AppendEntries::Request::DEFAULT_MAX_ELECTION_TIMEOUT_MS -
170  AppendEntries::Request::DEFAULT_MIN_ELECTION_TIMEOUT_MS;
171  // coverity[dont_call]
172  const int32_t random_msec = (std::rand() % randomization_range_msec) + 1;
173 
175  MonotonicDuration::fromMSec(AppendEntries::Request::DEFAULT_MIN_ELECTION_TIMEOUT_MS + random_msec);
176 
177  UAVCAN_ASSERT(randomized_activity_timeout_.toMSec() > AppendEntries::Request::DEFAULT_MIN_ELECTION_TIMEOUT_MS);
178  UAVCAN_ASSERT(randomized_activity_timeout_.toMSec() <= AppendEntries::Request::DEFAULT_MAX_ELECTION_TIMEOUT_MS);
179  }
180 
181  bool isActivityTimedOut() const
182  {
184  }
185 
187  {
188  UAVCAN_ASSERT(error < 0);
191  registerActivity(); // Deferring reelections
192  }
193 
195  {
196  if (isActivityTimedOut())
197  {
200  }
201  }
202 
204  {
206  {
209 
210  UAVCAN_TRACE("dynamic_node_id_server::distributed::RaftCore", "Election complete, won: %d", int(won));
211 
212  switchState(won ? ServerStateLeader : ServerStateFollower); // Start over or become leader
213  }
214  else
215  {
216  // Set votedFor, abort on failure
217  int res = persistent_state_.setVotedFor(getNode().getNodeID());
218  if (res < 0)
219  {
221  return;
222  }
223 
224  // Increment current term, abort on failure
226  if (res < 0)
227  {
229  return;
230  }
231 
232  num_votes_received_in_this_campaign_ = 1; // Voting for self
233 
234  RequestVote::Request req;
235  req.last_log_index = persistent_state_.getLog().getLastIndex();
236  req.last_log_term = persistent_state_.getLog().getEntryAtIndex(req.last_log_index)->term;
237  req.term = persistent_state_.getCurrentTerm();
238 
239  for (uint8_t i = 0; i < MaxNumFollowers; i++)
240  {
241  const NodeID node_id = cluster_.getRemoteServerNodeIDAtIndex(i);
242  if (!node_id.isUnicast())
243  {
244  break;
245  }
246 
247  UAVCAN_TRACE("dynamic_node_id_server::distributed::RaftCore",
248  "Requesting vote from %d", int(node_id.get()));
250 
251  res = request_vote_client_.call(node_id, req);
252  if (res < 0)
253  {
254  trace(TraceError, res);
255  }
256  }
257  }
258  }
259 
261  {
262  if (append_entries_client_.hasPendingCalls())
263  {
264  append_entries_client_.cancelAllCalls(); // Refer to the response callback to learn why
265  }
266 
267  if (cluster_.getClusterSize() > 1)
268  {
270  UAVCAN_ASSERT(node_id.isUnicast());
271 
274  {
275  next_server_index_ = 0;
276  }
277 
278  AppendEntries::Request req;
279  req.term = persistent_state_.getCurrentTerm();
280  req.leader_commit = commit_index_;
281 
282  req.prev_log_index = Log::Index(cluster_.getServerNextIndex(node_id) - 1U);
283 
284  const Entry* const entry = persistent_state_.getLog().getEntryAtIndex(req.prev_log_index);
285  if (entry == UAVCAN_NULLPTR)
286  {
287  UAVCAN_ASSERT(0);
289  return;
290  }
291 
292  req.prev_log_term = entry->term;
293 
294  for (Log::Index index = cluster_.getServerNextIndex(node_id);
296  index++)
297  {
298  req.entries.push_back(*persistent_state_.getLog().getEntryAtIndex(index));
299  if (req.entries.size() == req.entries.capacity())
300  {
301  break;
302  }
303  }
304 
305  pending_append_entries_fields_.num_entries = req.entries.size();
306  pending_append_entries_fields_.prev_log_index = req.prev_log_index;
307 
308  const int res = append_entries_client_.call(node_id, req);
309  if (res < 0)
310  {
312  }
313  }
314 
316  }
317 
318  void switchState(ServerState new_state)
319  {
320  if (server_state_ == new_state)
321  {
322  return;
323  }
324 
325  /*
326  * Logging
327  */
328  UAVCAN_TRACE("dynamic_node_id_server::distributed::RaftCore", "State switch: %d --> %d",
329  int(server_state_), int(new_state));
330  trace(TraceRaftStateSwitch, new_state);
331 
332  /*
333  * Updating the current state
334  */
335  const ServerState old_state = server_state_;
336  server_state_ = new_state;
337 
338  /*
339  * Resetting specific states
340  */
342 
343  next_server_index_ = 0;
345 
346  request_vote_client_.cancelAllCalls();
347  append_entries_client_.cancelAllCalls();
348 
349  /*
350  * Calling the switch handler
351  * Note that the handler may commit to the log directly
352  */
353  if ((old_state == ServerStateLeader) ||
354  (new_state == ServerStateLeader))
355  {
357  }
358  }
359 
361  {
363  const int res = persistent_state_.setCurrentTerm(new_term);
364  if (res < 0)
365  {
367  }
368  registerActivity(); // Deferring future elections
370  }
371 
373  {
374  // Objective is to estimate whether we can safely increment commit index value
377 
379  {
380  /*
381  * Not all local entries are committed.
382  * Deciding if it is safe to increment commit index.
383  */
384  uint8_t num_nodes_with_next_log_entry_available = 1; // Local node
385  for (uint8_t i = 0; i < cluster_.getNumKnownServers(); i++)
386  {
388  if (match_index > commit_index_)
389  {
390  num_nodes_with_next_log_entry_available++;
391  }
392  }
393 
394  if (num_nodes_with_next_log_entry_available >= cluster_.getQuorumSize())
395  {
396  commit_index_++;
397  UAVCAN_ASSERT(commit_index_ > 0); // Index 0 is always committed
399 
400  // AT THIS POINT ALLOCATION IS COMPLETE
402  }
403  }
404  }
405 
408  {
409  checkInvariants();
410 
411  if (!cluster_.isKnownServer(request.getSrcNodeID()))
412  {
414  {
415  trace(TraceRaftRequestIgnored, request.getSrcNodeID().get());
416  response.setResponseEnabled(false);
417  return;
418  }
419  else
420  {
421  cluster_.addServer(request.getSrcNodeID());
422  }
423  }
424 
425  UAVCAN_ASSERT(response.isResponseEnabled()); // This is default
426 
427  /*
428  * Checking if our current state is up to date.
429  * The request will be ignored if persistent state cannot be updated.
430  */
431  if (request.term > persistent_state_.getCurrentTerm())
432  {
433  int res = persistent_state_.setCurrentTerm(request.term);
434  if (res < 0)
435  {
437  response.setResponseEnabled(false);
438  return;
439  }
440 
442  if (res < 0)
443  {
445  response.setResponseEnabled(false);
446  return;
447  }
448  }
449 
450  /*
451  * Preparing the response
452  */
454  response.success = false;
455 
456  /*
457  * Step 1 (see Raft paper)
458  * Reject the request if the leader has stale term number.
459  */
460  if (request.term < persistent_state_.getCurrentTerm())
461  {
462  response.setResponseEnabled(true);
463  return;
464  }
465 
468 
469  /*
470  * Step 2
471  * Reject the request if the assumed log index does not exist on the local node.
472  */
473  const Entry* const prev_entry = persistent_state_.getLog().getEntryAtIndex(request.prev_log_index);
474  if (prev_entry == UAVCAN_NULLPTR)
475  {
476  response.setResponseEnabled(true);
477  return;
478  }
479 
480  /*
481  * Step 3
482  * Drop log entries if term number does not match.
483  * Ignore the request if the persistent state cannot be updated.
484  */
485  if (prev_entry->term != request.prev_log_term)
486  {
487  const int res = persistent_state_.getLog().removeEntriesWhereIndexGreaterOrEqual(request.prev_log_index);
488  response.setResponseEnabled(res >= 0);
489  if (res < 0)
490  {
492  }
493  return;
494  }
495 
496  /*
497  * Step 4
498  * Update the log with new entries - this will possibly require to rewrite existing entries.
499  * Ignore the request if the persistent state cannot be updated.
500  */
501  if (request.prev_log_index != persistent_state_.getLog().getLastIndex())
502  {
503  const int res = persistent_state_.getLog().removeEntriesWhereIndexGreater(request.prev_log_index);
504  if (res < 0)
505  {
507  response.setResponseEnabled(false);
508  return;
509  }
510  }
511 
512  for (uint8_t i = 0; i < request.entries.size(); i++)
513  {
514  const int res = persistent_state_.getLog().append(request.entries[i]);
515  if (res < 0)
516  {
518  response.setResponseEnabled(false);
519  return; // Response will not be sent, the server will assume that we're dead
520  }
521  }
522 
523  /*
524  * Step 5
525  * Update the commit index.
526  */
527  if (request.leader_commit > commit_index_)
528  {
529  commit_index_ = min(request.leader_commit, persistent_state_.getLog().getLastIndex());
531  }
532 
533  response.setResponseEnabled(true);
534  response.success = true;
535  }
536 
538  {
539  UAVCAN_ASSERT(server_state_ == ServerStateLeader); // When state switches, all requests must be cancelled
540  checkInvariants();
541 
542  if (!result.isSuccessful())
543  {
544  return;
545  }
546 
547  if (result.getResponse().term > persistent_state_.getCurrentTerm())
548  {
550  }
551  else
552  {
553  if (result.getResponse().success)
554  {
555  cluster_.incrementServerNextIndexBy(result.getCallID().server_node_id,
557  cluster_.setServerMatchIndex(result.getCallID().server_node_id,
560  }
561  else
562  {
563  cluster_.decrementServerNextIndex(result.getCallID().server_node_id);
564  trace(TraceRaftAppendEntriesRespUnsucfl, result.getCallID().server_node_id.get());
565  }
566  }
567 
569  // Rest of the logic is implemented in periodic update handlers.
570  }
571 
574  {
575  checkInvariants();
577 
578  if (!cluster_.isKnownServer(request.getSrcNodeID()))
579  {
580  trace(TraceRaftRequestIgnored, request.getSrcNodeID().get());
581  response.setResponseEnabled(false);
582  return;
583  }
584 
585  UAVCAN_ASSERT(response.isResponseEnabled()); // This is default
586 
587  /*
588  * Checking if our current state is up to date.
589  * The request will be ignored if persistent state cannot be updated.
590  */
591  if (request.term > persistent_state_.getCurrentTerm())
592  {
593  switchState(ServerStateFollower); // Our term is stale, so we can't serve as leader
594 
595  int res = persistent_state_.setCurrentTerm(request.term);
596  if (res < 0)
597  {
599  response.setResponseEnabled(false);
600  return;
601  }
602 
604  if (res < 0)
605  {
607  response.setResponseEnabled(false);
608  return;
609  }
610  }
611 
612  /*
613  * Preparing the response
614  */
616 
617  if (request.term < response.term)
618  {
619  response.vote_granted = false;
620  }
621  else
622  {
623  const bool can_vote = !persistent_state_.isVotedForSet() ||
624  (persistent_state_.getVotedFor() == request.getSrcNodeID());
625  const bool log_is_up_to_date =
626  persistent_state_.getLog().isOtherLogUpToDate(request.last_log_index, request.last_log_term);
627 
628  response.vote_granted = can_vote && log_is_up_to_date;
629 
630  if (response.vote_granted)
631  {
632  switchState(ServerStateFollower); // Avoiding race condition when Candidate
633  registerActivity(); // This is necessary to avoid excessive elections
634 
635  const int res = persistent_state_.setVotedFor(request.getSrcNodeID());
636  if (res < 0)
637  {
639  response.setResponseEnabled(false);
640  return;
641  }
642  }
643  }
644  }
645 
647  {
648  UAVCAN_ASSERT(server_state_ == ServerStateCandidate); // When state switches, all requests must be cancelled
649  checkInvariants();
650 
651  if (!result.isSuccessful())
652  {
653  return;
654  }
655 
656  trace(TraceRaftVoteRequestSucceeded, result.getCallID().server_node_id.get());
657 
658  if (result.getResponse().term > persistent_state_.getCurrentTerm())
659  {
661  }
662  else
663  {
664  if (result.getResponse().vote_granted)
665  {
667  }
668  }
669  // Rest of the logic is implemented in periodic update handlers.
670  // I'm no fan of asynchronous programming. At all.
671  }
672 
673  virtual void handleTimerEvent(const TimerEvent&)
674  {
675  checkInvariants();
676 
677  switch (server_state_)
678  {
679  case ServerStateFollower:
680  {
681  updateFollower();
682  break;
683  }
685  {
686  updateCandidate();
687  break;
688  }
689  case ServerStateLeader:
690  {
691  updateLeader();
692  break;
693  }
694  default:
695  {
696  UAVCAN_ASSERT(0);
697  break;
698  }
699  }
700  }
701 
702 public:
704  IStorageBackend& storage,
705  IEventTracer& tracer,
706  IRaftLeaderMonitor& leader_monitor)
707  : TimerBase(node)
708  , tracer_(tracer)
709  , leader_monitor_(leader_monitor)
710  , persistent_state_(storage, tracer)
711  , cluster_(node, storage, persistent_state_.getLog(), tracer)
712  , commit_index_(0) // Per Raft paper, commitIndex must be initialized to zero
713  , last_activity_timestamp_(node.getMonotonicTime())
715  MonotonicDuration::fromMSec(AppendEntries::Request::DEFAULT_MAX_ELECTION_TIMEOUT_MS))
717  , next_server_index_(0)
723  { }
724 
731  int init(const uint8_t cluster_size, const TransferPriority priority)
732  {
733  /*
734  * Initializing state variables
735  */
737  next_server_index_ = 0;
739  commit_index_ = 0;
740 
742 
743  /*
744  * Initializing internals
745  */
746  int res = persistent_state_.init();
747  if (res < 0)
748  {
749  return res;
750  }
751 
752  res = cluster_.init(cluster_size, priority);
753  if (res < 0)
754  {
755  return res;
756  }
757 
759  if (res < 0)
760  {
761  return res;
762  }
763 
765  if (res < 0)
766  {
767  return res;
768  }
769 
770  res = append_entries_client_.init(priority);
771  if (res < 0)
772  {
773  return res;
774  }
777 
778  res = request_vote_client_.init(priority);
779  if (res < 0)
780  {
781  return res;
782  }
784 
785  /*
786  * Initializing timing constants
787  * Refer to the specification for the formula
788  */
789  const uint8_t num_followers = static_cast<uint8_t>(cluster_.getClusterSize() - 1);
790 
791  const MonotonicDuration update_interval =
792  MonotonicDuration::fromMSec(AppendEntries::Request::DEFAULT_MIN_ELECTION_TIMEOUT_MS /
793  2 / max(static_cast<uint8_t>(2), num_followers));
794 
795  UAVCAN_TRACE("dynamic_node_id_server::distributed::RaftCore",
796  "Update interval: %ld msec", static_cast<long>(update_interval.toMSec()));
797 
798  append_entries_client_.setRequestTimeout(min(append_entries_client_.getDefaultRequestTimeout(),
799  update_interval));
800 
801  request_vote_client_.setRequestTimeout(min(request_vote_client_.getDefaultRequestTimeout(),
802  update_interval));
803 
804  startPeriodic(update_interval);
805 
806  trace(TraceRaftCoreInited, update_interval.toUSec());
807 
808  UAVCAN_ASSERT(res >= 0);
809  return 0;
810  }
811 
816 
821 
825  bool isLeader() const { return server_state_ == ServerStateLeader; }
826 
832  void appendLog(const Entry::FieldTypes::unique_id& unique_id, NodeID node_id)
833  {
834  if (isLeader())
835  {
836  Entry entry;
837  entry.node_id = node_id.get();
838  entry.unique_id = unique_id;
839  entry.term = persistent_state_.getCurrentTerm();
840 
841  trace(TraceRaftNewLogEntry, entry.node_id);
842  const int res = persistent_state_.getLog().append(entry);
843  if (res < 0)
844  {
846  }
847  }
848  else
849  {
850  UAVCAN_ASSERT(0);
851  }
852  }
853 
858  {
860  bool committed;
861 
862  LogEntryInfo(const Entry& arg_entry, bool arg_committed)
863  : entry(arg_entry)
864  , committed(arg_committed)
865  { }
866  };
867 
877  template <typename Predicate>
878  inline LazyConstructor<LogEntryInfo> traverseLogFromEndUntil(const Predicate& predicate) const
879  {
880  UAVCAN_ASSERT(coerceOrFallback<bool>(predicate, true));
881  for (int index = static_cast<int>(persistent_state_.getLog().getLastIndex()); index >= 0; index--)
882  {
883  const Entry* const entry = persistent_state_.getLog().getEntryAtIndex(Log::Index(index));
884  UAVCAN_ASSERT(entry != UAVCAN_NULLPTR);
885  const LogEntryInfo info(*entry, Log::Index(index) <= commit_index_);
886  if (predicate(info))
887  {
889  ret.template construct<const LogEntryInfo&>(info);
890  return ret;
891  }
892  }
894  }
895 
897  {
898  // Remember that index zero contains a special-purpose entry that doesn't count as allocation
900  }
901 
906  const ClusterManager& getClusterManager() const { return cluster_; }
911 };
912 
913 }
914 }
915 }
916 
917 #endif // Include guard
response
const std::string response
uavcan::dynamic_node_id_server::distributed::RaftCore::RequestVoteCallback
MethodBinder< RaftCore *, void(RaftCore::*)(const ReceivedDataStructure< RequestVote::Request > &, ServiceResponseDataStructure< RequestVote::Response > &)> RequestVoteCallback
Definition: raft_core.hpp:84
uavcan::dynamic_node_id_server::distributed::ClusterManager::getClusterSize
uint8_t getClusterSize() const
Definition: cluster_manager.hpp:423
uavcan::dynamic_node_id_server::distributed::ClusterManager::isClusterDiscovered
bool isClusterDiscovered() const
Definition: cluster_manager.hpp:426
uavcan::TimerBase
Definition: timer.hpp:46
uavcan::TimerBase::getPeriod
MonotonicDuration getPeriod() const
Definition: timer.hpp:77
UAVCAN_NULLPTR
#define UAVCAN_NULLPTR
Definition: libuavcan/libuavcan/include/uavcan/build_config.hpp:51
uavcan::dynamic_node_id_server::distributed::PersistentState::getLog
Log & getLog()
Definition: persistent_state.hpp:165
uavcan::INode::getMonotonicTime
MonotonicTime getMonotonicTime() const
Definition: abstract_node.hpp:32
TraceError
TraceError
Definition: event.hpp:23
uavcan::DurationBase::toMSec
int64_t toMSec() const
Definition: time.hpp:44
persistent_state.hpp
TraceRaftRequestIgnored
TraceRaftRequestIgnored
Definition: event.hpp:43
TraceRaftNewEntryCommitted
TraceRaftNewEntryCommitted
Definition: event.hpp:51
uavcan::dynamic_node_id_server::distributed::RaftCore::registerActivity
void registerActivity()
Definition: raft_core.hpp:165
TraceRaftVoteRequestSucceeded
TraceRaftVoteRequestSucceeded
Definition: event.hpp:45
debug.hpp
uavcan::dynamic_node_id_server::distributed::Term
StorageType< Entry::FieldTypes::term >::Type Term
Definition: protocol/dynamic_node_id_server/distributed/types.hpp:23
uavcan::dynamic_node_id_server::distributed::RaftCore::commit_index_
Log::Index commit_index_
Definition: raft_core.hpp:113
uavcan::dynamic_node_id_server::distributed::Log::isOtherLogUpToDate
bool isOtherLogUpToDate(Index other_last_index, Term other_last_term) const
Definition: log.hpp:293
uavcan::dynamic_node_id_server::distributed::RaftCore::ServerState
ServerState
Definition: raft_core.hpp:67
uavcan::dynamic_node_id_server::distributed::IRaftLeaderMonitor::handleLogCommitOnLeader
virtual void handleLogCommitOnLeader(const Entry &committed_entry)=0
uavcan::dynamic_node_id_server::distributed::ClusterManager::decrementServerNextIndex
void decrementServerNextIndex(NodeID server_node_id)
Definition: cluster_manager.hpp:362
uavcan::dynamic_node_id_server::distributed::PersistentState::isVotedForSet
bool isVotedForSet() const
Definition: persistent_state.hpp:163
uavcan::ServiceCallResult::getCallID
ServiceCallID getCallID() const
Definition: service_client.hpp:83
uavcan::dynamic_node_id_server::distributed::RaftCore::server_state_
ServerState server_state_
Definition: raft_core.hpp:117
uavcan::dynamic_node_id_server::distributed::Log::Index
uint8_t Index
Definition: log.hpp:28
uavcan::dynamic_node_id_server::distributed::ClusterManager::getRemoteServerNodeIDAtIndex
NodeID getRemoteServerNodeIDAtIndex(uint8_t index) const
Definition: cluster_manager.hpp:326
uavcan::dynamic_node_id_server::distributed::RaftCore::tracer_
IEventTracer & tracer_
Definition: raft_core.hpp:105
pyuavcan_v0.dsdl.parser.error
def error(fmt, *args)
Definition: parser.py:722
uavcan::NodeID::get
uint8_t get() const
Definition: transfer.hpp:132
uavcan::dynamic_node_id_server::distributed::Log::getEntryAtIndex
const Entry * getEntryAtIndex(Index index) const
Definition: log.hpp:285
uavcan::NodeID
Definition: transfer.hpp:112
uavcan::dynamic_node_id_server::distributed::RaftCore::propagateCommitIndex
void propagateCommitIndex()
Definition: raft_core.hpp:372
uavcan::dynamic_node_id_server::distributed::RaftCore::isActivityTimedOut
bool isActivityTimedOut() const
Definition: raft_core.hpp:181
TraceRaftNewerTermInResponse
TraceRaftNewerTermInResponse
Definition: event.hpp:50
uavcan::DurationBase< MonotonicDuration >::fromMSec
static MonotonicDuration fromMSec(int64_t ms)
Definition: time.hpp:41
uavcan::dynamic_node_id_server::distributed::RaftCore::areAllLogEntriesCommitted
bool areAllLogEntriesCommitted() const
Definition: raft_core.hpp:820
uavcan::dynamic_node_id_server::distributed::RaftCore::updateFollower
void updateFollower()
Definition: raft_core.hpp:194
event.hpp
service_client.hpp
uavcan::dynamic_node_id_server::distributed::PersistentState::setVotedFor
int setVotedFor(NodeID node_id)
Definition: persistent_state.hpp:202
uavcan::dynamic_node_id_server::distributed::RaftCore::handleRequestVoteResponse
void handleRequestVoteResponse(const ServiceCallResult< RequestVote > &result)
Definition: raft_core.hpp:646
TraceRaftPersistStateUpdateError
TraceRaftPersistStateUpdateError
Definition: event.hpp:48
uavcan::dynamic_node_id_server::distributed::RaftCore::leader_monitor_
IRaftLeaderMonitor & leader_monitor_
Definition: raft_core.hpp:106
uavcan::dynamic_node_id_server::distributed::RaftCore::RaftCore
RaftCore(INode &node, IStorageBackend &storage, IEventTracer &tracer, IRaftLeaderMonitor &leader_monitor)
Definition: raft_core.hpp:703
uavcan::ReceivedDataStructure
Definition: generic_subscriber.hpp:39
uavcan::dynamic_node_id_server::distributed::ClusterManager::getServerNextIndex
Log::Index getServerNextIndex(NodeID server_node_id) const
Definition: cluster_manager.hpp:338
UAVCAN_TRACE
#define UAVCAN_TRACE(...)
Definition: libuavcan/libuavcan/include/uavcan/debug.hpp:31
uavcan::dynamic_node_id_server::distributed::RaftCore::getUpdateInterval
MonotonicDuration getUpdateInterval() const
Definition: raft_core.hpp:909
uavcan::int64_t
std::int64_t int64_t
Definition: std.hpp:32
uavcan::dynamic_node_id_server::distributed::ClusterManager::isKnownServer
bool isKnownServer(NodeID node_id) const
Definition: cluster_manager.hpp:304
uavcan::dynamic_node_id_server::distributed::PersistentState::init
int init()
Definition: persistent_state.hpp:53
uavcan::dynamic_node_id_server::distributed::RaftCore::appendLog
void appendLog(const Entry::FieldTypes::unique_id &unique_id, NodeID node_id)
Definition: raft_core.hpp:832
types.hpp
uavcan::MonotonicDuration
Definition: time.hpp:182
uavcan::dynamic_node_id_server::distributed::RaftCore::checkInvariants
void checkInvariants() const
Definition: raft_core.hpp:140
uavcan::dynamic_node_id_server::distributed::Log::append
int append(const Entry &entry)
Definition: log.hpp:202
uavcan::dynamic_node_id_server::distributed::RaftCore::tryIncrementCurrentTermFromResponse
void tryIncrementCurrentTermFromResponse(Term new_term)
Definition: raft_core.hpp:360
uavcan::dynamic_node_id_server::distributed::ClusterManager::incrementServerNextIndexBy
void incrementServerNextIndexBy(NodeID server_node_id, Log::Index increment)
Definition: cluster_manager.hpp:349
timer.hpp
uavcan::dynamic_node_id_server::distributed::RaftCore
Definition: raft_core.hpp:64
uavcan::dynamic_node_id_server::distributed::RaftCore::request_vote_client_
ServiceClient< RequestVote, RequestVoteResponseCallback > request_vote_client_
Definition: raft_core.hpp:130
uavcan::ServiceCallResult
Definition: service_client.hpp:54
uavcan::dynamic_node_id_server::distributed::RaftCore::getRandomizedTimeout
MonotonicDuration getRandomizedTimeout() const
Definition: raft_core.hpp:910
uavcan::dynamic_node_id_server::distributed::ClusterManager::getServerMatchIndex
Log::Index getServerMatchIndex(NodeID server_node_id) const
Definition: cluster_manager.hpp:378
rand
int rand()
Definition: main.cpp:28
uavcan::TimerBase::startPeriodic
void startPeriodic(MonotonicDuration period)
Definition: uc_timer.cpp:42
uavcan::dynamic_node_id_server::distributed::RaftCore::AppendEntriesResponseCallback
MethodBinder< RaftCore *, void(RaftCore::*)(const ServiceCallResult< AppendEntries > &)> AppendEntriesResponseCallback
Definition: raft_core.hpp:80
uavcan::int32_t
std::int32_t int32_t
Definition: std.hpp:31
uavcan::dynamic_node_id_server::distributed::RaftCore::PendingAppendEntriesFields::prev_log_index
Log::Index prev_log_index
Definition: raft_core.hpp:91
uavcan::dynamic_node_id_server::distributed::RaftCore::last_activity_timestamp_
MonotonicTime last_activity_timestamp_
Definition: raft_core.hpp:115
uavcan::dynamic_node_id_server::distributed::RaftCore::getNode
const INode & getNode() const
Definition: raft_core.hpp:138
uavcan::ServiceServer
Definition: service_server.hpp:90
uavcan_kinetis::ErrLogic
static const uavcan::int16_t ErrLogic
Internal logic error.
Definition: platform_specific_components/kinetis/libuavcan/driver/include/uavcan_kinetis/can.hpp:22
cluster_manager.hpp
uavcan::dynamic_node_id_server::distributed::Log::removeEntriesWhereIndexGreaterOrEqual
int removeEntriesWhereIndexGreaterOrEqual(Index index)
Definition: log.hpp:242
uavcan::uint8_t
std::uint8_t uint8_t
Definition: std.hpp:24
uavcan::dynamic_node_id_server::distributed::RaftCore::ServerStateFollower
@ ServerStateFollower
Definition: raft_core.hpp:69
uavcan::dynamic_node_id_server::distributed::IRaftLeaderMonitor::~IRaftLeaderMonitor
virtual ~IRaftLeaderMonitor()
Definition: raft_core.hpp:47
uavcan::dynamic_node_id_server::distributed::PersistentState::setCurrentTerm
int setCurrentTerm(Term term)
Definition: persistent_state.hpp:171
uavcan::dynamic_node_id_server::IStorageBackend
Definition: storage_backend.hpp:22
uavcan::dynamic_node_id_server::distributed::RaftCore::isLeader
bool isLeader() const
Definition: raft_core.hpp:825
uavcan::max
const UAVCAN_EXPORT T & max(const T &a, const T &b)
Definition: templates.hpp:291
uavcan::dynamic_node_id_server::distributed::RaftCore::RequestVoteResponseCallback
MethodBinder< RaftCore *, void(RaftCore::*)(const ServiceCallResult< RequestVote > &)> RequestVoteResponseCallback
Definition: raft_core.hpp:87
uavcan::dynamic_node_id_server::distributed::RaftCore::handleRequestVoteRequest
void handleRequestVoteRequest(const ReceivedDataStructure< RequestVote::Request > &request, ServiceResponseDataStructure< RequestVote::Response > &response)
Definition: raft_core.hpp:572
uavcan::dynamic_node_id_server::distributed::ClusterManager::resetAllServerIndices
void resetAllServerIndices()
Definition: cluster_manager.hpp:405
uavcan::NodeID::isUnicast
bool isUnicast() const
Definition: transfer.hpp:136
uavcan::dynamic_node_id_server::distributed::PersistentState
Definition: persistent_state.hpp:25
uavcan::dynamic_node_id_server::distributed::RaftCore::trace
void trace(TraceCode event, int64_t argument)
Definition: raft_core.hpp:135
uavcan::dynamic_node_id_server::distributed::RaftCore::getNumAllocations
Log::Index getNumAllocations() const
Definition: raft_core.hpp:896
uavcan::dynamic_node_id_server::distributed::PersistentState::resetVotedFor
int resetVotedFor()
Definition: persistent_state.hpp:230
uavcan::min
const UAVCAN_EXPORT T & min(const T &a, const T &b)
Definition: templates.hpp:281
method_binder.hpp
uavcan::INode
Definition: abstract_node.hpp:19
uavcan::dynamic_node_id_server::distributed::ClusterManager::MaxClusterSize
@ MaxClusterSize
Definition: cluster_manager.hpp:33
uavcan::dynamic_node_id_server::distributed::RaftCore::MaxNumFollowers
@ MaxNumFollowers
Definition: raft_core.hpp:103
uavcan::dynamic_node_id_server::distributed::RaftCore::request_vote_srv_
ServiceServer< RequestVote, RequestVoteCallback > request_vote_srv_
Definition: raft_core.hpp:129
uavcan::ServiceClient
Definition: service_client.hpp:217
uavcan::TransferPriority
Definition: transfer.hpp:28
TraceRaftAppendEntriesCallFailure
TraceRaftAppendEntriesCallFailure
Definition: event.hpp:53
uavcan::dynamic_node_id_server::distributed::RaftCore::persistent_state_
PersistentState persistent_state_
Definition: raft_core.hpp:111
uavcan::dynamic_node_id_server::distributed::RaftCore::LogEntryInfo
Definition: raft_core.hpp:857
uavcan::dynamic_node_id_server::distributed::RaftCore::handleTimerEvent
virtual void handleTimerEvent(const TimerEvent &)
Definition: raft_core.hpp:673
uavcan::ServiceCallResult::getResponse
const ResponseFieldType & getResponse() const
Definition: service_client.hpp:88
TraceRaftVoteRequestInitiation
TraceRaftVoteRequestInitiation
Definition: event.hpp:47
uavcan::ServiceCallResult::isSuccessful
bool isSuccessful() const
Definition: service_client.hpp:79
uavcan::dynamic_node_id_server::distributed::RaftCore::next_server_index_
uint8_t next_server_index_
Next server to query AE from.
Definition: raft_core.hpp:119
uavcan::dynamic_node_id_server::distributed::IRaftLeaderMonitor
Definition: raft_core.hpp:32
TraceRaftElectionComplete
TraceRaftElectionComplete
Definition: event.hpp:54
build_config.hpp
uavcan::dynamic_node_id_server::distributed::RaftCore::getServerState
ServerState getServerState() const
Definition: raft_core.hpp:908
Entry
Definition: avl_tree.cpp:12
uavcan::dynamic_node_id_server::distributed::RaftCore::num_votes_received_in_this_campaign_
uint8_t num_votes_received_in_this_campaign_
Definition: raft_core.hpp:120
uavcan::dynamic_node_id_server::distributed::RaftCore::ServerStateCandidate
@ ServerStateCandidate
Definition: raft_core.hpp:70
uavcan::dynamic_node_id_server::IEventTracer::onEvent
virtual void onEvent(TraceCode event_code, int64_t event_argument)=0
uavcan::dynamic_node_id_server::distributed::RaftCore::PendingAppendEntriesFields
Definition: raft_core.hpp:89
TraceRaftCoreInited
TraceRaftCoreInited
Definition: event.hpp:38
uavcan::dynamic_node_id_server::distributed::RaftCore::init
int init(const uint8_t cluster_size, const TransferPriority priority)
Definition: raft_core.hpp:731
uavcan::dynamic_node_id_server::IEventTracer
Definition: event.hpp:90
uavcan::dynamic_node_id_server::distributed::IRaftLeaderMonitor::handleLocalLeadershipChange
virtual void handleLocalLeadershipChange(bool local_node_is_leader)=0
uavcan::dynamic_node_id_server::distributed::RaftCore::PendingAppendEntriesFields::PendingAppendEntriesFields
PendingAppendEntriesFields()
Definition: raft_core.hpp:94
uavcan::dynamic_node_id_server::distributed::RaftCore::ServerStateLeader
@ ServerStateLeader
Definition: raft_core.hpp:71
uavcan::MethodBinder
Definition: method_binder.hpp:20
uavcan::dynamic_node_id_server::distributed::Log::removeEntriesWhereIndexGreater
int removeEntriesWhereIndexGreater(Index index)
Definition: log.hpp:276
TraceRaftAppendEntriesRespUnsucfl
TraceRaftAppendEntriesRespUnsucfl
Definition: event.hpp:55
uavcan::dynamic_node_id_server::distributed::RaftCore::updateLeader
void updateLeader()
Definition: raft_core.hpp:260
uavcan::dynamic_node_id_server::distributed::RaftCore::getPersistentState
const PersistentState & getPersistentState() const
Definition: raft_core.hpp:905
uavcan::dynamic_node_id_server::distributed::RaftCore::getLastActivityTimestamp
MonotonicTime getLastActivityTimestamp() const
Definition: raft_core.hpp:907
uavcan::dynamic_node_id_server::distributed::RaftCore::PendingAppendEntriesFields::num_entries
Log::Index num_entries
Definition: raft_core.hpp:92
uavcan::dynamic_node_id_server::distributed::RaftCore::handlePersistentStateUpdateError
void handlePersistentStateUpdateError(int error)
Definition: raft_core.hpp:186
uavcan::dynamic_node_id_server::distributed::RaftCore::randomized_activity_timeout_
MonotonicDuration randomized_activity_timeout_
Definition: raft_core.hpp:116
TraceRaftNewLogEntry
TraceRaftNewLogEntry
Definition: event.hpp:42
uavcan::dynamic_node_id_server::distributed::RaftCore::cluster_
ClusterManager cluster_
Definition: raft_core.hpp:112
uavcan::dynamic_node_id_server::distributed::RaftCore::switchState
void switchState(ServerState new_state)
Definition: raft_core.hpp:318
uavcan::dynamic_node_id_server::distributed::RaftCore::handleAppendEntriesRequest
void handleAppendEntriesRequest(const ReceivedDataStructure< AppendEntries::Request > &request, ServiceResponseDataStructure< AppendEntries::Response > &response)
Definition: raft_core.hpp:406
uavcan::dynamic_node_id_server::distributed::ClusterManager::init
int init(const uint8_t init_cluster_size, const TransferPriority priority)
Definition: cluster_manager.hpp:210
uavcan::dynamic_node_id_server::distributed::RaftCore::LogEntryInfo::committed
bool committed
Definition: raft_core.hpp:860
uavcan::dynamic_node_id_server::distributed::ClusterManager::setServerMatchIndex
void setServerMatchIndex(NodeID server_node_id, Log::Index match_index)
Definition: cluster_manager.hpp:389
uavcan::ServiceResponseDataStructure
Definition: service_server.hpp:40
TraceRaftVoteRequestReceived
TraceRaftVoteRequestReceived
Definition: event.hpp:44
uavcan::dynamic_node_id_server::distributed::RaftCore::getClusterManager
const ClusterManager & getClusterManager() const
Definition: raft_core.hpp:906
uavcan::dynamic_node_id_server::distributed::RaftCore::traverseLogFromEndUntil
LazyConstructor< LogEntryInfo > traverseLogFromEndUntil(const Predicate &predicate) const
Definition: raft_core.hpp:878
uavcan::dynamic_node_id_server::distributed::ClusterManager::getQuorumSize
uint8_t getQuorumSize() const
Definition: cluster_manager.hpp:424
uavcan::dynamic_node_id_server::distributed::ClusterManager::getNumKnownServers
uint8_t getNumKnownServers() const
Definition: cluster_manager.hpp:418
pyuavcan_v0.introspect.node
node
Definition: introspect.py:398
uavcan::MonotonicTime
Definition: time.hpp:184
uavcan::dynamic_node_id_server::distributed::RaftCore::getCommitIndex
Log::Index getCommitIndex() const
Definition: raft_core.hpp:815
uavcan::dynamic_node_id_server::distributed::RaftCore::LogEntryInfo::LogEntryInfo
LogEntryInfo(const Entry &arg_entry, bool arg_committed)
Definition: raft_core.hpp:862
TraceRaftStateSwitch
TraceRaftStateSwitch
Definition: event.hpp:39
uavcan
Definition: libuavcan/libuavcan/include/uavcan/build_config.hpp:204
uavcan::ReceivedDataStructure::getSrcNodeID
NodeID getSrcNodeID() const
Definition: generic_subscriber.hpp:75
uavcan::dynamic_node_id_server::distributed::PersistentState::getCurrentTerm
Term getCurrentTerm() const
Definition: persistent_state.hpp:160
uavcan::dynamic_node_id_server::distributed::RaftCore::append_entries_srv_
ServiceServer< AppendEntries, AppendEntriesCallback > append_entries_srv_
Definition: raft_core.hpp:127
uavcan::dynamic_node_id_server::distributed::ClusterManager::addServer
void addServer(NodeID node_id)
Definition: cluster_manager.hpp:285
uavcan::dynamic_node_id_server::distributed::RaftCore::handleAppendEntriesResponse
void handleAppendEntriesResponse(const ServiceCallResult< AppendEntries > &result)
Definition: raft_core.hpp:537
uavcan::dynamic_node_id_server::distributed::PersistentState::getVotedFor
NodeID getVotedFor() const
Definition: persistent_state.hpp:162
pyuavcan_v0.introspect.info
info
Definition: introspect.py:333
uavcan::dynamic_node_id_server::distributed::RaftCore::pending_append_entries_fields_
PendingAppendEntriesFields pending_append_entries_fields_
Definition: raft_core.hpp:122
service_server.hpp
uavcan::dynamic_node_id_server::distributed::RaftCore::LogEntryInfo::entry
Entry entry
Definition: raft_core.hpp:859
uavcan::dynamic_node_id_server::distributed::RaftCore::AppendEntriesCallback
MethodBinder< RaftCore *, void(RaftCore::*)(const ReceivedDataStructure< AppendEntries::Request > &, ServiceResponseDataStructure< AppendEntries::Response > &)> AppendEntriesCallback
Definition: raft_core.hpp:77
uavcan::LazyConstructor
Definition: lazy_constructor.hpp:27
uavcan::DurationBase::toUSec
int64_t toUSec() const
Definition: time.hpp:43
uavcan::dynamic_node_id_server::distributed::RaftCore::getNode
INode & getNode()
Definition: raft_core.hpp:137
UAVCAN_ASSERT
#define UAVCAN_ASSERT(x)
Definition: libuavcan/libuavcan/include/uavcan/build_config.hpp:184
uavcan::TimerEvent
Definition: timer.hpp:32
uavcan::dynamic_node_id_server::distributed::RaftCore::updateCandidate
void updateCandidate()
Definition: raft_core.hpp:203
TraceRaftCommitIndexUpdate
TraceRaftCommitIndexUpdate
Definition: event.hpp:49
uavcan::dynamic_node_id_server::distributed::ClusterManager
Definition: cluster_manager.hpp:30
uavcan::dynamic_node_id_server::distributed::RaftCore::append_entries_client_
ServiceClient< AppendEntries, AppendEntriesResponseCallback > append_entries_client_
Definition: raft_core.hpp:128
uavcan::dynamic_node_id_server::distributed::Log::getLastIndex
Index getLastIndex() const
Definition: log.hpp:291


uavcan_communicator
Author(s):
autogenerated on Fri Dec 13 2024 03:10:03