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