19#include "sparta/pipeViewer/transaction_structures.hpp"
23#include "sparta/pairs/SpartaKeyPairs.hpp"
24#include "sparta/utils/Utils.hpp"
27#include "boost/numeric/conversion/converter.hpp"
48 template<
typename DataT, SchedulingPhase collection_phase = SchedulingPhase::Collection,
typename =
void>
52 static constexpr uint64_t BAD_DISPLAY_ID = 0x1000;
62 const std::string& name,
63 const std::string& group,
65 uint64_t parentid = 0,
66 const std::string & desc =
"Collectable <manual, no desc>") :
69 ev_close_record_(&event_set_, name +
"_pipeline_collectable_close_event",
73 "Tree has at least " <<
getNodeUID() <<
" in it. Because pipeouts "
74 "use these locations and only have 32b location IDs, the pipeline "
75 "collection system imposes a limit of " << ~(
decltype(transaction_t::location_ID))0
76 <<
" nodes in the tree. This is expected to be an unattainable number "
77 "without some kind of runaway allocation bug. If you are sure you "
78 <<
" nodes in the tree. This is expected to be an unattainable number "
79 "without some kind of runaway allocation bug. If you are sure you "
80 "need more nodes than this, contact the SPARTA team. In the meantime, "
81 "it is probably safe to comment out this assertion if you do not "
82 "plan to use the pipeline collection functionality");
84 argos_record_.location_ID = boost::numeric::converter<
decltype(argos_record_.location_ID),
86 argos_record_.control_Process_ID = 0;
87 argos_record_.parent_ID = parentid;
88 argos_record_.flags = is_Annotation;
89 argos_record_.time_Start = 0;
90 argos_record_.time_End = 1;
104 const std::string& name,
105 const DataT * collected_object,
106 uint64_t parentid = 0,
107 const std::string & desc =
"Collectable <no desc>") :
114 collected_object_ = collected_object;
117 if(collected_object) {
118 std::ostringstream ss;
119 ss << *collected_object;
120 prev_annot_ = ss.str();
132 const std::string& name,
133 uint64_t parentid = 0,
134 const std::string & desc =
"Collectable <manual, no desc>") :
149 std::ostringstream ss;
151 prev_annot_ = ss.str();
160 std::ostringstream ss;
162 if((ss.str() != prev_annot_) && !record_closed_)
170 prev_annot_ = ss.str();
171 if(!prev_annot_.empty() && record_closed_) {
173 record_closed_ =
false;
204 if(
nullptr == collected_object_) {
218 if(
nullptr == collected_object_) {
229 if(!record_closed_) {
230 argos_record_.flags |= CONTINUE_FLAG;
232 argos_record_.flags &= ~CONTINUE_FLAG;
239 void closeRecord(
const bool & simulation_ending =
false) override final
243 if(!record_closed_ && writeRecord_(simulation_ending)) {
246 record_closed_ =
true;
253 auto_collect_ =
false;
267 bool writeRecord_(
bool simulation_ending =
false)
270 "Must startCollecting_ on this Collectable "
271 <<
getLocation() <<
" before a record can be written");
283 argos_record_.length =
static_cast<uint16_t
>(prev_annot_.size());
287 argos_record_.annt = prev_annot_;
290 argos_record_.time_End =
296 sparta_assert(argos_record_.time_Start < argos_record_.time_End);
305 void startNewRecord_() {
312 void setCollecting_(
bool collect, Collector * collector)
override final
314 pipeline_col_ =
dynamic_cast<PipelineCollector *
>(collector);
316 "Collectables can only added to PipelineCollectors... for now");
318 if(
collect && !prev_annot_.empty()) {
326 if(collected_object_ && auto_collect_) {
340 if(!
collect && !record_closed_) {
347 const DataT * collected_object_ =
nullptr;
350 annotation_t argos_record_;
354 std::string prev_annot_;
357 PipelineCollector * pipeline_col_ =
nullptr;
365 bool record_closed_ =
true;
368 bool auto_collect_ =
true;
383 template<
typename DataT, SchedulingPhase collection_phase,
typename>
389 static uint64_t getUniquePairID_() {
390 static uint64_t
id = 0;
439 template<
typename DataT, SchedulingPhase collection_phase>
441 MetaStruct::enable_if_t<
442 std::is_base_of<sparta::PairDefinition<MetaStruct::remove_any_pointer_t<DataT>>,
443 typename MetaStruct::remove_any_pointer_t<DataT>::SpartaPairDefinitionType>::value>> :
444 public sparta::PairCollector<typename MetaStruct::remove_any_pointer_t<DataT>::SpartaPairDefinitionType>,
public CollectableTreeNode
450 typedef typename Data_t::SpartaPairDefinitionType PairDef_t;
453 using PairCollector<PairDef_t>::getNameStrings;
454 using PairCollector<PairDef_t>::getDataVector;
455 using PairCollector<PairDef_t>::getStringVector;
456 using PairCollector<PairDef_t>::getFormatVector;
457 using PairCollector<PairDef_t>::getSizeOfVector;
458 using PairCollector<PairDef_t>::getPEventLogVector;
459 using PairCollector<PairDef_t>::getArgosFormatGuide;
460 using PairCollector<PairDef_t>::collect_;
461 using PairCollector<PairDef_t>::isCollecting;
473 const std::string& name,
474 const std::string& group,
476 uint64_t parentid = 0,
477 const std::string & desc =
"Collectable <manual, no desc>") :
478 sparta::PairCollector<PairDef_t>(),
480 argos_record_(pair_t(0, 1, parentid, 0, BAD_DISPLAY_ID,
481 boost::numeric::converter<decltype(argos_record_.location_ID),
485 ev_close_record_(&event_set_, name +
"_pipeline_collectable_close_event",
487 static constexpr auto MAX_UID = std::numeric_limits<
decltype(argos_record_.location_ID)>::max();
489 "Tree has at least " <<
getNodeUID() <<
" in it. Because pipeouts "
490 "use these locations and only have 32b location IDs, the pipeline "
491 "collection system imposes a limit of " << MAX_UID
492 <<
" nodes in the tree. This is expected to be an unattainable number "
493 "without some kind of runaway allocation bug. If you are sure you "
494 "need more nodes than this, contact the SPARTA team. In the meantime, "
495 "it is probably safe to comment out this assertion if you do not "
496 "plan to use the pipeline collection functionality");
509 const std::string& name,
510 const DataT * collected_object,
511 uint64_t parentid = 0,
512 const std::string & desc =
"Collectable <no desc>") :
519 collected_object_ = collected_object;
522 if(collected_object) {
535 const std::string& name,
536 uint64_t parentid = 0,
537 const std::string & desc =
"Collectable <manual, no desc>") :
552 MetaStruct::enable_if_t<!MetaStruct::is_any_pointer<T>::value,
void>
564 MetaStruct::enable_if_t<MetaStruct::is_any_pointer<T>::value,
void>
575 MetaStruct::enable_if_t<!MetaStruct::is_any_pointer<T>::value,
void>
582 if(!isSameRecord() && !record_closed_)
593 if(record_closed_ && hasData_()){
595 record_closed_ =
false;
602 template <
typename T>
603 MetaStruct::enable_if_t<MetaStruct::is_any_pointer<T>::value,
void>
624 MetaStruct::enable_if_t<!MetaStruct::is_any_pointer<T>::value,
void>
646 MetaStruct::enable_if_t<MetaStruct::is_any_pointer<T>::value,
void>
661 if(
nullptr == collected_object_) {
675 if(
nullptr == collected_object_) {
687 if(!record_closed_) {
688 argos_record_.flags |= CONTINUE_FLAG;
690 argos_record_.flags &= ~CONTINUE_FLAG;
697 void closeRecord(
const bool & simulation_ending =
false) override final
701 if(!record_closed_ && writeRecord_(simulation_ending)) {
704 argos_record_.valueVector.clear();
705 argos_record_.stringVector.clear();
707 record_closed_ =
true;
714 auto_collect_ =
false;
720 return (argos_record_.valueVector == getDataVector()) && (argos_record_.stringVector == getStringVector());
728 std::ostringstream ss;
729 for(
const auto & pairs : getPEventLogVector()){
730 ss << pairs.first <<
"(" << pairs.second <<
") ";
732 log_string_ = ss.str();
761 inline static uint64_t getUniquePairID_() {
762 static uint64_t
id = 0;
764 id = sparta::collection::UniquePairIDGenerator::getUniquePairID_();
772 void updateLastRecord_(){
774 argos_record_.valueVector = getDataVector();
775 argos_record_.stringVector = getStringVector();
776 argos_record_.sizeOfVector = getSizeOfVector();
778 if (has_display_id_field_) {
779 argos_record_.display_ID = argos_record_.valueVector[0].first & 0x0fff;
784 bool hasData_()
const {
785 return !(argos_record_.valueVector.empty() && argos_record_.stringVector.empty());
790 bool writeRecord_(
bool simulation_ending =
false)
793 "Must startCollecting_ on this Collectable "
794 <<
getLocation() <<
" before a record can be written");
804 argos_record_.pairId = getUniquePairID_();
807 argos_record_.time_End =
813 sparta_assert(argos_record_.time_Start < argos_record_.time_End);
821 void startNewRecord_() {
828 void setCollecting_(
bool collect, Collector * collector)
override final
830 pipeline_col_ =
dynamic_cast<PipelineCollector *
>(collector);
832 "Collectables can only added to PipelineCollectors... for now");
836 argos_record_.nameVector = getNameStrings();
837 argos_record_.length = argos_record_.nameVector.size();
838 has_display_id_field_ = (argos_record_.nameVector[0] ==
"DID");
839 for(
const auto formatter: getFormatVector()) {
840 argos_record_.delimVector.emplace_back(formatter);
852 if(collected_object_ && auto_collect_) {
869 const DataT * collected_object_ =
nullptr;
872 pair_t argos_record_;
875 PipelineCollector * pipeline_col_ =
nullptr;
883 bool record_closed_ =
true;
886 bool auto_collect_ =
true;
889 bool has_display_id_field_ =
false;
891 std::string log_string_;
File that defines the EventSet class.
File that defines the PayloadEvent class.
Class to facilitate pipeline collection operations.
File that defines the phases used in simulation.
#define sparta_assert(...)
Simple variadic assertion that will throw a sparta_exception if the condition fails.
#define SPARTA_EXPECT_FALSE(x)
A macro for hinting to the compiler a particular condition should be considered most likely false.
#define CREATE_SPARTA_HANDLER_WITH_DATA(clname, meth, dataT)
Set of Events that a unit (or sparta::TreeNode, sparta::Resource) contains and are visible through a ...
Class to schedule a Scheduleable in the future with a payload, typed on both the data type and the sc...
ScheduleableHandle preparePayload(const DataT &payload)
Prepare a Scheduleable Payload for scheduling either now or later.
void schedule()
Schedule this event with its pre-set delay using the pre-set Clock.
Tick getCurrentTick() const noexcept
The current tick the Scheduler is working on or just finished.
Node in a composite tree representing a sparta Tree item.
static const group_idx_type GROUP_IDX_NONE
GroupIndex indicating that a node has no group index because it belongs to no group.
node_uid_type getNodeUID() const
Gets the unique ID of this node.
std::string getLocation() const override final
static constexpr char GROUP_NAME_NONE[]
Group name indicating that a node belongs to no group.
An abstract type of TreeNode that has virtual calls to start collection on this node,...
bool isCollected() const
Determine whether or not this node has collection turned on or off.
Class used to either manually or auto-collect an Annotation String object in a pipeline database.
virtual ~Collectable()
Virtual destructor – does nothing.
void collect(const DataT &val)
void setManualCollection()
Do not perform any automatic collection The SchedulingPhase is ignored.
void restartRecord() override final
void collect() override final
void collectWithDuration(const DataT &val, sparta::Clock::Cycle duration)
Explicitly collect a value for the given duration.
void closeRecord(const bool &simulation_ending=false) override final
void initialize(const DataT &val)
For manual collection, provide an initial value.
Collectable(sparta::TreeNode *parent, const std::string &name, const std::string &group, uint32_t index, uint64_t parentid=0, const std::string &desc="Collectable <manual, no desc>")
Construct the Collectable, no data object associated, part of a group.
EventSet & getEventSet_()
Get a reference to the internal event set.
Collectable(sparta::TreeNode *parent, const std::string &name, uint64_t parentid=0, const std::string &desc="Collectable <manual, no desc>")
Construct the Collectable, no data object associated.
void collectWithDuration(sparta::Clock::Cycle duration)
Calls collectWithDuration using the internal collected_object_ specified at construction.
Collectable(sparta::TreeNode *parent, const std::string &name, const DataT *collected_object, uint64_t parentid=0, const std::string &desc="Collectable <no desc>")
Construct the Collectable.
uint64_t getUniqueTransactionId()
Return a unique transaction id using a dummy counter.
void writeRecord(const R_Type &dat)
Output a finized transaction to our Outputter class.
void removeFromAutoCollection(CollectableTreeNode *ctn)
Remove the given CollectableTreeNode from collection.
void addToAutoCollection(CollectableTreeNode *ctn, SchedulingPhase collection_phase=SchedulingPhase::Tick)
Add the CollectableTreeNode to auto collection.
Scheduler * getScheduler() const
Macros for handling exponential backoff.
T * notNull(T *p)
Ensures that a pointer is not null.