SST  6.1.0
StructuralSimulationToolkit
componentregisterstat_impl.h
1 // Copyright 2009-2016 Sandia Corporation. Under the terms
2 // of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S.
3 // Government retains certain rights in this software.
4 //
5 // Copyright (c) 2009-2016, Sandia Corporation
6 // All rights reserved.
7 //
8 // This file is part of the SST software package. For license
9 // information, see the LICENSE file in the top level directory of the
10 // distribution.
11 
12 
13 #ifndef _H_SST_CORE_COMP_REG_STAT__
14 #define _H_SST_CORE_COMP_REG_STAT__
15 
16 // THIS IS THE IMPLEMENTATION OF Component::registerStatistic(...) code.
17 // It is placed in this implemenation file to provide a clean interface for
18 // the class Component.
19 
20 //template <typename T>
21 //Statistic<T>* registerStatisticCore(std::string statName, std::string statSubId = 0)
22 //{
23  std::string fullStatName;
24  bool statGood = true;
25  bool nameFound = false;
26  StatisticBase::StatMode_t statCollectionMode = StatisticBase::STAT_MODE_COUNT;
27  Simulation::statEnableList_t* statEnableList;
28  Simulation::statParamsList_t* statParamsList;
29  Output out = Simulation::getSimulation()->getSimulationOutput();
30  UnitAlgebra collectionRate;
31  UnitAlgebra startAtTime;
32  UnitAlgebra stopAtTime;
33  Params statParams;
34  std::string statRateParam;
35  std::string statTypeParam;
36  std::string statStartAtTimeParam;
37  std::string statStopAtTimeParam;
38  Statistic<T>* statistic = NULL;
39 
40  // Check to see if the Statistic is previously registered with the Statistics Engine
41  StatisticBase* prevStat = Simulation::getSimulation()->getStatisticsProcessingEngine()->isStatisticRegisteredWithEngine<T>(getName(), getId(), statName, statSubId);
42  if (NULL != prevStat) {
43  // Dynamic cast the base stat to the expected type
44  return dynamic_cast<Statistic<T>*>(prevStat);
45  }
46 
47  // Build a name to report errors against
48  fullStatName = StatisticBase::buildStatisticFullName(getName().c_str(), statName, statSubId);
49 
50  // Make sure that the wireup has not been completed
51  if (true == Simulation::getSimulation()->isWireUpFinished()) {
52  // We cannot register statistics AFTER the wireup (after all components have been created)
53  fprintf(stderr, "ERROR: Statistic %s - Cannot be registered after the Components have been wired up. Statistics must be registered on Component creation.; exiting...\n", fullStatName.c_str());
54  exit(1);
55  }
56 
57  // // Verify here that name of the stat is one of the registered
58  // // names of the component's ElementInfoStatistic.
59  // if (false == doesComponentInfoStatisticExist(statName)) {
60  // fprintf(stderr, "Error: Statistic %s name %s is not found in ElementInfoStatistic, exiting...\n", fullStatName.c_str(), statName.c_str());
61  // exit(1);
62  // }
63 
64  // Get Component Statistic Information from the ConfigGraph data
65  statEnableList = Simulation::getSimulation()->getComponentStatisticEnableList(getId());
66  statParamsList = Simulation::getSimulation()->getComponentStatisticParamsList(getId());
67 
68  // Check each entry in the StatEnableList (from the ConfigGraph via the
69  // Python File) to see if this Statistic is enabled, then check any of
70  // its critical parameters
71  for (uint32_t x = 0; x < statEnableList->size(); x++) {
72  // First check to see if the any entry in the StatEnableList matches
73  // the Statistic Name or the STATALLFLAG. If so, then this Statistic
74  // will be enabled. Then check any critical parameters
75  if ((std::string(STATALLFLAG) == statEnableList->at(x)) || (statName == statEnableList->at(x))) {
76  // Identify what keys are Allowed in the parameters
77  Params::KeySet_t allowedKeySet;
78  allowedKeySet.insert("type");
79  allowedKeySet.insert("rate");
80  allowedKeySet.insert("startat");
81  allowedKeySet.insert("stopat");
82  statParamsList->at(x).pushAllowedKeys(allowedKeySet);
83 
84  // We found an acceptible name... Now check its critical Parameters
85  // Note: If parameter not found, defaults will be provided
86  statTypeParam = statParamsList->at(x).find<std::string>("type", "sst.AccumulatorStatistic");
87  statRateParam = statParamsList->at(x).find<std::string>("rate", "0ns");
88  statStartAtTimeParam = statParamsList->at(x).find<std::string>("startat", "0ns");
89  statStopAtTimeParam = statParamsList->at(x).find<std::string>("stopat", "0ns");
90 
91  // Check for an empty string on the collection rate and start/stop times
92  if (true == statRateParam.empty()) {
93  statRateParam = "0ns";
94  }
95  if (true == statStartAtTimeParam.empty()) {
96  statStartAtTimeParam = "0ns";
97  }
98  if (true == statStopAtTimeParam.empty()) {
99  statStopAtTimeParam = "0ns";
100  }
101 
102  collectionRate = UnitAlgebra(statRateParam);
103  startAtTime = UnitAlgebra(statStartAtTimeParam);
104  stopAtTime = UnitAlgebra(statStopAtTimeParam);
105  statParams = statParamsList->at(x);
106  nameFound = true;
107  break;
108  }
109  }
110 
111  // Did we find a matching enable name?
112  if (false == nameFound) {
113  statGood = false;
114  out.verbose(CALL_INFO, 1, 0, " Warning: Statistic %s is not enabled in python script, statistic will not be enabled...\n", fullStatName.c_str());
115  }
116 
117  if (true == statGood) {
118  // Check that the Collection Rate is a valid unit type that we can use
119  if ((true == collectionRate.hasUnits("s")) ||
120  (true == collectionRate.hasUnits("hz")) ) {
121  // Rate is Periodic Based
122  statCollectionMode = StatisticBase::STAT_MODE_PERIODIC;
123  } else if (true == collectionRate.hasUnits("event")) {
124  // Rate is Count Based
125  statCollectionMode = StatisticBase::STAT_MODE_COUNT;
126  } else if (0 == collectionRate.getValue()) {
127  // Collection rate is zero and has no units, so make up a periodic flavor
128  collectionRate = UnitAlgebra("0ns");
129  statCollectionMode = StatisticBase::STAT_MODE_PERIODIC;
130  } else {
131  // collectionRate is a unit type we dont recognize
132  fprintf(stderr, "ERROR: Statistic %s - Collection Rate = %s not valid; exiting...\n", fullStatName.c_str(), collectionRate.toString().c_str());
133  exit(1);
134  }
135 
136  // Check the startat and stopat is in units of seconds
137  if ((true != startAtTime.hasUnits("s")) || (true != stopAtTime.hasUnits("s"))) {
138  // startat or stopat has a unit type we dont allow
139  fprintf(stderr, "ERROR: Statistic %s - param startat = %s; stopat = %s must both be in units of seconds; exiting...\n", fullStatName.c_str(), startAtTime.toString().c_str(), stopAtTime.toString().c_str());
140  exit(1);
141  }
142  }
143 
144  if (true == statGood) {
145  // Instantiate the Statistic here defined by the type here
146  statistic = CreateStatistic<T>(this, statTypeParam, statName, statSubId, statParams);
147  if (NULL == statistic) {
148  fprintf(stderr, "ERROR: Unable to instantiate Statistic %s; exiting...\n", fullStatName.c_str());
149  exit(1);
150  }
151 
152  // Check that the statistic supports this collection rate
153  if (false == statistic->isStatModeSupported(statCollectionMode)) {
154  if (StatisticBase::STAT_MODE_PERIODIC == statCollectionMode) {
155  out.verbose(CALL_INFO, 1, 0, " Warning: Statistic %s Does not support Periodic Based Collections; Collection Rate = %s\n", fullStatName.c_str(), collectionRate.toString().c_str());
156  } else {
157  out.verbose(CALL_INFO, 1, 0, " Warning: Statistic %s Does not support Event Based Collections; Collection Rate = %s\n", fullStatName.c_str(), collectionRate.toString().c_str());
158  }
159  statGood = false;
160  }
161 
162  // Tell the Statistic what collection mode it is in
163  statistic->setRegisteredCollectionMode(statCollectionMode);
164  }
165 
166  // If Stat is good, Add it to the Statistic Processing Engine
167  if (true == statGood) {
168  // Check the Statistics Enable Level vs the system Load Level to decide
169  // if this statistic can be used.
170  uint8_t enableLevel = getComponentInfoStatisticEnableLevel(statistic->getStatName());
171  uint8_t loadLevel = Simulation::getStatisticsOutput()->getStatisticLoadLevel();
172  if (0 == loadLevel) {
173  out.verbose(CALL_INFO, 1, 0, " Warning: Statistic Load Level = 0 (all statistics disabled); statistic %s is disabled...\n", fullStatName.c_str());
174  statGood = false;
175  // } else if (0 == enableLevel) {
176  // out.verbose(CALL_INFO, 1, 0, " Warning: Statistic %s Enable Level = %d, statistic is disabled by the ElementInfoStatistic...\n", fullStatName.c_str(), enableLevel);
177  // statGood = false;
178  } else if (enableLevel > loadLevel) {
179  out.verbose(CALL_INFO, 1, 0, " Warning: Load Level %d is too low to enable Statistic %s with Enable Level %d, statistic will not be enabled...\n", loadLevel, fullStatName.c_str(), enableLevel);
180  statGood = false;
181  }
182  }
183 
184  // If Stat is good, Add it to the Statistic Processing Engine
185  if (true == statGood) {
186  // If the mode is Periodic Based, the add the statistic to the
187  // StatisticProcessingEngine otherwise add it as an Event Based Stat.
188  if (StatisticBase::STAT_MODE_PERIODIC == statCollectionMode) {
189  if (false == Simulation::getSimulation()->getStatisticsProcessingEngine()->addPeriodicBasedStatistic(collectionRate, statistic)) {
190  statGood = false;
191  }
192  } else {
193  if (false == Simulation::getSimulation()->getStatisticsProcessingEngine()->addEventBasedStatistic(collectionRate, statistic)) {
194  statGood = false;
195  }
196  }
197  }
198 
199  // If Stats are still good, register its fields and
200  // add it to the array of registered statistics.
201  if (true == statGood) {
202  // The passed in Statistic is OK to use, register its fields
203  StatisticOutput* statOutput = Simulation::getSimulation()->getStatisticsOutput();
204  statOutput->startRegisterFields(statistic);
205  statistic->registerOutputFields(statOutput);
206  statOutput->stopRegisterFields();
207 
208  // Set the start / stop times for the stat
209  Simulation::getSimulation()->getStatisticsProcessingEngine()->setStatisticStartTime(startAtTime, statistic);
210  Simulation::getSimulation()->getStatisticsProcessingEngine()->setStatisticStopTime(stopAtTime, statistic);
211  } else {
212  // Delete the original statistic (if created), and return a NULL statistic instead
213  if (NULL != statistic) {
214  delete statistic;
215  }
216 
217  // Instantiate the Statistic here defined by the type here
218  statTypeParam = "sst.NullStatistic";
219  statistic = CreateStatistic<T>(this, statTypeParam, statName, statSubId, statParams);
220  if (NULL == statistic) {
221  statGood = false;
222  fprintf(stderr, "ERROR: Unable to instantiate Null Statistic %s; exiting...\n", fullStatName.c_str());
223  exit(1);
224  }
225  }
226 
227  // Register the new Statistic with the Statistic Engine
228  Simulation::getSimulation()->getStatisticsProcessingEngine()->registerStatisticWithEngine<T>(getId(), statistic);
229  return statistic;
230 //}
231 
232 #endif //_H_SST_CORE_COMP_REG_STAT__