libuav original
Dependents: UAVCAN UAVCAN_Subscriber
server.hpp
00001 /* 00002 * Copyright (C) 2015 Pavel Kirienko <pavel.kirienko@gmail.com> 00003 */ 00004 00005 #ifndef UAVCAN_PROTOCOL_DYNAMIC_NODE_ID_SERVER_CENTRALIZED_SERVER_HPP_INCLUDED 00006 #define UAVCAN_PROTOCOL_DYNAMIC_NODE_ID_SERVER_CENTRALIZED_SERVER_HPP_INCLUDED 00007 00008 #include <uavcan/build_config.hpp> 00009 #include <uavcan/debug.hpp> 00010 #include <uavcan/protocol/dynamic_node_id_server/abstract_server.hpp> 00011 #include <uavcan/protocol/dynamic_node_id_server/node_id_selector.hpp> 00012 #include <uavcan/protocol/dynamic_node_id_server/storage_marshaller.hpp> 00013 #include <uavcan/protocol/dynamic_node_id_server/centralized/storage.hpp> 00014 00015 namespace uavcan 00016 { 00017 namespace dynamic_node_id_server 00018 { 00019 namespace centralized 00020 { 00021 /** 00022 * This server is an alternative to @ref DistributedServer with the following differences: 00023 * - It is not distributed, so using it means introducing a single point of failure into the system. 00024 * - It takes less code space and requires less RAM, which makes it suitable for resource-constrained applications. 00025 * 00026 * This version is suitable only for simple non-critical systems. 00027 */ 00028 class Server : public AbstractServer 00029 { 00030 Storage storage_; 00031 00032 /* 00033 * Private methods 00034 */ 00035 bool isNodeIDTaken(const NodeID node_id) const 00036 { 00037 return storage_.isNodeIDOccupied(node_id); 00038 } 00039 00040 void tryPublishAllocationResult(const NodeID node_id, const UniqueID& unique_id) 00041 { 00042 const int res = allocation_request_manager_.broadcastAllocationResponse(unique_id, node_id); 00043 if (res < 0) 00044 { 00045 tracer_.onEvent(TraceError, res); 00046 node_.registerInternalFailure("Dynamic allocation response"); 00047 } 00048 } 00049 00050 /* 00051 * Methods of IAllocationRequestHandler 00052 */ 00053 virtual bool canPublishFollowupAllocationResponse() const 00054 { 00055 return true; // Because there's only one Centralized server in the system 00056 } 00057 00058 virtual void handleAllocationRequest(const UniqueID& unique_id, const NodeID preferred_node_id) 00059 { 00060 const NodeID existing_node_id = storage_.getNodeIDForUniqueID(unique_id); 00061 if (existing_node_id.isValid()) 00062 { 00063 tryPublishAllocationResult(existing_node_id, unique_id); 00064 } 00065 else 00066 { 00067 const NodeID allocated_node_id = 00068 NodeIDSelector<Server>(this, &Server::isNodeIDTaken).findFreeNodeID(preferred_node_id); 00069 00070 if (allocated_node_id.isUnicast()) 00071 { 00072 const int res = storage_.add(allocated_node_id, unique_id); 00073 if (res >= 0) 00074 { 00075 tryPublishAllocationResult(allocated_node_id, unique_id); 00076 } 00077 else 00078 { 00079 tracer_.onEvent(TraceError, res); 00080 node_.registerInternalFailure("CentralizedServer storage add"); 00081 } 00082 } 00083 else 00084 { 00085 UAVCAN_TRACE("dynamic_node_id_server::distributed::Server", "Request ignored - no free node ID left"); 00086 } 00087 } 00088 } 00089 00090 /* 00091 * Methods of INodeDiscoveryHandler 00092 */ 00093 virtual bool canDiscoverNewNodes() const 00094 { 00095 return true; // Because there's only one Centralized server in the system 00096 } 00097 00098 virtual NodeAwareness checkNodeAwareness(NodeID node_id) const 00099 { 00100 return storage_.isNodeIDOccupied(node_id) ? NodeAwarenessKnownAndCommitted : NodeAwarenessUnknown; 00101 } 00102 00103 virtual void handleNewNodeDiscovery(const UniqueID* unique_id_or_null, NodeID node_id) 00104 { 00105 if (storage_.isNodeIDOccupied(node_id)) 00106 { 00107 UAVCAN_ASSERT(0); // Such node is already known, the class that called this method should have known that 00108 return; 00109 } 00110 00111 const int res = storage_.add(node_id, (unique_id_or_null == UAVCAN_NULLPTR) ? UniqueID() : *unique_id_or_null); 00112 if (res < 0) 00113 { 00114 tracer_.onEvent(TraceError, res); 00115 node_.registerInternalFailure("CentralizedServer storage add"); 00116 } 00117 } 00118 00119 public: 00120 Server(INode& node, 00121 IStorageBackend& storage, 00122 IEventTracer& tracer) 00123 : AbstractServer(node, tracer) 00124 , storage_(storage) 00125 { } 00126 00127 int init(const UniqueID& own_unique_id, 00128 const TransferPriority priority = TransferPriority::OneHigherThanLowest) 00129 { 00130 /* 00131 * Initializing storage first, because the next step requires it to be loaded 00132 */ 00133 int res = storage_.init(); 00134 if (res < 0) 00135 { 00136 return res; 00137 } 00138 00139 /* 00140 * Common logic 00141 */ 00142 res = AbstractServer::init(own_unique_id, priority); 00143 if (res < 0) 00144 { 00145 return res; 00146 } 00147 00148 /* 00149 * Making sure that the server is started with the same node ID 00150 */ 00151 { 00152 const NodeID stored_own_node_id = storage_.getNodeIDForUniqueID(getOwnUniqueID()); 00153 if (stored_own_node_id.isValid()) 00154 { 00155 if (stored_own_node_id != node_.getNodeID()) 00156 { 00157 return -ErrInvalidConfiguration; 00158 } 00159 } 00160 else 00161 { 00162 res = storage_.add(node_.getNodeID(), getOwnUniqueID()); 00163 if (res < 0) 00164 { 00165 return res; 00166 } 00167 } 00168 } 00169 00170 return 0; 00171 } 00172 00173 uint8_t getNumAllocations() const { return storage_.getSize(); } 00174 }; 00175 00176 } 00177 } 00178 } 00179 00180 #endif // UAVCAN_PROTOCOL_DYNAMIC_NODE_ID_SERVER_CENTRALIZED_SERVER_HPP_INCLUDED
Generated on Tue Jul 12 2022 17:17:34 by 1.7.2