mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-05-23 16:47:35 +08:00
Merge pull request #86 from UAVCAN/nid_allocation_activity_monitoring
Monitoring activity of dynamic node ID allocation servers
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Pavel Kirienko <pavel.kirienko@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef UAVCAN_PROTOCOL_DYNAMIC_NODE_ID_SERVER_SERVER_HPP_INCLUDED
|
||||
#define UAVCAN_PROTOCOL_DYNAMIC_NODE_ID_SERVER_SERVER_HPP_INCLUDED
|
||||
|
||||
#include <uavcan/build_config.hpp>
|
||||
#include <uavcan/debug.hpp>
|
||||
#include <uavcan/protocol/dynamic_node_id_server/allocation_request_manager.hpp>
|
||||
#include <uavcan/protocol/dynamic_node_id_server/node_discoverer.hpp>
|
||||
#include <uavcan/protocol/dynamic_node_id_server/event.hpp>
|
||||
|
||||
namespace uavcan
|
||||
{
|
||||
namespace dynamic_node_id_server
|
||||
{
|
||||
|
||||
class AbstractServer : protected IAllocationRequestHandler
|
||||
, protected INodeDiscoveryHandler
|
||||
{
|
||||
UniqueID own_unique_id_;
|
||||
MonotonicTime started_at_;
|
||||
|
||||
protected:
|
||||
INode& node_;
|
||||
IEventTracer& tracer_;
|
||||
AllocationRequestManager allocation_request_manager_;
|
||||
NodeDiscoverer node_discoverer_;
|
||||
|
||||
AbstractServer(INode& node,
|
||||
IEventTracer& tracer) :
|
||||
node_(node),
|
||||
tracer_(tracer),
|
||||
allocation_request_manager_(node, tracer, *this),
|
||||
node_discoverer_(node, tracer, *this)
|
||||
{ }
|
||||
|
||||
const UniqueID& getOwnUniqueID() const { return own_unique_id_; }
|
||||
|
||||
int init(const UniqueID& own_unique_id, const TransferPriority priority)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
own_unique_id_ = own_unique_id;
|
||||
|
||||
res = allocation_request_manager_.init(priority);
|
||||
if (res < 0)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
|
||||
res = node_discoverer_.init(priority);
|
||||
if (res < 0)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
|
||||
started_at_ = node_.getMonotonicTime();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* This can be used to guess if there are any un-allocated dynamic nodes left in the network.
|
||||
*/
|
||||
bool guessIfAllDynamicNodesAreAllocated(
|
||||
const MonotonicDuration& allocation_activity_timeout =
|
||||
MonotonicDuration::fromMSec(Allocation::MAX_REQUEST_PERIOD_MS * 2),
|
||||
const MonotonicDuration& min_uptime = MonotonicDuration::fromMSec(6000)) const
|
||||
{
|
||||
const MonotonicTime ts = node_.getMonotonicTime();
|
||||
|
||||
/*
|
||||
* If uptime is not large enough, the allocator may be unaware about some nodes yet.
|
||||
*/
|
||||
const MonotonicDuration uptime = ts - started_at_;
|
||||
if (uptime < max(allocation_activity_timeout, min_uptime))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* If there are any undiscovered nodes, assume that allocation is still happening.
|
||||
*/
|
||||
if (node_discoverer_.hasUnknownNodes())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Lastly, check if there wasn't any allocation messages detected on the bus in the specified amount of time.
|
||||
*/
|
||||
const MonotonicDuration since_allocation_activity =
|
||||
ts - allocation_request_manager_.getTimeOfLastAllocationActivity();
|
||||
if (since_allocation_activity < allocation_activity_timeout)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is useful for debugging/testing/monitoring.
|
||||
*/
|
||||
const NodeDiscoverer& getNodeDiscoverer() const { return node_discoverer_; }
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // Include guard
|
||||
+9
@@ -51,6 +51,7 @@ class AllocationRequestManager
|
||||
const MonotonicDuration stage_timeout_;
|
||||
|
||||
MonotonicTime last_message_timestamp_;
|
||||
MonotonicTime last_activity_timestamp_;
|
||||
Allocation::FieldTypes::unique_id current_unique_id_;
|
||||
|
||||
IAllocationRequestHandler& handler_;
|
||||
@@ -127,6 +128,7 @@ class AllocationRequestManager
|
||||
void handleAllocation(const ReceivedDataStructure<Allocation>& msg)
|
||||
{
|
||||
trace(TraceAllocationActivity, msg.getSrcNodeID().get());
|
||||
last_activity_timestamp_ = msg.getMonotonicTimestamp();
|
||||
|
||||
if (!msg.isAnonymousTransfer())
|
||||
{
|
||||
@@ -266,9 +268,16 @@ public:
|
||||
msg.node_id = allocated_node_id.get();
|
||||
|
||||
trace(TraceAllocationResponse, msg.node_id);
|
||||
last_activity_timestamp_ = allocation_pub_.getNode().getMonotonicTime();
|
||||
|
||||
return allocation_pub_.broadcast(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* When the last allocation activity was registered.
|
||||
* This value can be used to heuristically determine whether there are any unallocated nodes left in the network.
|
||||
*/
|
||||
MonotonicTime getTimeOfLastAllocationActivity() const { return last_activity_timestamp_; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -7,8 +7,7 @@
|
||||
|
||||
#include <uavcan/build_config.hpp>
|
||||
#include <uavcan/debug.hpp>
|
||||
#include <uavcan/protocol/dynamic_node_id_server/allocation_request_manager.hpp>
|
||||
#include <uavcan/protocol/dynamic_node_id_server/node_discoverer.hpp>
|
||||
#include <uavcan/protocol/dynamic_node_id_server/abstract_server.hpp>
|
||||
#include <uavcan/protocol/dynamic_node_id_server/node_id_selector.hpp>
|
||||
#include <uavcan/protocol/dynamic_node_id_server/storage_marshaller.hpp>
|
||||
#include <uavcan/protocol/dynamic_node_id_server/centralized/storage.hpp>
|
||||
@@ -26,15 +25,8 @@ namespace centralized
|
||||
*
|
||||
* This version is suitable only for simple non-critical systems.
|
||||
*/
|
||||
class Server : IAllocationRequestHandler
|
||||
, INodeDiscoveryHandler
|
||||
class Server : public AbstractServer
|
||||
{
|
||||
UniqueID own_unique_id_;
|
||||
|
||||
INode& node_;
|
||||
IEventTracer& tracer_;
|
||||
AllocationRequestManager allocation_request_manager_;
|
||||
NodeDiscoverer node_discoverer_;
|
||||
Storage storage_;
|
||||
|
||||
/*
|
||||
@@ -128,10 +120,7 @@ public:
|
||||
Server(INode& node,
|
||||
IStorageBackend& storage,
|
||||
IEventTracer& tracer)
|
||||
: node_(node)
|
||||
, tracer_(tracer)
|
||||
, allocation_request_manager_(node, tracer, *this)
|
||||
, node_discoverer_(node, tracer, *this)
|
||||
: AbstractServer(node, tracer)
|
||||
, storage_(storage)
|
||||
{ }
|
||||
|
||||
@@ -147,13 +136,20 @@ public:
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Common logic
|
||||
*/
|
||||
res = AbstractServer::init(own_unique_id, priority);
|
||||
if (res < 0)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Making sure that the server is started with the same node ID
|
||||
*/
|
||||
own_unique_id_ = own_unique_id;
|
||||
|
||||
{
|
||||
const NodeID stored_own_node_id = storage_.getNodeIDForUniqueID(own_unique_id_);
|
||||
const NodeID stored_own_node_id = storage_.getNodeIDForUniqueID(getOwnUniqueID());
|
||||
if (stored_own_node_id.isValid())
|
||||
{
|
||||
if (stored_own_node_id != node_.getNodeID())
|
||||
@@ -163,7 +159,7 @@ public:
|
||||
}
|
||||
else
|
||||
{
|
||||
res = storage_.add(node_.getNodeID(), own_unique_id_);
|
||||
res = storage_.add(node_.getNodeID(), getOwnUniqueID());
|
||||
if (res < 0)
|
||||
{
|
||||
return res;
|
||||
@@ -171,21 +167,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Misc
|
||||
*/
|
||||
res = allocation_request_manager_.init(priority);
|
||||
if (res < 0)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
|
||||
res = node_discoverer_.init(priority);
|
||||
if (res < 0)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,9 +9,8 @@
|
||||
#include <uavcan/debug.hpp>
|
||||
#include <uavcan/protocol/dynamic_node_id_server/distributed/types.hpp>
|
||||
#include <uavcan/protocol/dynamic_node_id_server/distributed/raft_core.hpp>
|
||||
#include <uavcan/protocol/dynamic_node_id_server/allocation_request_manager.hpp>
|
||||
#include <uavcan/protocol/dynamic_node_id_server/abstract_server.hpp>
|
||||
#include <uavcan/protocol/dynamic_node_id_server/node_id_selector.hpp>
|
||||
#include <uavcan/protocol/dynamic_node_id_server/node_discoverer.hpp>
|
||||
#include <uavcan/protocol/dynamic_node_id_server/event.hpp>
|
||||
|
||||
namespace uavcan
|
||||
@@ -23,8 +22,7 @@ namespace distributed
|
||||
/**
|
||||
* This class implements the top-level allocation logic and server API.
|
||||
*/
|
||||
class UAVCAN_EXPORT Server : IAllocationRequestHandler
|
||||
, INodeDiscoveryHandler
|
||||
class UAVCAN_EXPORT Server : public AbstractServer
|
||||
, IRaftLeaderMonitor
|
||||
{
|
||||
struct UniqueIDLogPredicate
|
||||
@@ -55,19 +53,10 @@ class UAVCAN_EXPORT Server : IAllocationRequestHandler
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
UniqueID own_unique_id_;
|
||||
|
||||
/*
|
||||
* States
|
||||
*/
|
||||
INode& node_;
|
||||
IEventTracer& tracer_;
|
||||
RaftCore raft_core_;
|
||||
AllocationRequestManager allocation_request_manager_;
|
||||
NodeDiscoverer node_discoverer_;
|
||||
|
||||
/*
|
||||
* Methods of IAllocationRequestHandler
|
||||
@@ -196,7 +185,7 @@ class UAVCAN_EXPORT Server : IAllocationRequestHandler
|
||||
|
||||
if (!result.isConstructed())
|
||||
{
|
||||
raft_core_.appendLog(own_unique_id_, node_.getNodeID());
|
||||
raft_core_.appendLog(getOwnUniqueID(), node_.getNodeID());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -239,11 +228,8 @@ public:
|
||||
Server(INode& node,
|
||||
IStorageBackend& storage,
|
||||
IEventTracer& tracer)
|
||||
: node_(node)
|
||||
, tracer_(tracer)
|
||||
: AbstractServer(node, tracer)
|
||||
, raft_core_(node, storage, tracer, *this)
|
||||
, allocation_request_manager_(node, tracer, *this)
|
||||
, node_discoverer_(node, tracer, *this)
|
||||
{ }
|
||||
|
||||
int init(const UniqueID& own_unique_id,
|
||||
@@ -259,37 +245,29 @@ public:
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Common logic
|
||||
*/
|
||||
res = AbstractServer::init(own_unique_id, priority);
|
||||
if (res < 0)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Making sure that the server is started with the same node ID
|
||||
*/
|
||||
own_unique_id_ = own_unique_id;
|
||||
|
||||
const LazyConstructor<RaftCore::LogEntryInfo> own_log_entry =
|
||||
raft_core_.traverseLogFromEndUntil(NodeIDLogPredicate(node_.getNodeID()));
|
||||
|
||||
if (own_log_entry.isConstructed())
|
||||
{
|
||||
if (own_log_entry->entry.unique_id != own_unique_id_)
|
||||
if (own_log_entry->entry.unique_id != getOwnUniqueID())
|
||||
{
|
||||
return -ErrInvalidConfiguration;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Misc
|
||||
*/
|
||||
res = allocation_request_manager_.init(priority);
|
||||
if (res < 0)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
|
||||
res = node_discoverer_.init(priority);
|
||||
if (res < 0)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -299,7 +277,6 @@ public:
|
||||
* These accessors are needed for debugging, visualization and testing.
|
||||
*/
|
||||
const RaftCore& getRaftCore() const { return raft_core_; }
|
||||
const NodeDiscoverer& getNodeDiscoverer() const { return node_discoverer_; }
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -256,7 +256,7 @@ void redraw(const uavcan_linux::NodePtr& node,
|
||||
/*
|
||||
* Constants that are permanent for the designed UI layout
|
||||
*/
|
||||
constexpr unsigned NumRelevantEvents = 16;
|
||||
constexpr unsigned NumRelevantEvents = 17;
|
||||
constexpr unsigned NumRowsWithoutEvents = 3;
|
||||
|
||||
/*
|
||||
@@ -390,6 +390,11 @@ void redraw(const uavcan_linux::NodePtr& node,
|
||||
node->getInternalFailureCount(),
|
||||
colorize_if(node->getInternalFailureCount() != 0, CLIColor::Magenta));
|
||||
|
||||
const bool all_allocated = server.guessIfAllDynamicNodesAreAllocated();
|
||||
render_top_str("All allocated",
|
||||
all_allocated ? "Yes": "No",
|
||||
colorize_if(!all_allocated, CLIColor::Magenta));
|
||||
|
||||
// Empty line before the next block
|
||||
std::printf(" ");
|
||||
render_next_event_counter();
|
||||
|
||||
Reference in New Issue
Block a user