mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-05-23 14:37:34 +08:00
Raft event tracing interface, more states of RaftCore, basic functions of RaftCore
This commit is contained in:
@@ -70,6 +70,25 @@ public:
|
||||
virtual ~IDynamicNodeIDStorageBackend() { }
|
||||
};
|
||||
|
||||
/**
|
||||
* This interface allows the application to trace events that happen in the server.
|
||||
*/
|
||||
class IDynamicNodeIDAllocationServerEventTracer
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* The server invokes this method every time it believes that a noteworthy event has happened.
|
||||
* The table of event codes can be found in the server sources.
|
||||
* It is guaranteed that event code values will never change, but new ones can be added in future. This ensures
|
||||
* full backward compatibility.
|
||||
* @param event_code Event code, see the sources for the enum with values.
|
||||
* @param event_argument Value associated with the event; its meaning depends on the event code.
|
||||
*/
|
||||
virtual void onEvent(uint16_t event_code, int64_t event_argument) = 0;
|
||||
|
||||
virtual ~IDynamicNodeIDAllocationServerEventTracer() { }
|
||||
};
|
||||
|
||||
/**
|
||||
* Internals, do not use anything from this namespace directly.
|
||||
*/
|
||||
@@ -83,6 +102,37 @@ using namespace protocol::dynamic_node_id::server;
|
||||
*/
|
||||
typedef StorageType<Entry::FieldTypes::term>::Type Term;
|
||||
|
||||
/**
|
||||
* @ref IDynamicNodeIDAllocationServerEventTracer.
|
||||
* Event codes cannot be changed, only new ones can be added.
|
||||
*/
|
||||
enum TraceEvent
|
||||
{
|
||||
// Event name Argument
|
||||
// 0
|
||||
TraceError, // error code (may be negated)
|
||||
TraceLogLastIndexRestored, // recovered last index value
|
||||
TraceLogAppend, // index of new entry
|
||||
TraceLogRemove, // new last index value
|
||||
TraceCurrentTermRestored, // current term
|
||||
// 5
|
||||
TraceCurrentTermUpdate, // current term
|
||||
TraceVotedForRestored, // value of votedFor
|
||||
TraceVotedForUpdate, // value of votedFor
|
||||
TraceDiscoveryBroadcast, // number of known servers
|
||||
TraceNewServerDiscovered, // node ID of the new server
|
||||
// 10
|
||||
TraceDiscoveryReceived, // node ID of the sender
|
||||
TraceClusterSizeInited, // cluster size
|
||||
TraceRaftCoreInited, // update interval in usec
|
||||
TraceRaftStateSwitch, // 0 - Follower, 1 - Candidate, 2 - Leader
|
||||
TraceRaftModeSwitch, // 0 - Passive, 1 - Active
|
||||
// 15
|
||||
TraceRaftNewLogEntry, // node ID value
|
||||
|
||||
NumTraceEventCodes
|
||||
};
|
||||
|
||||
/**
|
||||
* This class extends the storage backend interface with serialization/deserialization functionality.
|
||||
*/
|
||||
@@ -137,6 +187,7 @@ public:
|
||||
|
||||
private:
|
||||
IDynamicNodeIDStorageBackend& storage_;
|
||||
IDynamicNodeIDAllocationServerEventTracer& tracer_;
|
||||
Entry entries_[Capacity];
|
||||
Index last_index_; // Index zero always contains an empty entry
|
||||
|
||||
@@ -149,8 +200,9 @@ private:
|
||||
int initEmptyLogStorage();
|
||||
|
||||
public:
|
||||
Log(IDynamicNodeIDStorageBackend& storage)
|
||||
Log(IDynamicNodeIDStorageBackend& storage, IDynamicNodeIDAllocationServerEventTracer& tracer)
|
||||
: storage_(storage)
|
||||
, tracer_(tracer)
|
||||
, last_index_(0)
|
||||
{ }
|
||||
|
||||
@@ -195,6 +247,7 @@ public:
|
||||
class PersistentState
|
||||
{
|
||||
IDynamicNodeIDStorageBackend& storage_;
|
||||
IDynamicNodeIDAllocationServerEventTracer& tracer_;
|
||||
|
||||
Term current_term_;
|
||||
NodeID voted_for_;
|
||||
@@ -204,10 +257,11 @@ class PersistentState
|
||||
static IDynamicNodeIDStorageBackend::String getVotedForKey() { return "voted_for"; }
|
||||
|
||||
public:
|
||||
PersistentState(IDynamicNodeIDStorageBackend& storage)
|
||||
PersistentState(IDynamicNodeIDStorageBackend& storage, IDynamicNodeIDAllocationServerEventTracer& tracer)
|
||||
: storage_(storage)
|
||||
, tracer_(tracer)
|
||||
, current_term_(0)
|
||||
, log_(storage)
|
||||
, log_(storage, tracer)
|
||||
{ }
|
||||
|
||||
int init();
|
||||
@@ -257,6 +311,7 @@ class ClusterManager : private TimerBase
|
||||
enum { MaxServers = Discovery::FieldTypes::known_nodes::MaxSize };
|
||||
|
||||
IDynamicNodeIDStorageBackend& storage_;
|
||||
IDynamicNodeIDAllocationServerEventTracer& tracer_;
|
||||
const Log& log_;
|
||||
|
||||
Subscriber<Discovery, DiscoveryCallback> discovery_sub_;
|
||||
@@ -293,9 +348,11 @@ public:
|
||||
* @param storage Needed to read the cluster size parameter from the storage
|
||||
* @param log Needed to initialize nextIndex[] values after elections
|
||||
*/
|
||||
ClusterManager(INode& node, IDynamicNodeIDStorageBackend& storage, const Log& log)
|
||||
ClusterManager(INode& node, IDynamicNodeIDStorageBackend& storage, const Log& log,
|
||||
IDynamicNodeIDAllocationServerEventTracer& tracer)
|
||||
: TimerBase(node)
|
||||
, storage_(storage)
|
||||
, tracer_(tracer)
|
||||
, log_(log)
|
||||
, discovery_sub_(node)
|
||||
, discovery_pub_(node)
|
||||
@@ -348,7 +405,15 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Number of known servers can only grow, and it never exceeds the cluster size value.
|
||||
* This number does not include the local server.
|
||||
*/
|
||||
uint8_t getNumKnownServers() const { return num_known_servers_; }
|
||||
|
||||
/**
|
||||
* Cluster size and quorum size are constant.
|
||||
*/
|
||||
uint8_t getClusterSize() const { return cluster_size_; }
|
||||
uint8_t getQuorumSize() const { return static_cast<uint8_t>(cluster_size_ / 2U + 1U); }
|
||||
|
||||
@@ -366,13 +431,13 @@ class RaftCore : private TimerBase
|
||||
ServiceResponseDataStructure<AppendEntries::Response>&)>
|
||||
AppendEntriesCallback;
|
||||
|
||||
typedef MethodBinder<RaftCore*, void (RaftCore::*)(const ServiceCallResult<AppendEntries>&)>
|
||||
AppendEntriesResponseCallback;
|
||||
|
||||
typedef MethodBinder<RaftCore*, void (RaftCore::*)(const ReceivedDataStructure<RequestVote::Request>&,
|
||||
ServiceResponseDataStructure<RequestVote::Response>&)>
|
||||
RequestVoteCallback;
|
||||
|
||||
typedef MethodBinder<RaftCore*, void (RaftCore::*)(const ServiceCallResult<AppendEntries>&)>
|
||||
AppendEntriesResponseCallback;
|
||||
|
||||
typedef MethodBinder<RaftCore*, void (RaftCore::*)(const ServiceCallResult<RequestVote>&)>
|
||||
RequestVoteResponseCallback;
|
||||
|
||||
@@ -383,48 +448,95 @@ class RaftCore : private TimerBase
|
||||
ServerStateLeader
|
||||
};
|
||||
|
||||
IDynamicNodeIDAllocationServerEventTracer& tracer_;
|
||||
|
||||
/*
|
||||
* States
|
||||
*/
|
||||
PersistentState persistent_state_;
|
||||
Log::Index commit_index_;
|
||||
ClusterManager cluster_;
|
||||
Log::Index commit_index_;
|
||||
|
||||
MonotonicTime last_activity_timestamp_;
|
||||
bool active_mode_;
|
||||
|
||||
ServerState server_state_;
|
||||
|
||||
ServiceServer<AppendEntries, AppendEntriesCallback> append_entries_srv_;
|
||||
ServiceServer<RequestVote, RequestVoteCallback> request_vote_srv_;
|
||||
uint8_t next_server_index_; ///< Next server to query for AE or RV RPC
|
||||
uint8_t num_votes_received_in_this_campaign_;
|
||||
|
||||
/*
|
||||
* Transport
|
||||
*/
|
||||
ServiceServer<AppendEntries, AppendEntriesCallback> append_entries_srv_;
|
||||
ServiceClient<AppendEntries, AppendEntriesResponseCallback> append_entries_client_;
|
||||
ServiceServer<RequestVote, RequestVoteCallback> request_vote_srv_;
|
||||
ServiceClient<RequestVote, RequestVoteResponseCallback> request_vote_client_;
|
||||
|
||||
virtual void handleTimerEvent(const TimerEvent&);
|
||||
/**
|
||||
* This constant defines the rate at which internal state updates happen.
|
||||
* It also defines timeouts for AppendEntries and RequestVote RPCs.
|
||||
*/
|
||||
static MonotonicDuration getUpdateInterval() { return MonotonicDuration::fromMSec(50); }
|
||||
|
||||
void trace(TraceEvent event, int64_t argument) { tracer_.onEvent(event, argument); }
|
||||
|
||||
INode& getNode() { return append_entries_srv_.getNode(); }
|
||||
|
||||
void updateFollower(const MonotonicTime& current_time);
|
||||
void updateCandidate(const MonotonicTime& current_time);
|
||||
void updateLeader(const MonotonicTime& current_time);
|
||||
|
||||
void switchState(ServerState new_state);
|
||||
|
||||
void handleAppendEntriesRequest(const ReceivedDataStructure<AppendEntries::Request>& request,
|
||||
ServiceResponseDataStructure<AppendEntries::Response>& response);
|
||||
|
||||
void handleAppendEntriesResponse(const ServiceCallResult<AppendEntries>& result);
|
||||
|
||||
void handleRequestVoteRequest(const ReceivedDataStructure<RequestVote::Request>& request,
|
||||
ServiceResponseDataStructure<RequestVote::Response>& response);
|
||||
|
||||
void handleRequestVoteResponse(const ServiceCallResult<RequestVote>& result);
|
||||
|
||||
virtual void handleTimerEvent(const TimerEvent& event);
|
||||
|
||||
public:
|
||||
RaftCore(INode& node, IDynamicNodeIDStorageBackend& storage)
|
||||
RaftCore(INode& node, IDynamicNodeIDStorageBackend& storage, IDynamicNodeIDAllocationServerEventTracer& tracer)
|
||||
: TimerBase(node)
|
||||
, persistent_state_(storage)
|
||||
, commit_index_(0) // Per Raft paper, commitIndex must be initialized to zero
|
||||
, cluster_(node, storage, persistent_state_.getLog())
|
||||
, tracer_(tracer)
|
||||
, persistent_state_(storage, tracer)
|
||||
, cluster_(node, storage, persistent_state_.getLog(), tracer)
|
||||
, commit_index_(0) // Per Raft paper, commitIndex must be initialized to zero
|
||||
, last_activity_timestamp_(node.getMonotonicTime())
|
||||
, active_mode_(true)
|
||||
, server_state_(ServerStateFollower)
|
||||
, next_server_index_(0)
|
||||
, num_votes_received_in_this_campaign_(0)
|
||||
, append_entries_srv_(node)
|
||||
, request_vote_srv_(node)
|
||||
, append_entries_client_(node)
|
||||
, request_vote_srv_(node)
|
||||
, request_vote_client_(node)
|
||||
{ }
|
||||
|
||||
/**
|
||||
* Once started, the logic runs in the background until destructor is called.
|
||||
* @param cluster_size If set, this value will be used and stored in the persistent storage. If not set,
|
||||
* value from the persistent storage will be used. If not set and there's no such key
|
||||
* in the persistent storage, initialization will fail.
|
||||
*/
|
||||
int init();
|
||||
int init(uint8_t cluster_size = ClusterManager::ClusterSizeUnknown);
|
||||
|
||||
/**
|
||||
* Inserts one entry into log. This operation may fail, which will not be reported.
|
||||
* Failures are tolerble because all operations are idempotent.
|
||||
* Only the leader can call @ref appendLog().
|
||||
*/
|
||||
void appendLog(const Entry& entry);
|
||||
bool isLeader() const { return server_state_ == ServerStateLeader; }
|
||||
|
||||
/**
|
||||
* Inserts one entry into log.
|
||||
* Failures are tolerble because all operations are idempotent.
|
||||
* This method will trigger an assertion failure and return error if the current node is not the leader.
|
||||
*/
|
||||
int appendLog(const Entry& entry);
|
||||
|
||||
/**
|
||||
* This class is used to perform log searches.
|
||||
|
||||
@@ -286,6 +286,8 @@ int Log::init()
|
||||
last_index_ = Index(value);
|
||||
}
|
||||
|
||||
tracer_.onEvent(TraceLogLastIndexRestored, last_index_);
|
||||
|
||||
// Restoring log entries - note that index 0 always exists
|
||||
for (Index index = 0; index <= last_index_; index++)
|
||||
{
|
||||
@@ -309,6 +311,8 @@ int Log::append(const Entry& entry)
|
||||
return -ErrLogic;
|
||||
}
|
||||
|
||||
tracer_.onEvent(TraceLogAppend, last_index_ + 1U);
|
||||
|
||||
// If next operations fail, we'll get a dangling entry, but it's absolutely OK.
|
||||
int res = writeEntryToStorage(Index(last_index_ + 1), entry);
|
||||
if (res < 0)
|
||||
@@ -345,6 +349,8 @@ int Log::removeEntriesWhereIndexGreaterOrEqual(Index index)
|
||||
return -ErrLogic;
|
||||
}
|
||||
|
||||
tracer_.onEvent(TraceLogRemove, index - 1U);
|
||||
|
||||
MarshallingStorageDecorator io(storage_);
|
||||
uint32_t new_last_index = index - 1U;
|
||||
int res = io.setAndGetBack(getLastIndexKey(), new_last_index);
|
||||
@@ -437,6 +443,8 @@ int PersistentState::init()
|
||||
}
|
||||
}
|
||||
|
||||
tracer_.onEvent(TraceCurrentTermRestored, current_term_);
|
||||
|
||||
if (current_term_ < last_entry->term)
|
||||
{
|
||||
UAVCAN_TRACE("dynamic_node_id_server_impl::PersistentState",
|
||||
@@ -481,6 +489,8 @@ int PersistentState::init()
|
||||
voted_for_ = NodeID(uint8_t(stored_voted_for));
|
||||
}
|
||||
|
||||
tracer_.onEvent(TraceVotedForRestored, voted_for_.get());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -492,6 +502,8 @@ int PersistentState::setCurrentTerm(const Term term)
|
||||
return -ErrInvalidParam;
|
||||
}
|
||||
|
||||
tracer_.onEvent(TraceCurrentTermUpdate, term);
|
||||
|
||||
MarshallingStorageDecorator io(storage_);
|
||||
|
||||
Term tmp = term;
|
||||
@@ -518,6 +530,8 @@ int PersistentState::setVotedFor(const NodeID node_id)
|
||||
return -ErrInvalidParam;
|
||||
}
|
||||
|
||||
tracer_.onEvent(TraceVotedForUpdate, node_id.get());
|
||||
|
||||
MarshallingStorageDecorator io(storage_);
|
||||
|
||||
uint32_t tmp = node_id.get();
|
||||
@@ -586,6 +600,7 @@ void ClusterManager::addServer(NodeID node_id)
|
||||
UAVCAN_ASSERT((num_known_servers_ + 1) < (MaxServers - 2));
|
||||
if (!isKnownServer(node_id) && node_id.isUnicast())
|
||||
{
|
||||
tracer_.onEvent(TraceNewServerDiscovered, node_id.get());
|
||||
servers_[num_known_servers_].node_id = node_id;
|
||||
servers_[num_known_servers_].resetIndices(log_);
|
||||
num_known_servers_ = static_cast<uint8_t>(num_known_servers_ + 1U);
|
||||
@@ -600,6 +615,8 @@ void ClusterManager::handleTimerEvent(const TimerEvent&)
|
||||
{
|
||||
UAVCAN_ASSERT(num_known_servers_ < cluster_size_);
|
||||
|
||||
tracer_.onEvent(TraceDiscoveryBroadcast, num_known_servers_);
|
||||
|
||||
/*
|
||||
* Filling the message
|
||||
*/
|
||||
@@ -641,6 +658,8 @@ void ClusterManager::handleTimerEvent(const TimerEvent&)
|
||||
|
||||
void ClusterManager::handleDiscovery(const ReceivedDataStructure<Discovery>& msg)
|
||||
{
|
||||
tracer_.onEvent(TraceDiscoveryReceived, msg.getSrcNodeID().get());
|
||||
|
||||
/*
|
||||
* Validating cluster configuration
|
||||
* If there's a case of misconfiguration, the message will be ignored.
|
||||
@@ -730,6 +749,8 @@ int ClusterManager::init(const uint8_t init_cluster_size)
|
||||
}
|
||||
}
|
||||
|
||||
tracer_.onEvent(TraceClusterSizeInited, cluster_size_);
|
||||
|
||||
UAVCAN_ASSERT(cluster_size_ > 0);
|
||||
UAVCAN_ASSERT(cluster_size_ <= MaxServers);
|
||||
|
||||
@@ -836,6 +857,158 @@ void ClusterManager::resetAllServerIndices()
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* RaftCore
|
||||
*/
|
||||
void RaftCore::updateFollower(const MonotonicTime& current_time)
|
||||
{
|
||||
(void)current_time;
|
||||
}
|
||||
|
||||
void RaftCore::updateCandidate(const MonotonicTime& current_time)
|
||||
{
|
||||
(void)current_time;
|
||||
}
|
||||
|
||||
void RaftCore::updateLeader(const MonotonicTime& current_time)
|
||||
{
|
||||
(void)current_time;
|
||||
}
|
||||
|
||||
void RaftCore::switchState(ServerState new_state)
|
||||
{
|
||||
if (server_state_ != new_state)
|
||||
{
|
||||
trace(TraceRaftStateSwitch, new_state);
|
||||
}
|
||||
}
|
||||
|
||||
void RaftCore::handleAppendEntriesRequest(const ReceivedDataStructure<AppendEntries::Request>& request,
|
||||
ServiceResponseDataStructure<AppendEntries::Response>& response)
|
||||
{
|
||||
(void)request;
|
||||
(void)response;
|
||||
}
|
||||
|
||||
void RaftCore::handleAppendEntriesResponse(const ServiceCallResult<AppendEntries>& result)
|
||||
{
|
||||
(void)result;
|
||||
}
|
||||
|
||||
void RaftCore::handleRequestVoteRequest(const ReceivedDataStructure<RequestVote::Request>& request,
|
||||
ServiceResponseDataStructure<RequestVote::Response>& response)
|
||||
{
|
||||
(void)request;
|
||||
(void)response;
|
||||
}
|
||||
|
||||
void RaftCore::handleRequestVoteResponse(const ServiceCallResult<RequestVote>& result)
|
||||
{
|
||||
(void)result;
|
||||
}
|
||||
|
||||
void RaftCore::handleTimerEvent(const TimerEvent& event)
|
||||
{
|
||||
switch (server_state_)
|
||||
{
|
||||
case ServerStateFollower:
|
||||
{
|
||||
updateFollower(event.real_time);
|
||||
break;
|
||||
}
|
||||
case ServerStateCandidate:
|
||||
{
|
||||
updateCandidate(event.real_time);
|
||||
break;
|
||||
}
|
||||
case ServerStateLeader:
|
||||
{
|
||||
updateLeader(event.real_time);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
UAVCAN_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int RaftCore::init(uint8_t cluster_size)
|
||||
{
|
||||
/*
|
||||
* Initializing state variables
|
||||
*/
|
||||
last_activity_timestamp_ = getNode().getMonotonicTime();
|
||||
active_mode_ = true;
|
||||
server_state_ = ServerStateFollower;
|
||||
next_server_index_ = 0;
|
||||
num_votes_received_in_this_campaign_ = 0;
|
||||
commit_index_ = 0;
|
||||
|
||||
/*
|
||||
* Initializing internals
|
||||
*/
|
||||
int res = persistent_state_.init();
|
||||
if (res < 0)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
|
||||
res = cluster_.init(cluster_size);
|
||||
if (res < 0)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
|
||||
res = append_entries_srv_.start(AppendEntriesCallback(this, &RaftCore::handleAppendEntriesRequest));
|
||||
if (res < 0)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
|
||||
res = request_vote_srv_.start(RequestVoteCallback(this, &RaftCore::handleRequestVoteRequest));
|
||||
if (res < 0)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
|
||||
res = append_entries_client_.init();
|
||||
if (res < 0)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
append_entries_client_.setRequestTimeout(getUpdateInterval());
|
||||
|
||||
res = request_vote_client_.init();
|
||||
if (res < 0)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
request_vote_client_.setRequestTimeout(getUpdateInterval());
|
||||
|
||||
startPeriodic(getUpdateInterval());
|
||||
|
||||
trace(TraceRaftCoreInited, getUpdateInterval().toUSec());
|
||||
|
||||
UAVCAN_ASSERT(res >= 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RaftCore::appendLog(const Entry& entry)
|
||||
{
|
||||
if (isLeader())
|
||||
{
|
||||
trace(TraceRaftNewLogEntry, entry.node_id);
|
||||
return persistent_state_.getLog().append(entry);
|
||||
}
|
||||
else
|
||||
{
|
||||
UAVCAN_ASSERT(0);
|
||||
return -ErrLogic;
|
||||
}
|
||||
}
|
||||
|
||||
} // dynamic_node_id_server_impl
|
||||
|
||||
}
|
||||
|
||||
@@ -53,6 +53,15 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class EventTracer : public uavcan::IDynamicNodeIDAllocationServerEventTracer
|
||||
{
|
||||
virtual void onEvent(uavcan::uint16_t event_code, uavcan::int64_t event_argument)
|
||||
{
|
||||
std::cout << "Event\t" << event_code << "\t" << event_argument << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static const unsigned NumEntriesInStorageWithEmptyLog = 4; // last index + 3 items per log entry
|
||||
|
||||
|
||||
@@ -140,10 +149,11 @@ TEST(DynamicNodeIDAllocationServer, MarshallingStorageDecorator)
|
||||
|
||||
TEST(DynamicNodeIDAllocationServer, LogInitialization)
|
||||
{
|
||||
EventTracer tracer;
|
||||
// No log data in the storage - initializing empty log
|
||||
{
|
||||
StorageBackend storage;
|
||||
uavcan::dynamic_node_id_server_impl::Log log(storage);
|
||||
uavcan::dynamic_node_id_server_impl::Log log(storage, tracer);
|
||||
|
||||
ASSERT_EQ(0, storage.getNumKeys());
|
||||
ASSERT_LE(0, log.init());
|
||||
@@ -157,7 +167,7 @@ TEST(DynamicNodeIDAllocationServer, LogInitialization)
|
||||
// Nonempty storage, one item
|
||||
{
|
||||
StorageBackend storage;
|
||||
uavcan::dynamic_node_id_server_impl::Log log(storage);
|
||||
uavcan::dynamic_node_id_server_impl::Log log(storage, tracer);
|
||||
|
||||
storage.set("log_last_index", "0");
|
||||
ASSERT_LE(-uavcan::ErrFailure, log.init()); // Expected one entry, none found
|
||||
@@ -174,7 +184,7 @@ TEST(DynamicNodeIDAllocationServer, LogInitialization)
|
||||
// Nonempty storage, broken data
|
||||
{
|
||||
StorageBackend storage;
|
||||
uavcan::dynamic_node_id_server_impl::Log log(storage);
|
||||
uavcan::dynamic_node_id_server_impl::Log log(storage, tracer);
|
||||
|
||||
storage.set("log_last_index", "foobar");
|
||||
ASSERT_LE(-uavcan::ErrFailure, log.init()); // Bad value
|
||||
@@ -197,7 +207,7 @@ TEST(DynamicNodeIDAllocationServer, LogInitialization)
|
||||
// Nonempty storage, many items
|
||||
{
|
||||
StorageBackend storage;
|
||||
uavcan::dynamic_node_id_server_impl::Log log(storage);
|
||||
uavcan::dynamic_node_id_server_impl::Log log(storage, tracer);
|
||||
|
||||
storage.set("log_last_index", "1"); // 2 items - 0, 1
|
||||
storage.set("log0_term", "0");
|
||||
@@ -235,8 +245,9 @@ TEST(DynamicNodeIDAllocationServer, LogInitialization)
|
||||
|
||||
TEST(DynamicNodeIDAllocationServer, LogAppend)
|
||||
{
|
||||
EventTracer tracer;
|
||||
StorageBackend storage;
|
||||
uavcan::dynamic_node_id_server_impl::Log log(storage);
|
||||
uavcan::dynamic_node_id_server_impl::Log log(storage, tracer);
|
||||
|
||||
ASSERT_EQ(0, storage.getNumKeys());
|
||||
ASSERT_LE(0, log.init());
|
||||
@@ -307,8 +318,9 @@ TEST(DynamicNodeIDAllocationServer, LogAppend)
|
||||
|
||||
TEST(DynamicNodeIDAllocationServer, LogRemove)
|
||||
{
|
||||
EventTracer tracer;
|
||||
StorageBackend storage;
|
||||
uavcan::dynamic_node_id_server_impl::Log log(storage);
|
||||
uavcan::dynamic_node_id_server_impl::Log log(storage, tracer);
|
||||
|
||||
/*
|
||||
* Filling the log fully
|
||||
@@ -359,12 +371,13 @@ TEST(DynamicNodeIDAllocationServer, LogRemove)
|
||||
|
||||
TEST(DynamicNodeIDAllocationServer, PersistentStorageInitialization)
|
||||
{
|
||||
EventTracer tracer;
|
||||
/*
|
||||
* First initialization
|
||||
*/
|
||||
{
|
||||
StorageBackend storage;
|
||||
uavcan::dynamic_node_id_server_impl::PersistentState pers(storage);
|
||||
uavcan::dynamic_node_id_server_impl::PersistentState pers(storage, tracer);
|
||||
|
||||
ASSERT_EQ(0, storage.getNumKeys());
|
||||
ASSERT_LE(0, pers.init());
|
||||
@@ -382,12 +395,12 @@ TEST(DynamicNodeIDAllocationServer, PersistentStorageInitialization)
|
||||
|
||||
{
|
||||
// This log is used to initialize the storage
|
||||
uavcan::dynamic_node_id_server_impl::Log log(storage);
|
||||
uavcan::dynamic_node_id_server_impl::Log log(storage, tracer);
|
||||
ASSERT_LE(0, log.init());
|
||||
}
|
||||
ASSERT_LE(1, storage.getNumKeys());
|
||||
|
||||
uavcan::dynamic_node_id_server_impl::PersistentState pers(storage);
|
||||
uavcan::dynamic_node_id_server_impl::PersistentState pers(storage, tracer);
|
||||
|
||||
ASSERT_LE(0, pers.init());
|
||||
|
||||
@@ -404,14 +417,14 @@ TEST(DynamicNodeIDAllocationServer, PersistentStorageInitialization)
|
||||
|
||||
{
|
||||
// This log is used to initialize the storage
|
||||
uavcan::dynamic_node_id_server_impl::Log log(storage);
|
||||
uavcan::dynamic_node_id_server_impl::Log log(storage, tracer);
|
||||
ASSERT_LE(0, log.init());
|
||||
}
|
||||
ASSERT_LE(1, storage.getNumKeys());
|
||||
|
||||
storage.set("current_term", "1");
|
||||
|
||||
uavcan::dynamic_node_id_server_impl::PersistentState pers(storage);
|
||||
uavcan::dynamic_node_id_server_impl::PersistentState pers(storage, tracer);
|
||||
|
||||
ASSERT_GT(0, pers.init()); // Fails because current term is not zero
|
||||
|
||||
@@ -432,7 +445,7 @@ TEST(DynamicNodeIDAllocationServer, PersistentStorageInitialization)
|
||||
|
||||
{
|
||||
// This log is used to initialize the storage
|
||||
uavcan::dynamic_node_id_server_impl::Log log(storage);
|
||||
uavcan::dynamic_node_id_server_impl::Log log(storage, tracer);
|
||||
ASSERT_LE(0, log.init());
|
||||
|
||||
uavcan::protocol::dynamic_node_id::server::Entry entry;
|
||||
@@ -443,7 +456,7 @@ TEST(DynamicNodeIDAllocationServer, PersistentStorageInitialization)
|
||||
}
|
||||
ASSERT_LE(4, storage.getNumKeys());
|
||||
|
||||
uavcan::dynamic_node_id_server_impl::PersistentState pers(storage);
|
||||
uavcan::dynamic_node_id_server_impl::PersistentState pers(storage, tracer);
|
||||
|
||||
ASSERT_GT(0, pers.init()); // Fails because log is not empty
|
||||
|
||||
@@ -468,8 +481,9 @@ TEST(DynamicNodeIDAllocationServer, PersistentStorageInitialization)
|
||||
|
||||
TEST(DynamicNodeIDAllocationServer, PersistentStorage)
|
||||
{
|
||||
EventTracer tracer;
|
||||
StorageBackend storage;
|
||||
uavcan::dynamic_node_id_server_impl::PersistentState pers(storage);
|
||||
uavcan::dynamic_node_id_server_impl::PersistentState pers(storage, tracer);
|
||||
|
||||
/*
|
||||
* Initializing
|
||||
@@ -549,15 +563,17 @@ TEST(DynamicNodeIDAllocationServer, ClusterManagerInitialization)
|
||||
uavcan::GlobalDataTypeRegistry::instance().reset();
|
||||
uavcan::DefaultDataTypeRegistrator<uavcan::protocol::dynamic_node_id::server::Discovery> _reg1;
|
||||
|
||||
EventTracer tracer;
|
||||
|
||||
/*
|
||||
* Simple initialization
|
||||
*/
|
||||
{
|
||||
StorageBackend storage;
|
||||
uavcan::dynamic_node_id_server_impl::Log log(storage);
|
||||
uavcan::dynamic_node_id_server_impl::Log log(storage, tracer);
|
||||
InterlinkedTestNodesWithSysClock nodes;
|
||||
|
||||
uavcan::dynamic_node_id_server_impl::ClusterManager mgr(nodes.a, storage, log);
|
||||
uavcan::dynamic_node_id_server_impl::ClusterManager mgr(nodes.a, storage, log, tracer);
|
||||
|
||||
// Too big
|
||||
ASSERT_GT(0, mgr.init(MaxClusterSize + 1));
|
||||
@@ -579,10 +595,10 @@ TEST(DynamicNodeIDAllocationServer, ClusterManagerInitialization)
|
||||
*/
|
||||
{
|
||||
StorageBackend storage;
|
||||
uavcan::dynamic_node_id_server_impl::Log log(storage);
|
||||
uavcan::dynamic_node_id_server_impl::Log log(storage, tracer);
|
||||
InterlinkedTestNodesWithSysClock nodes;
|
||||
|
||||
uavcan::dynamic_node_id_server_impl::ClusterManager mgr(nodes.a, storage, log);
|
||||
uavcan::dynamic_node_id_server_impl::ClusterManager mgr(nodes.a, storage, log, tracer);
|
||||
|
||||
// Not configured
|
||||
ASSERT_GT(0, mgr.init());
|
||||
@@ -601,11 +617,12 @@ TEST(DynamicNodeIDAllocationServer, ClusterManagerOneServer)
|
||||
uavcan::GlobalDataTypeRegistry::instance().reset();
|
||||
uavcan::DefaultDataTypeRegistrator<uavcan::protocol::dynamic_node_id::server::Discovery> _reg1;
|
||||
|
||||
EventTracer tracer;
|
||||
StorageBackend storage;
|
||||
uavcan::dynamic_node_id_server_impl::Log log(storage);
|
||||
uavcan::dynamic_node_id_server_impl::Log log(storage, tracer);
|
||||
InterlinkedTestNodesWithSysClock nodes;
|
||||
|
||||
uavcan::dynamic_node_id_server_impl::ClusterManager mgr(nodes.a, storage, log);
|
||||
uavcan::dynamic_node_id_server_impl::ClusterManager mgr(nodes.a, storage, log, tracer);
|
||||
|
||||
/*
|
||||
* Pub and sub
|
||||
@@ -675,11 +692,12 @@ TEST(DynamicNodeIDAllocationServer, ClusterManagerThreeServers)
|
||||
uavcan::GlobalDataTypeRegistry::instance().reset();
|
||||
uavcan::DefaultDataTypeRegistrator<uavcan::protocol::dynamic_node_id::server::Discovery> _reg1;
|
||||
|
||||
EventTracer tracer;
|
||||
StorageBackend storage;
|
||||
uavcan::dynamic_node_id_server_impl::Log log(storage);
|
||||
uavcan::dynamic_node_id_server_impl::Log log(storage, tracer);
|
||||
InterlinkedTestNodesWithSysClock nodes;
|
||||
|
||||
uavcan::dynamic_node_id_server_impl::ClusterManager mgr(nodes.a, storage, log);
|
||||
uavcan::dynamic_node_id_server_impl::ClusterManager mgr(nodes.a, storage, log, tracer);
|
||||
|
||||
/*
|
||||
* Pub and sub
|
||||
|
||||
Reference in New Issue
Block a user