The Sparta Modeling Framework
Loading...
Searching...
No Matches
Tap.hpp
1// <Tap> -*- C++ -*-
2
3#pragma once
4
5#include <iostream>
6#include <vector>
7
9#include "sparta/log/categories/CategoryManager.hpp"
10#include "sparta/utils/StringManager.hpp"
11#include "sparta/log/Destination.hpp"
12#include "sparta/log/Events.hpp"
13#include "sparta/simulation/TreeNodePrivateAttorney.hpp"
14namespace sparta
15{
16 namespace log
17 {
18
27 class Tap
28 {
29 public:
30
32 Tap(const Tap&) = delete;
33
35 Tap& operator=(const Tap&) = delete;
36
55 template <typename DestT>
56 Tap(TreeNode* node, const std::string* pcategory, DestT& dest) :
57 node_(node),
58 category_(pcategory)
59 {
60 Destination* d = DestinationManager::getDestination(dest); // Can instantiate new
61 sparta_assert(d != nullptr);
62 dest_ = d;
63
64 if(nullptr == node){
65 throw SpartaException("Cannot attach a Tap to a null TreeNode");
66 }
67
68 reset(node);
69 }
70
81 template <typename DestT>
82 Tap(TreeNode* node, const std::string& category, DestT& dest) :
83 Tap(node, StringManager::getStringManager().internString(category), dest)
84 {
85 // Initialization handled in delegated constructor
86 }
87
102 template <typename DestT>
103 Tap(const std::string& category, DestT& dest) :
104 node_(nullptr),
105 category_(StringManager::getStringManager().internString(category))
106 {
107 Destination* d = DestinationManager::getDestination(dest); // Can instantiate new
108 sparta_assert(d != nullptr);
109 dest_ = d;
110 }
111
116 virtual ~Tap() {
117 detach();
118 }
119
128 void reset(TreeNode* node) {
129 detach();
130
131 if(nullptr != node){
132 node_wptr_ = node->getWeakPtr();
133
134 // Use the form of the registration command which can ignore the no-notification-source case
135 TreeNodePrivateAttorney::registerForNotification<sparta::log::Message,
136 typename std::remove_reference<decltype(*this)>::type,
137 &std::remove_reference<decltype(*this)>::type::send_>
138 (node_wptr_.lock().get(), this, *category_, false);
139 }
140 }
141
150 void detach() {
151 if(!node_wptr_.expired()){
152 auto shared = node_wptr_.lock();
153 if(shared){ // Check if reset
154 TreeNodePrivateAttorney::deregisterForNotification<sparta::log::Message,
155 typename std::remove_reference<decltype(*this)>::type,
156 &std::remove_reference<decltype(*this)>::type::send_>(shared.get(),
157 this, *category_);
158 }
159 }else{
160 // Warn that the target node already expired before this tap was destructed
161 // Note that this is one of the only things that cannot be logged because
162 // it can happen at a time when there is all taps that may observe it are being
163 // destroyed. This it not a real issue, but everyone should be aware that it can
164 // happen.
165 //std::cerr << "Warning: Tap of category \"" << *category_ << "\" and destination "
166 // << dest_->stringize() << " is detaching from an already-expired node"
167 // << std::endl;
168 }
169
170 node_wptr_.reset(); // Clears content
171 }
172
173 const std::string* getCategoryID() const {
174 return category_;
175 }
176
177 const std::string& getCategoryName() const {
178 return *category_;
179 }
180
181 const Destination* getDestination() const {
182 return dest_;
183 }
184
185 Destination* getDestination() {
186 return dest_;
187 }
188
196 uint64_t getNumMessages() const {
197 return num_msgs_;
198 }
199
206 return node_;
207 }
208
214 return node_wptr_.expired();
215 }
216
217 protected:
218
234 void send_(const TreeNode& origin,
235 const TreeNode& obs_pt_DO_NOT_USE,
236 const Message& msg) {
237 (void)origin;
238 (void)obs_pt_DO_NOT_USE;
239
240 sparta_assert(dest_); // Ensure this tap has a valid destination before sending
241 dest_->write(msg);
242 ++num_msgs_;
243 }
244
245 private:
246
247 TreeNode* node_;
248 TreeNode::WeakPtr node_wptr_;
249 const std::string* const category_;
250 Destination* dest_;
251 uint64_t num_msgs_ = 0;
252 };
253
258 {
259 public:
260
261 TapDescriptor(const std::string& _loc_pattern,
262 const std::string& _category,
263 const std::string& _destination) :
264 loc_pattern_(_loc_pattern),
265 category_(_category),
266 dest_(_destination)
267 { }
268
269 // Allow copies and assignment (needed for vector)
270 TapDescriptor(const TapDescriptor&) = default;
271 TapDescriptor& operator=(const TapDescriptor&) = default;
272
273 // Pretty print
274 std::string stringize() const {
275 std::stringstream ss;
276 ss << "Tap location_pattern=\"" << loc_pattern_ << "\" (category=\"" << category_
277 << "\") -> file: \"" << dest_ << "\"";
278 return ss.str();
279 }
280
281 // Increments the usage count of this descriptor
282 void incrementUsageCount() const { ++num_times_used_; }
283
284 // Returns the usage count (incremented by incrementUsageCount)
285 uint32_t getUsageCount() const { return num_times_used_; }
286
287 // Get the location pattern
288 const std::string &getLocation() const { return loc_pattern_; }
289
290 // Get the category
291 const std::string &getCategory() const { return category_; }
292
293 // Get the destination file
294 const std::string &getDestination() const { return dest_; }
295
296 // Get pattern goodness check
297 bool hasBadPattern() const { return has_bad_pattern_; }
298
299 // Set the pattern to be bad
300 void setBadPattern(bool bad) const { has_bad_pattern_ = bad; }
301
302 private:
303
304 // Node location string (pattern) on which tap should be placed
305 std::string loc_pattern_;
306
307 // Tap category
308 std::string category_;
309
310 // Destination file for this tap
311 std::string dest_;
312
313 // Number of times this descriptor has been used to
314 // construct a tap
315 mutable uint32_t num_times_used_ = 0;
316
317 // Is the pattern for this tap known to be false. This is usually
318 // detected as the tree is being built when searches fail with an
319 // exception
320 mutable bool has_bad_pattern_ = false;
321 };
322
323 // Convenient typedef
324 typedef std::vector<TapDescriptor> TapDescVec;
325
332 inline std::vector<const log::TapDescriptor*> getUnusedTaps(const log::TapDescVec& taps) {
333 std::vector<const log::TapDescriptor*> unused_taps;
334 for(const TapDescriptor& td : taps){
335 if(td.getUsageCount() == 0){
336 unused_taps.push_back(&td);
337 }
338 }
339 return unused_taps;
340 }
341
342 } // namespace log
343} // namespace sparta
344
345
#define sparta_assert(...)
Simple variadic assertion that will throw a sparta_exception if the condition fails.
Basic Node framework in sparta device tree composite pattern.
Used to construct and throw a standard C++ exception. Inherits from std::exception.
Manages string internment for SPARTA. This allows strings to be compared by pointer once interned.
Node in a composite tree representing a sparta Tree item.
Definition TreeNode.hpp:205
std::weak_ptr< TreeNode > WeakPtr
Weak pointer to a TreeNode. Acquire with getWeakPtr.
Definition TreeNode.hpp:266
WeakPtr getWeakPtr()
Gets a weak pointer to this TreeNode. This weak pointer is guaranteed to expire when this TreeNode is...
static Destination * getDestination(DestT &arg)
Requests an existing Destination* from the manager and allocates a new one if it does not yet have a ...
Generic Logging destination stream interface which writes sparta::log::Message structures to some out...
void write(const sparta::log::Message &msg)
Describes a tap.
Definition Tap.hpp:258
Logging Tap. Attach to a TreeNode to intercept logging messages from any NotificationSource nodes in ...
Definition Tap.hpp:28
void reset(TreeNode *node)
Detach the tap from the current node (if any) and re-attach to a new node. Destination and category o...
Definition Tap.hpp:128
Tap(TreeNode *node, const std::string *pcategory, DestT &dest)
Constructor.
Definition Tap.hpp:56
virtual ~Tap()
Destructor.
Definition Tap.hpp:116
Tap(TreeNode *node, const std::string &category, DestT &dest)
Constructor.
Definition Tap.hpp:82
uint64_t getNumMessages() const
Gets the number of messages seen by this tap having the designated category.
Definition Tap.hpp:196
TreeNode * getObservedNode() const
Gets the node at which this tap is observing.
Definition Tap.hpp:205
void send_(const TreeNode &origin, const TreeNode &obs_pt_DO_NOT_USE, const Message &msg)
Actually send the notification.
Definition Tap.hpp:234
void detach()
Detach the tap from a node without destructing. Node can later be reattached to the same or another n...
Definition Tap.hpp:150
Tap & operator=(const Tap &)=delete
Disallow copy assignment.
Tap(const Tap &)=delete
Disallow copy construction.
Tap(const std::string &category, DestT &dest)
Non-observing Constructor.
Definition Tap.hpp:103
bool isObservedNodeExpired() const
Checks if the node at which this tap is observing has been deleted (i.e. its weak reference has expir...
Definition Tap.hpp:213
std::vector< const log::TapDescriptor * > getUnusedTaps(const log::TapDescVec &taps)
Finds all unused taps in the given tap descriptor vector.
Definition Tap.hpp:332
Macros for handling exponential backoff.
Contains a logging message header and content.
Definition Message.hpp:18