11#define BOOST_DLL_USE_STD_FS
12#include <boost/dll/import.hpp>
13#include <boost/algorithm/string.hpp>
19namespace ba = boost::algorithm;
26#pragma comment(lib, "advapi32")
38Application::Messages::Messages()
47 if (msg.size() != 0) {
48 errorMessage.push_back(
49 "\n\n************************************************\n"
51 "************************************************\n\n"
53 "\nError: " + msg +
"\n");
55 errorMessage.push_back(r);
61 return static_cast<int>(errorMessage.size());
66 logwriter.reset(_logwriter);
71 logwriter->write(msg);
76 logwriter->writeendl();
81 logwriter->warn(warning, msg);
89 std::unique_lock<std::mutex> msgLock(
msg_mutex);
90 std::thread::id curId = std::this_thread::get_id();
91 auto iter = m_threadMsgMap.find(curId);
92 if (iter != m_threadMsgMap.end()) {
93 return iter->second.get();
96 m_threadMsgMap.insert({curId, pMsgs});
102 std::unique_lock<std::mutex> msgLock(
msg_mutex);
103 std::thread::id curId = std::this_thread::get_id();
104 auto iter = m_threadMsgMap.find(curId);
105 if (iter != m_threadMsgMap.end()) {
106 m_threadMsgMap.erase(iter);
119 std::unique_lock<std::mutex> appLock(
app_mutex);
128 std::unique_lock<std::mutex> appLock(
app_mutex);
137 if (m_fatal_deprecation_warnings) {
139 }
else if (m_suppress_deprecation_warnings ||
warnings.count(method)) {
143 warnlog(
"Deprecation", fmt::format(
"{}: {}", method, extra));
148 if (m_fatal_warnings) {
150 }
else if (m_suppress_warnings) {
153 warnlog(warning, fmt::format(
"{}: {}", method, extra));
162long int Application::readStringRegistryKey(
const string& keyName,
const string& valueName,
163 string& value,
const string& defaultValue)
166 long open_error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyName.c_str(), 0, KEY_READ, &key);
167 if (open_error != ERROR_SUCCESS) {
170 value = defaultValue;
172 DWORD bufferSize =
sizeof(buffer);
174 error = RegQueryValueEx(key, valueName.c_str(), 0, NULL, (LPBYTE) buffer, &bufferSize);
175 if (ERROR_SUCCESS == error) {
185 if (!errorMessage.empty()) {
186 errorMessage.pop_back();
192 if (!errorMessage.empty()) {
193 return errorMessage.back();
195 return "<no Cantera error>";
201 for (
size_t j = 0; j < errorMessage.size(); j++) {
202 f << errorMessage[j] << std::endl;
204 errorMessage.clear();
209 for (
size_t j = 0; j < errorMessage.size(); j++) {
213 errorMessage.clear();
226 string pathsep =
";";
227 string dirsep =
"\\";
229 string pathsep =
":";
233 if (getenv(
"CANTERA_DATA") !=
nullptr) {
234 string s(getenv(
"CANTERA_DATA"));
236 size_t end = s.find(pathsep);
237 while (end !=
npos) {
238 inputDirs.push_back(s.substr(start, end-start));
240 end = s.find(pathsep, start);
242 inputDirs.push_back(s.substr(start,end));
247 if (getenv(
"CONDA_PREFIX") !=
nullptr) {
248 string s(getenv(
"CONDA_PREFIX"));
249 inputDirs.push_back(s + dirsep +
"share" + dirsep +
"cantera" + dirsep +
"data");
257 readStringRegistryKey(
"SOFTWARE\\Cantera\\Cantera " CANTERA_SHORT_VERSION,
258 "InstallDir", installDir,
"");
259 if (installDir !=
"") {
260 inputDirs.push_back(installDir +
"data");
264 const char* old_pythonpath = getenv(
"PYTHONPATH");
265 string pythonpath =
"PYTHONPATH=" + installDir +
"\\bin";
266 if (old_pythonpath) {
268 pythonpath.append(old_pythonpath);
270 _putenv(pythonpath.c_str());
286 std::unique_lock<std::mutex> dirLock(
dir_mutex);
293 if (d.find(
"~/") == 0 || d.find(
"~\\") == 0) {
294 char* home = getenv(
"HOME");
296 home = getenv(
"USERPROFILE");
299 d = home + d.substr(1,
npos);
315 std::unique_lock<std::mutex> dirLock(
dir_mutex);
316 string::size_type islash = name.find(
'/');
317 string::size_type ibslash = name.find(
'\\');
318 string::size_type icolon = name.find(
':');
322 if (name.find(
"~/") == 0 || name.find(
"~\\") == 0) {
323 char* home = getenv(
"HOME");
325 home = getenv(
"USERPROFILE");
328 string full_name = home + name.substr(1,
npos);
329 std::ifstream fin(full_name);
334 "Input file '{}' not found", name);
340 if (islash == 0 || ibslash == 0
341 || (icolon == 1 && (ibslash == 2 || islash == 2)))
343 std::ifstream fin(name);
348 "Input file '{}' not found", name);
354 size_t nd = dirs.size();
355 for (
size_t i = 0; i < nd; i++) {
356 string full_name = dirs[i] +
"/" + name;
357 std::ifstream fin(full_name);
362 string msg =
"\nInput file " + name +
" not found in director";
363 msg += (nd == 1 ?
"y " :
"ies ");
364 for (
size_t i = 0; i < nd; i++) {
365 msg +=
"\n'" + dirs[i] +
"'";
371 msg +=
"To fix this problem, either:\n";
372 msg +=
" a) move the missing files into the local directory;\n";
373 msg +=
" b) define environment variable CANTERA_DATA to\n";
374 msg +=
" point to the directory containing the file.";
382 "Loading extensions requires linking to the Cantera shared library\n"
383 "rather than the static library");
385 if (m_loaded_extensions.count({extType, name})) {
393 typedef void (loader_t)();
397 static function<loader_t> loader;
401 string py_ver_underscore = ba::replace_all_copy(py_ver,
".",
"_");
403 loader = boost::dll::import_alias<loader_t>(
404 "cantera_python" + py_ver_underscore,
405 "registerPythonExtensionManager",
408 boost::dll::load_mode::search_system_folders
409 | boost::dll::load_mode::append_decorations
410 | boost::dll::load_mode::rtld_global
415 }
catch (std::exception& err) {
416 errors += fmt::format(
"\nPython {}: {}\n", py_ver, err.what());
421 "Error loading Python extension support. Tried the following:{}",
426 m_loaded_extensions.insert({extType, name});
Class to carry out messages.
unique_ptr< Logger > logwriter
Current pointer to the logwriter.
void writelogendl()
Write an end of line character to the screen and flush output.
Messages * operator->()
Provide a pointer dereferencing overloaded operator.
void removeThreadMessages()
Remove a local thread message.
Class to hold global data.
static Application * s_app
Pointer to the single Application instance.
vector< string > m_pythonSearchVersions
Versions of Python to consider when attempting to load user extensions.
void warnlog(const string &warning, const string &msg)
Write a warning message to the screen.
static Application * Instance()
Return a pointer to the one and only instance of class Application.
void loadExtension(const string &extType, const string &name)
Load an extension implementing user-defined models.
void warn_deprecated(const string &method, const string &extra="")
Print a warning indicating that method is deprecated.
void searchPythonVersions(const string &versions)
Set the versions of Python to try when loading user-defined extensions, in order of preference.
vector< string > inputDirs
Current vector of input directories to search for input files.
void thread_complete()
Delete and free memory allocated per thread in multithreaded applications.
void writelog(const string &msg)
Write a message to the screen.
set< string > warnings
Set of deprecation warnings that have been emitted (to suppress duplicates)
shared_ptr< Messages > pMessages_t
Typedef for thread specific messages.
Application()
Constructor for class sets up the initial conditions Protected ctor access thru static member functio...
void writelogendl()
Write an endl to the screen and flush output.
static void ApplicationDestroy()
Static function that destroys the application class's data.
void warn(const string &warning, const string &method, const string &extra="")
Generate a general purpose warning; repeated warnings are not suppressed.
Base class for exceptions thrown by Cantera classes.
static shared_ptr< ExtensionManager > build(const string &extensionType)
Create a new ExtensionManager.
static ExtensionManagerFactory & factory()
Static function that returns the static instance of the factory, creating it if necessary.
Base class for 'loggers' that write text messages to log files.
Definitions for the classes that are thrown when Cantera experiences an error condition (also contain...
string stripnonprint(const string &s)
Strip non-printing characters wherever they are.
void addError(const string &r, const string &msg="")
Set an error condition in the application class without throwing an exception.
void logErrors()
Prints all of the error messages using writelog.
void getErrors(std::ostream &f)
Prints all of the error messages to an ostream.
string lastErrorMessage()
Retrieve the last error message in a string.
int getErrorCount()
Return the number of errors that have been encountered so far.
void popError()
Discard the last error message.
bool usingSharedLibrary()
Returns true if Cantera was loaded as a shared library in the current application.
void warnlog(const string &warning, const string &msg)
Write a warning message to the screen.
void setLogger(Logger *logwriter)
Install a logger.
void writelog(const string &msg)
Write a message to the screen.
Namespace for the Cantera kernel.
const size_t npos
index returned by functions to indicate "no position"
static std::mutex app_mutex
Mutex for creating singletons within the application object.
static std::mutex dir_mutex
Mutex for input directory access.
static std::mutex msg_mutex
Mutex for access to string messages.
Contains declarations for string manipulation functions within Cantera.