SST  12.0.1
StructuralSimulationToolkit
factory.h
1 // Copyright 2009-2022 NTESS. Under the terms
2 // of Contract DE-NA0003525 with NTESS, the U.S.
3 // Government retains certain rights in this software.
4 //
5 // Copyright (c) 2009-2022, NTESS
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 #ifndef SST_CORE_FACTORY_H
13 #define SST_CORE_FACTORY_H
14 
15 #include "sst/core/eli/elementinfo.h"
16 #include "sst/core/params.h"
17 #include "sst/core/sst_types.h"
18 
19 #include <mutex>
20 #include <stdio.h>
21 
22 /* Forward declare for Friendship */
23 extern int main(int argc, char** argv);
24 
25 namespace SST {
26 namespace Statistics {
27 class StatisticOutput;
28 class StatisticBase;
29 } // namespace Statistics
30 
31 class Module;
32 class Component;
33 class BaseComponent;
34 class SubComponent;
35 class ElemLoader;
36 class SSTElementPythonModule;
37 
38 /**
39  * Class for instantiating Components, Links and the like out
40  * of element libraries.
41  */
42 class Factory
43 {
44 public:
45  static Factory* getFactory() { return instance; }
46 
47  /** Get a list of allowed ports for a given component type.
48  * @param type - Name of component in lib.name format
49  * @return True if this is a valid portname
50  */
51  bool isPortNameValid(const std::string& type, const std::string& port_name);
52 
53  /** Get a list of allowed param keys for a given component type.
54  * @param type - Name of component in lib.name format
55  * @return True if this is a valid portname
56  */
57  const Params::KeySet_t& getParamNames(const std::string& type);
58 
59  /** Attempt to create a new Component instantiation
60  * @param id - The unique ID of the component instantiation
61  * @param componentname - The fully qualified elementlibname.componentname type of component
62  * @param params - The params to pass to the component's constructor
63  * @return Newly created component
64  */
65  Component* CreateComponent(ComponentId_t id, const std::string& componentname, Params& params);
66 
67  /** Ensure that an element library containing the required event is loaded
68  * @param eventname - The fully qualified elementlibname.eventname type
69  */
70  void RequireEvent(const std::string& eventname);
71 
72  /** Instantiate a new Module
73  * @param type - Fully qualified elementlibname.modulename type
74  * @param params - Parameters to pass to the Module's constructor
75  */
76  Module* CreateModule(const std::string& type, Params& params);
77 
78  /** Instantiate a new Module
79  * @param type - Fully qualified elementlibname.modulename type
80  * @param comp - Component instance to pass to the Module's constructor
81  * @param params - Parameters to pass to the Module's constructor
82  */
83  Module* CreateModuleWithComponent(const std::string& type, Component* comp, Params& params);
84 
85  bool doesSubComponentExist(const std::string& type);
86 
87  /** Return partitioner function
88  * @param name - Fully qualified elementlibname.partitioner type name
89  */
91  CreatePartitioner(const std::string& name, RankInfo total_ranks, RankInfo my_rank, int verbosity);
92 
93  /**
94  Check to see if a given element type is loadable with a particular API
95  @param name - Name of element to check in lib.name format
96  @return True if loadable as the API specified as the template parameter
97  */
98  template <class Base>
99  bool isSubComponentLoadableUsingAPI(const std::string& type)
100  {
101  std::string elemlib, elem;
102  std::tie(elemlib, elem) = parseLoadName(type);
103 
104  requireLibrary(elemlib);
105  std::lock_guard<std::recursive_mutex> lock(factoryMutex);
106 
107  auto* lib = ELI::InfoDatabase::getLibrary<Base>(elemlib);
108  if ( lib ) {
109  auto map = lib->getMap();
110  auto* info = lib->getInfo(elem);
111  if ( info ) {
112  auto* builderLib = Base::getBuilderLibrary(elemlib);
113  if ( builderLib ) {
114  auto* fact = builderLib->getBuilder(elem);
115  if ( fact ) { return true; }
116  }
117  }
118  }
119  return false;
120  }
121 
122  template <class Base, int index, class InfoType>
123  const InfoType& getSimpleInfo(const std::string& type)
124  {
125  static InfoType invalid_ret;
126  std::string elemlib, elem;
127  std::tie(elemlib, elem) = parseLoadName(type);
128 
129  std::stringstream err_os;
130  requireLibrary(elemlib, err_os);
131  std::lock_guard<std::recursive_mutex> lock(factoryMutex);
132 
133  auto* lib = ELI::InfoDatabase::getLibrary<Base>(elemlib);
134  if ( lib ) {
135  auto* info = lib->getInfo(elem);
136  if ( info ) {
137  // Need to cast this to a ProvidesSimpleInfo to get
138  // the templated data
139  auto* cast_info = dynamic_cast<ELI::ProvidesSimpleInfo<index, InfoType>*>(info);
140  if ( cast_info ) { return cast_info->getSimpleInfo(); }
141  }
142  }
143  // notFound(Base::ELI_baseName(), type, err_os.str());
144  return invalid_ret;
145  }
146 
147  /**
148  * General function to create a given base class.
149  *
150  * @param type
151  * @param params
152  * @param args Constructor arguments
153  */
154  template <class Base, class... CtorArgs>
155  Base* Create(const std::string& type, CtorArgs&&... args)
156  {
157  std::string elemlib, elem;
158  std::tie(elemlib, elem) = parseLoadName(type);
159 
160  std::stringstream err_os;
161  requireLibrary(elemlib, err_os);
162  std::lock_guard<std::recursive_mutex> lock(factoryMutex);
163 
164  auto* lib = ELI::InfoDatabase::getLibrary<Base>(elemlib);
165  if ( lib ) {
166  auto* info = lib->getInfo(elem);
167  if ( info ) {
168  auto* builderLib = Base::getBuilderLibrary(elemlib);
169  if ( builderLib ) {
170  auto* fact = builderLib->getBuilder(elem);
171  if ( fact ) {
172  Base* ret = fact->create(std::forward<CtorArgs>(args)...);
173  return ret;
174  }
175  }
176  }
177  }
178  notFound(Base::ELI_baseName(), type, err_os.str());
179  return nullptr;
180  }
181 
182  /**
183  * General function to create a given base class. This version
184  * should be used if a Params object is being passed in and you
185  * need the system to populate the allowed keys for the object.
186  * If you don't need the allowed keys to be populated, just use
187  * the Create() bunction.
188  *
189  * @param type
190  * @param params
191  * @param args Constructor arguments
192  */
193  template <class Base, class... CtorArgs>
194  Base* CreateWithParams(const std::string& type, SST::Params& params, CtorArgs&&... args)
195  {
196  std::string elemlib, elem;
197  std::tie(elemlib, elem) = parseLoadName(type);
198 
199  std::stringstream err_os;
200  requireLibrary(elemlib, err_os);
201  std::lock_guard<std::recursive_mutex> lock(factoryMutex);
202 
203  auto* lib = ELI::InfoDatabase::getLibrary<Base>(elemlib);
204  if ( lib ) {
205  auto map = lib->getMap();
206  auto* info = lib->getInfo(elem);
207  if ( info ) {
208  auto* builderLib = Base::getBuilderLibrary(elemlib);
209  if ( builderLib ) {
210  auto* fact = builderLib->getBuilder(elem);
211  if ( fact ) {
212  params.pushAllowedKeys(info->getParamNames());
213  Base* ret = fact->create(std::forward<CtorArgs>(args)...);
214  params.popAllowedKeys();
215  return ret;
216  }
217  }
218  }
219  }
220  notFound(Base::ELI_baseName(), type, err_os.str());
221  return nullptr;
222  }
223 
224  /** Instantiate a new Statistic
225  * @param comp - Owning component
226  * @param type - Fully qualified elementlibname.statisticname type
227  * @param statName - Name of the statistic
228  * @param statSubId - Name of the sub statistic
229  * @param params - Parameters to pass to the Statistics's constructor
230  * @param fieldType - Type of data stored in statistic
231  */
232  template <class T, class... Args>
234  const std::string& type, BaseComponent* comp, const std::string& statName, const std::string& stat,
235  Params& params, Args... args)
236  {
237  std::string elemlib, elem;
238  std::tie(elemlib, elem) = parseLoadName(type);
239  // ensure library is already loaded...
240  std::stringstream sstr;
241  requireLibrary(elemlib, sstr);
242 
243  auto* lib = ELI::BuilderDatabase::getLibrary<Statistics::Statistic<T>, Args...>(elemlib);
244  if ( lib ) {
245  auto* fact = lib->getFactory(elem);
246  if ( fact ) { return fact->create(comp, statName, stat, params, std::forward<Args>(args)...); }
247  }
248  // If we make it to here, component not found
249  out.fatal(CALL_INFO, -1, "can't find requested statistic %s.\n%s\n", type.c_str(), sstr.str().c_str());
250  return nullptr;
251  }
252 
253  /** Return Python Module creation function
254  * @param name - Fully qualified elementlibname.pythonModName type name
255  */
256  SSTElementPythonModule* getPythonModule(const std::string& name);
257 
258  /**
259  * @brief hasLibrary Checks to see if library exists and can be loaded
260  * @param elemlib
261  * @param err_os Stream to print error messages to
262  * @return whether the library was found
263  */
264  bool hasLibrary(const std::string& elemlib, std::ostream& err_os);
265  void requireLibrary(const std::string& elemlib, std::ostream& err_os);
266  /**
267  * @brief requireLibrary Throws away error messages
268  * @param elemlib
269  */
270  void requireLibrary(const std::string& elemlib);
271 
272  void getLoadedLibraryNames(std::set<std::string>& lib_names);
273  void loadUnloadedLibraries(const std::set<std::string>& lib_names);
274 
275  /** Determine if a SubComponentSlot is defined in a components ElementInfoStatistic
276  * @param type - The name of the component/subcomponent
277  * @param slotName - The name of the SubComponentSlot
278  * @return True if the SubComponentSlot is defined in the component's ELI
279  */
280  bool DoesSubComponentSlotExist(const std::string& type, const std::string& slotName);
281 
282  /** Determine if a statistic is defined in a components ElementInfoStatistic
283  * @param type - The name of the component
284  * @param statisticName - The name of the statistic
285  * @return True if the statistic is defined in the component's ElementInfoStatistic
286  */
287  bool DoesComponentInfoStatisticNameExist(const std::string& type, const std::string& statisticName);
288 
289  const std::vector<std::string>& GetValidStatistics(const std::string& compType);
290 
291  /** Get the enable level of a statistic defined in the component's ElementInfoStatistic
292  * @param componentname - The name of the component
293  * @param statisticName - The name of the statistic
294  * @return The Enable Level of the statistic from the ElementInfoStatistic
295  */
296  uint8_t GetComponentInfoStatisticEnableLevel(const std::string& type, const std::string& statisticName);
297 
298  /** Get the units of a statistic defined in the component's ElementInfoStatistic
299  * @param componentname - The name of the component
300  * @param statisticName - The name of the statistic
301  * @return The units string of the statistic from the ElementInfoStatistic
302  */
303  std::string GetComponentInfoStatisticUnits(const std::string& type, const std::string& statisticName);
304 
305 private:
306  friend int ::main(int argc, char** argv);
307 
308  void notFound(const std::string& baseName, const std::string& type, const std::string& errorMsg);
309 
310  Factory(const std::string& searchPaths);
311  ~Factory();
312 
313  Factory(); // Don't Implement
314  Factory(Factory const&); // Don't Implement
315  void operator=(Factory const&); // Don't Implement
316 
317  static Factory* instance;
318 
319  // find library information for name
320  bool findLibrary(const std::string& name, std::ostream& err_os = std::cerr);
321  // handle low-level loading of name
322  bool loadLibrary(const std::string& name, std::ostream& err_os = std::cerr);
323 
324  std::set<std::string> loaded_libraries;
325 
326  std::string searchPaths;
327 
328  ElemLoader* loader;
329  std::string loadingComponentType;
330 
331  std::pair<std::string, std::string> parseLoadName(const std::string& wholename);
332 
333  std::recursive_mutex factoryMutex;
334 
335 protected:
336  Output& out;
337 };
338 
339 } // namespace SST
340 
341 #endif // SST_CORE_FACTORY_H
Output object provides consistent method for outputting data to stdout, stderr and/or sst debug file...
Definition: output.h:51
Module * CreateModule(const std::string &type, Params &params)
Instantiate a new Module.
Definition: factory.cc:390
void pushAllowedKeys(const KeySet_t &keys)
Definition: params.cc:203
bool isSubComponentLoadableUsingAPI(const std::string &type)
Check to see if a given element type is loadable with a particular API.
Definition: factory.h:99
Base * Create(const std::string &type, CtorArgs &&...args)
General function to create a given base class.
Definition: factory.h:155
Main component object for the simulation.
Definition: component.h:30
bool DoesComponentInfoStatisticNameExist(const std::string &type, const std::string &statisticName)
Determine if a statistic is defined in a components ElementInfoStatistic.
Definition: factory.cc:307
SSTElementPythonModule * getPythonModule(const std::string &name)
Return Python Module creation function.
Definition: factory.cc:532
Forms the template defined base class for statistics gathering within SST.
Definition: elementinfo.h:42
std::string GetComponentInfoStatisticUnits(const std::string &type, const std::string &statisticName)
Get the units of a statistic defined in the component&#39;s ElementInfoStatistic.
Definition: factory.cc:361
Base * CreateWithParams(const std::string &type, SST::Params &params, CtorArgs &&...args)
General function to create a given base class.
Definition: factory.h:194
Definition: simpleInfo.h:82
bool hasLibrary(const std::string &elemlib, std::ostream &err_os)
hasLibrary Checks to see if library exists and can be loaded
Definition: factory.cc:558
Module is a tag class used with the loadModule function.
Definition: module.h:21
Class to load Element Libraries.
Definition: elemLoader.h:23
uint8_t GetComponentInfoStatisticEnableLevel(const std::string &type, const std::string &statisticName)
Get the enable level of a statistic defined in the component&#39;s ElementInfoStatistic.
Definition: factory.cc:317
Component * CreateComponent(ComponentId_t id, const std::string &componentname, Params &params)
Attempt to create a new Component instantiation.
Definition: factory.cc:189
void fatal(uint32_t line, const char *file, const char *func, int exit_code, const char *format,...) const
Output the fatal message with formatting as specified by the format parameter.
Definition: output.cc:155
Partition::SSTPartitioner * CreatePartitioner(const std::string &name, RankInfo total_ranks, RankInfo my_rank, int verbosity)
Return partitioner function.
Definition: factory.cc:499
void RequireEvent(const std::string &eventname)
Ensure that an element library containing the required event is loaded.
Definition: factory.cc:488
Definition: rankInfo.h:21
Main component object for the simulation.
Definition: baseComponent.h:49
const Params::KeySet_t & getParamNames(const std::string &type)
Get a list of allowed param keys for a given component type.
Definition: factory.cc:150
Base class for Partitioning graphs.
Definition: sstpart.h:31
Parameter store.
Definition: params.h:55
Module * CreateModuleWithComponent(const std::string &type, Component *comp, Params &params)
Instantiate a new Module.
Definition: factory.cc:430
void popAllowedKeys()
Removes the most recent set of keys considered allowed.
Definition: params.cc:209
Class for instantiating Components, Links and the like out of element libraries.
Definition: factory.h:42
Base class for python modules in element libraries.
Definition: element_python.h:128
std::set< key_type, KeyCompare > KeySet_t
Definition: params.h:233
bool isPortNameValid(const std::string &type, const std::string &port_name)
Get a list of allowed ports for a given component type.
Definition: factory.cc:99
Statistics::Statistic< T > * CreateStatistic(const std::string &type, BaseComponent *comp, const std::string &statName, const std::string &stat, Params &params, Args...args)
Instantiate a new Statistic.
Definition: factory.h:233
bool DoesSubComponentSlotExist(const std::string &type, const std::string &slotName)
Determine if a SubComponentSlot is defined in a components ElementInfoStatistic.
Definition: factory.cc:227