SST 12.1.0
Structural Simulation Toolkit
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 */
23extern int main(int argc, char** argv);
24
25namespace SST {
26namespace Statistics {
27class StatisticOutput;
28class StatisticBase;
29} // namespace Statistics
30
31class Module;
32class Component;
33class BaseComponent;
34class SubComponent;
35class ElemLoader;
36class SSTElementPythonModule;
37
38/**
39 * Class for instantiating Components, Links and the like out
40 * of element libraries.
41 */
43{
44public:
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 template <class T, class... ARGS>
183 T* CreateProfileTool(const std::string& type, ARGS... args)
184 {
185 return Factory::getFactory()->Create<T>(type, args...);
186 }
187
188 /**
189 * General function to create a given base class. This version
190 * should be used if a Params object is being passed in and you
191 * need the system to populate the allowed keys for the object.
192 * If you don't need the allowed keys to be populated, just use
193 * the Create() bunction.
194 *
195 * @param type
196 * @param params
197 * @param args Constructor arguments
198 */
199 template <class Base, class... CtorArgs>
200 Base* CreateWithParams(const std::string& type, SST::Params& params, CtorArgs&&... args)
201 {
202 std::string elemlib, elem;
203 std::tie(elemlib, elem) = parseLoadName(type);
204
205 std::stringstream err_os;
206 requireLibrary(elemlib, err_os);
207 std::lock_guard<std::recursive_mutex> lock(factoryMutex);
208
209 auto* lib = ELI::InfoDatabase::getLibrary<Base>(elemlib);
210 if ( lib ) {
211 auto map = lib->getMap();
212 auto* info = lib->getInfo(elem);
213 if ( info ) {
214 auto* builderLib = Base::getBuilderLibrary(elemlib);
215 if ( builderLib ) {
216 auto* fact = builderLib->getBuilder(elem);
217 if ( fact ) {
218 params.pushAllowedKeys(info->getParamNames());
219 Base* ret = fact->create(std::forward<CtorArgs>(args)...);
220 params.popAllowedKeys();
221 return ret;
222 }
223 }
224 }
225 }
226 notFound(Base::ELI_baseName(), type, err_os.str());
227 return nullptr;
228 }
229
230 /** Instantiate a new Statistic
231 * @param comp - Owning component
232 * @param type - Fully qualified elementlibname.statisticname type
233 * @param statName - Name of the statistic
234 * @param statSubId - Name of the sub statistic
235 * @param params - Parameters to pass to the Statistics's constructor
236 * @param fieldType - Type of data stored in statistic
237 */
238 template <class T, class... Args>
240 const std::string& type, BaseComponent* comp, const std::string& statName, const std::string& stat,
241 Params& params, Args... args)
242 {
243 std::string elemlib, elem;
244 std::tie(elemlib, elem) = parseLoadName(type);
245 // ensure library is already loaded...
246 std::stringstream sstr;
247 requireLibrary(elemlib, sstr);
248
249 auto* lib = ELI::BuilderDatabase::getLibrary<Statistics::Statistic<T>, Args...>(elemlib);
250 if ( lib ) {
251 auto* fact = lib->getFactory(elem);
252 if ( fact ) { return fact->create(comp, statName, stat, params, std::forward<Args>(args)...); }
253 }
254 // If we make it to here, component not found
255 out.fatal(CALL_INFO, -1, "can't find requested statistic %s.\n%s\n", type.c_str(), sstr.str().c_str());
256 return nullptr;
257 }
258
259 /** Return Python Module creation function
260 * @param name - Fully qualified elementlibname.pythonModName type name
261 */
262 SSTElementPythonModule* getPythonModule(const std::string& name);
263
264 /**
265 * @brief hasLibrary Checks to see if library exists and can be loaded
266 * @param elemlib
267 * @param err_os Stream to print error messages to
268 * @return whether the library was found
269 */
270 bool hasLibrary(const std::string& elemlib, std::ostream& err_os);
271 void requireLibrary(const std::string& elemlib, std::ostream& err_os);
272 /**
273 * @brief requireLibrary Throws away error messages
274 * @param elemlib
275 */
276 void requireLibrary(const std::string& elemlib);
277
278 void getLoadedLibraryNames(std::set<std::string>& lib_names);
279 void loadUnloadedLibraries(const std::set<std::string>& lib_names);
280
281 /** Determine if a SubComponentSlot is defined in a components ElementInfoStatistic
282 * @param type - The name of the component/subcomponent
283 * @param slotName - The name of the SubComponentSlot
284 * @return True if the SubComponentSlot is defined in the component's ELI
285 */
286 bool DoesSubComponentSlotExist(const std::string& type, const std::string& slotName);
287
288 /** Determine if a statistic is defined in a components ElementInfoStatistic
289 * @param type - The name of the component
290 * @param statisticName - The name of the statistic
291 * @return True if the statistic is defined in the component's ElementInfoStatistic
292 */
293 bool DoesComponentInfoStatisticNameExist(const std::string& type, const std::string& statisticName);
294
295 const std::vector<std::string>& GetValidStatistics(const std::string& compType);
296
297 /** Get the enable level of a statistic defined in the component's ElementInfoStatistic
298 * @param componentname - The name of the component
299 * @param statisticName - The name of the statistic
300 * @return The Enable Level of the statistic from the ElementInfoStatistic
301 */
302 uint8_t GetComponentInfoStatisticEnableLevel(const std::string& type, const std::string& statisticName);
303
304 /** Get the units of a statistic defined in the component's ElementInfoStatistic
305 * @param componentname - The name of the component
306 * @param statisticName - The name of the statistic
307 * @return The units string of the statistic from the ElementInfoStatistic
308 */
309 std::string GetComponentInfoStatisticUnits(const std::string& type, const std::string& statisticName);
310
311 /** Get a list of allowed ports for a given component type.
312 * @param type - Type of component in lib.name format
313 * @param point = Profile point to check
314 * @return True if this is a valid profile point
315 */
316 bool isProfilePointValid(const std::string& type, const std::string& point);
317
318private:
319 friend int ::main(int argc, char** argv);
320
321 void notFound(const std::string& baseName, const std::string& type, const std::string& errorMsg);
322
323 Factory(const std::string& searchPaths);
324 ~Factory();
325
326 Factory(); // Don't Implement
327 Factory(Factory const&); // Don't Implement
328 void operator=(Factory const&); // Don't Implement
329
330 static Factory* instance;
331
332 // find library information for name
333 bool findLibrary(const std::string& name, std::ostream& err_os = std::cerr);
334 // handle low-level loading of name
335 bool loadLibrary(const std::string& name, std::ostream& err_os = std::cerr);
336
337 std::set<std::string> loaded_libraries;
338
339 std::string searchPaths;
340
341 ElemLoader* loader;
342 std::string loadingComponentType;
343
344 std::pair<std::string, std::string> parseLoadName(const std::string& wholename);
345
346 std::recursive_mutex factoryMutex;
347
348protected:
349 Output& out;
350};
351
352} // namespace SST
353
354#endif // SST_CORE_FACTORY_H
Main component object for the simulation.
Definition: baseComponent.h:51
Main component object for the simulation.
Definition: component.h:31
Definition: simpleInfo.h:83
Class to load Element Libraries.
Definition: elemLoader.h:24
Class for instantiating Components, Links and the like out of element libraries.
Definition: factory.h:43
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:239
void RequireEvent(const std::string &eventname)
Ensure that an element library containing the required event is loaded.
Definition: factory.cc:530
Partition::SSTPartitioner * CreatePartitioner(const std::string &name, RankInfo total_ranks, RankInfo my_rank, int verbosity)
Return partitioner function.
Definition: factory.cc:541
bool DoesSubComponentSlotExist(const std::string &type, const std::string &slotName)
Determine if a SubComponentSlot is defined in a components ElementInfoStatistic.
Definition: factory.cc:227
Module * CreateModuleWithComponent(const std::string &type, Component *comp, Params &params)
Instantiate a new Module.
Definition: factory.cc:472
SSTElementPythonModule * getPythonModule(const std::string &name)
Return Python Module creation function.
Definition: factory.cc:574
Component * CreateComponent(ComponentId_t id, const std::string &componentname, Params &params)
Attempt to create a new Component instantiation.
Definition: factory.cc:189
std::string GetComponentInfoStatisticUnits(const std::string &type, const std::string &statisticName)
Get the units of a statistic defined in the component'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:200
bool hasLibrary(const std::string &elemlib, std::ostream &err_os)
hasLibrary Checks to see if library exists and can be loaded
Definition: factory.cc:600
uint8_t GetComponentInfoStatisticEnableLevel(const std::string &type, const std::string &statisticName)
Get the enable level of a statistic defined in the component's ElementInfoStatistic.
Definition: factory.cc:317
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
Base * Create(const std::string &type, CtorArgs &&... args)
General function to create a given base class.
Definition: factory.h:155
bool DoesComponentInfoStatisticNameExist(const std::string &type, const std::string &statisticName)
Determine if a statistic is defined in a components ElementInfoStatistic.
Definition: factory.cc:307
Module * CreateModule(const std::string &type, Params &params)
Instantiate a new Module.
Definition: factory.cc:432
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
bool isProfilePointValid(const std::string &type, const std::string &point)
Get a list of allowed ports for a given component type.
Definition: factory.cc:390
bool isSubComponentLoadableUsingAPI(const std::string &type)
Check to see if a given element type is loadable with a particular API.
Definition: factory.h:99
Module is a tag class used with the loadModule function.
Definition: module.h:22
Output object provides consistent method for outputting data to stdout, stderr and/or sst debug file.
Definition: output.h:52
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
Parameter store.
Definition: params.h:56
void popAllowedKeys()
Removes the most recent set of keys considered allowed.
Definition: params.cc:209
void pushAllowedKeys(const KeySet_t &keys)
Definition: params.cc:203
std::set< key_type, KeyCompare > KeySet_t
Definition: params.h:233
Base class for Partitioning graphs.
Definition: sstpart.h:32
Definition: rankInfo.h:22
Base class for python modules in element libraries.
Definition: element_python.h:129
Forms the template defined base class for statistics gathering within SST.
Definition: statbase.h:361