persistent_state.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_PERSISTENT_STATE_HPP_INCLUDED
6 #define UAVCAN_PROTOCOL_DYNAMIC_NODE_ID_SERVER_DISTRIBUTED_PERSISTENT_STATE_HPP_INCLUDED
7 
9 #include <uavcan/debug.hpp>
14 
15 namespace uavcan
16 {
17 namespace dynamic_node_id_server
18 {
19 namespace distributed
20 {
26 {
29 
33 
34  static IStorageBackend::String getCurrentTermKey() { return "current_term"; }
35  static IStorageBackend::String getVotedForKey() { return "voted_for"; }
36 
37 public:
39  : storage_(storage)
40  , tracer_(tracer)
41  , current_term_(0)
42  , log_(storage, tracer)
43  { }
44 
53  int init()
54  {
55  /*
56  * Reading log
57  */
58  int res = log_.init();
59  if (res < 0)
60  {
61  UAVCAN_TRACE("dynamic_node_id_server::distributed::PersistentState", "Log init failed: %d", res);
62  return res;
63  }
64 
65  const Entry* const last_entry = log_.getEntryAtIndex(log_.getLastIndex());
66  if (last_entry == UAVCAN_NULLPTR)
67  {
68  UAVCAN_ASSERT(0);
69  return -ErrLogic;
70  }
71 
72  const bool log_is_empty = (log_.getLastIndex() == 0) && (last_entry->term == 0);
73 
75 
76  /*
77  * Reading currentTerm
78  */
79  if (storage_.get(getCurrentTermKey()).empty() && log_is_empty)
80  {
81  // First initialization
82  current_term_ = 0;
84  if (res < 0)
85  {
86  UAVCAN_TRACE("dynamic_node_id_server::distributed::PersistentState",
87  "Failed to init current term: %d", res);
88  return res;
89  }
90  if (current_term_ != 0)
91  {
92  return -ErrFailure;
93  }
94  }
95  else
96  {
97  // Restoring
98  res = io.get(getCurrentTermKey(), current_term_);
99  if (res < 0)
100  {
101  UAVCAN_TRACE("dynamic_node_id_server::distributed::PersistentState",
102  "Failed to read current term: %d", res);
103  return res;
104  }
105  }
106 
108 
109  if (current_term_ < last_entry->term)
110  {
111  UAVCAN_TRACE("dynamic_node_id_server::distributed::PersistentState",
112  "Persistent storage is damaged: current term is less than term of the last log entry (%u < %u)",
113  unsigned(current_term_), unsigned(last_entry->term));
114  return -ErrLogic;
115  }
116 
117  /*
118  * Reading votedFor
119  */
120  if (storage_.get(getVotedForKey()).empty() && log_is_empty && (current_term_ == 0))
121  {
122  // First initialization
123  voted_for_ = NodeID(0);
124  uint32_t stored_voted_for = 0;
125  res = io.setAndGetBack(getVotedForKey(), stored_voted_for);
126  if (res < 0)
127  {
128  UAVCAN_TRACE("dynamic_node_id_server::distributed::PersistentState",
129  "Failed to init votedFor: %d", res);
130  return res;
131  }
132  if (stored_voted_for != 0)
133  {
134  return -ErrFailure;
135  }
136  }
137  else
138  {
139  // Restoring
140  uint32_t stored_voted_for = 0;
141  res = io.get(getVotedForKey(), stored_voted_for);
142  if (res < 0)
143  {
144  UAVCAN_TRACE("dynamic_node_id_server::distributed::PersistentState",
145  "Failed to read votedFor: %d", res);
146  return res;
147  }
148  if (stored_voted_for > NodeID::Max)
149  {
150  return -ErrInvalidConfiguration;
151  }
152  voted_for_ = NodeID(uint8_t(stored_voted_for));
153  }
154 
156 
157  return 0;
158  }
159 
160  Term getCurrentTerm() const { return current_term_; }
161 
162  NodeID getVotedFor() const { return voted_for_; }
163  bool isVotedForSet() const { return voted_for_.isUnicast(); }
164 
165  Log& getLog() { return log_; }
166  const Log& getLog() const { return log_; }
167 
172  {
173  if (term < current_term_)
174  {
175  UAVCAN_ASSERT(0);
176  return -ErrInvalidParam;
177  }
178 
180 
182 
183  Term tmp = term;
184  int res = io.setAndGetBack(getCurrentTermKey(), tmp);
185  if (res < 0)
186  {
187  return res;
188  }
189 
190  if (tmp != term)
191  {
192  return -ErrFailure;
193  }
194 
195  current_term_ = term;
196  return 0;
197  }
198 
202  int setVotedFor(NodeID node_id)
203  {
204  if (!node_id.isValid())
205  {
206  UAVCAN_ASSERT(0);
207  return -ErrInvalidParam;
208  }
209 
211 
213 
214  uint32_t tmp = node_id.get();
215  int res = io.setAndGetBack(getVotedForKey(), tmp);
216  if (res < 0)
217  {
218  return res;
219  }
220 
221  if (node_id.get() != tmp)
222  {
223  return -ErrFailure;
224  }
225 
226  voted_for_ = node_id;
227  return 0;
228  }
229 
230  int resetVotedFor() { return setVotedFor(NodeID(0)); }
231 };
232 
233 }
234 }
235 }
236 
237 #endif // Include guard
TraceRaftVotedForRestored
TraceRaftVotedForRestored
Definition: event.hpp:30
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::NodeID::isValid
bool isValid() const
Definition: transfer.hpp:134
uavcan::dynamic_node_id_server::distributed::Log::init
int init()
Definition: log.hpp:152
uavcan::dynamic_node_id_server::distributed::PersistentState::getLog
const Log & getLog() const
Definition: persistent_state.hpp:166
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::uint32_t
std::uint32_t uint32_t
Definition: std.hpp:26
uavcan::dynamic_node_id_server::distributed::PersistentState::voted_for_
NodeID voted_for_
Definition: persistent_state.hpp:31
uavcan::dynamic_node_id_server::distributed::PersistentState::isVotedForSet
bool isVotedForSet() const
Definition: persistent_state.hpp:163
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::StorageMarshaller
Definition: storage_marshaller.hpp:25
uavcan::dynamic_node_id_server::distributed::PersistentState::storage_
IStorageBackend & storage_
Definition: persistent_state.hpp:27
event.hpp
uavcan::dynamic_node_id_server::distributed::PersistentState::setVotedFor
int setVotedFor(NodeID node_id)
Definition: persistent_state.hpp:202
uavcan::dynamic_node_id_server::StorageMarshaller::setAndGetBack
int setAndGetBack(const IStorageBackend::String &key, uint32_t &inout_value)
Definition: storage_marshaller.hpp:62
uavcan::dynamic_node_id_server::StorageMarshaller::get
int get(const IStorageBackend::String &key, uint32_t &out_value) const
Definition: storage_marshaller.hpp:90
UAVCAN_TRACE
#define UAVCAN_TRACE(...)
Definition: libuavcan/libuavcan/include/uavcan/debug.hpp:31
uavcan::dynamic_node_id_server::distributed::PersistentState::init
int init()
Definition: persistent_state.hpp:53
types.hpp
uavcan::dynamic_node_id_server::distributed::PersistentState::tracer_
IEventTracer & tracer_
Definition: persistent_state.hpp:28
uavcan::Array
Definition: array.hpp:424
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
uavcan::uint8_t
std::uint8_t uint8_t
Definition: std.hpp:24
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
TraceRaftVotedForUpdate
TraceRaftVotedForUpdate
Definition: event.hpp:31
TraceRaftCurrentTermUpdate
TraceRaftCurrentTermUpdate
Definition: event.hpp:29
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::PersistentState::resetVotedFor
int resetVotedFor()
Definition: persistent_state.hpp:230
build_config.hpp
uavcan::dynamic_node_id_server::distributed::PersistentState::log_
Log log_
Definition: persistent_state.hpp:32
Entry
Definition: avl_tree.cpp:12
uavcan::dynamic_node_id_server::distributed::PersistentState::current_term_
Term current_term_
Definition: persistent_state.hpp:30
uavcan::dynamic_node_id_server::IEventTracer::onEvent
virtual void onEvent(TraceCode event_code, int64_t event_argument)=0
uavcan::dynamic_node_id_server::IEventTracer
Definition: event.hpp:90
log.hpp
uavcan::NodeID::Max
static const uint8_t Max
Definition: transfer.hpp:120
uavcan::dynamic_node_id_server::distributed::Log
Definition: log.hpp:25
uavcan
Definition: libuavcan/libuavcan/include/uavcan/build_config.hpp:204
uavcan::dynamic_node_id_server::distributed::PersistentState::getCurrentTerm
Term getCurrentTerm() const
Definition: persistent_state.hpp:160
uavcan::dynamic_node_id_server::IStorageBackend::get
virtual String get(const String &key) const =0
TraceRaftCurrentTermRestored
TraceRaftCurrentTermRestored
Definition: event.hpp:27
uavcan::dynamic_node_id_server::distributed::PersistentState::getVotedFor
NodeID getVotedFor() const
Definition: persistent_state.hpp:162
uavcan::dynamic_node_id_server::distributed::PersistentState::getCurrentTermKey
static IStorageBackend::String getCurrentTermKey()
Definition: persistent_state.hpp:34
storage_marshaller.hpp
uavcan::dynamic_node_id_server::distributed::PersistentState::PersistentState
PersistentState(IStorageBackend &storage, IEventTracer &tracer)
Definition: persistent_state.hpp:38
UAVCAN_ASSERT
#define UAVCAN_ASSERT(x)
Definition: libuavcan/libuavcan/include/uavcan/build_config.hpp:184
uavcan::dynamic_node_id_server::distributed::PersistentState::getVotedForKey
static IStorageBackend::String getVotedForKey()
Definition: persistent_state.hpp:35
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:02