ENH: finer granularity for handling functionObject failure (#1779)

- additional "errors" entry with enumerated values
  (default|warn|ignore|strict) for defining warning or error at
  construct or runtime stage

- default : construct = warn, runtime = fatal
- warn    : construct = warn, runtime = warn
- ignore  : construct = silent, runtime = silent
- strict  : construct = fatal, runtime = fatal

The errors control can be added at the top-level and/or for individual
function objects.
This commit is contained in:
Mark Olesen
2020-08-05 17:16:54 +02:00
parent f39c1d3c57
commit 5424c5e5bc
3 changed files with 478 additions and 101 deletions

View File

@ -58,7 +58,9 @@ Description
\verbatim \verbatim
functions // sub-dictionary name under the system/controlDict file functions // sub-dictionary name under the system/controlDict file
{ {
<userDefinedSubDictName1> ..optional entries..
<dictName1>
{ {
// Mandatory entries // Mandatory entries
type <functionObjectTypeName>; type <functionObjectTypeName>;
@ -82,14 +84,14 @@ Description
writeInterval 1; writeInterval 1;
} }
<userDefinedSubDictName2> <dictName2>
{ {
... ...
} }
... ...
<userDefinedSubDictNameN> <dictNameN>
{ {
... ...
} }
@ -101,6 +103,7 @@ Description
Property | Description | Type | Reqd | Deflt Property | Description | Type | Reqd | Deflt
type | Type name of function object | word | yes | - type | Type name of function object | word | yes | -
libs | Library name(s) for implementation | words | no | - libs | Library name(s) for implementation | words | no | -
errors | Error handling (default/warn/ignore/strict) | word | no | inherits
region | Name of region for multi-region cases | word | no | region0 region | Name of region for multi-region cases | word | no | region0
enabled | Switch to turn function object on/off | bool | no | true enabled | Switch to turn function object on/off | bool | no | true
log | Switch to write log info to standard output | bool | no | true log | Switch to write log info to standard output | bool | no | true
@ -112,6 +115,9 @@ Description
writeInterval | Steps/time between write phases | label | no | 1 writeInterval | Steps/time between write phases | label | no | 1
\endtable \endtable
If the \c errors entry is missing, it uses the value (if any)
specified within the top-level functionObjectList.
Time controls: Time controls:
\table \table
Option | Description Option | Description

View File

@ -37,15 +37,64 @@ License
#include "Tuple2.H" #include "Tuple2.H"
#include "etcFiles.H" #include "etcFiles.H"
#include "IOdictionary.H" #include "IOdictionary.H"
#include "Pstream.H"
#include "OSspecific.H"
/* * * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * */
//- Max number of warnings (per functionObject)
static constexpr const uint32_t maxWarnings = 10u;
Foam::fileName Foam::functionObjectList::functionObjectDictPath Foam::fileName Foam::functionObjectList::functionObjectDictPath
( (
"caseDicts/postProcessing" "caseDicts/postProcessing"
); );
const Foam::Enum
<
Foam::functionObjectList::errorHandlingType
>
Foam::functionObjectList::errorHandlingNames_
({
{ errorHandlingType::DEFAULT, "default" },
{ errorHandlingType::WARN, "warn" },
{ errorHandlingType::IGNORE, "ignore" },
{ errorHandlingType::STRICT, "strict" },
});
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
namespace Foam
{
//- Mimic exit handling of the error class
static void exitNow(const error& err)
{
if (hasEnv("FOAM_ABORT"))
{
Perr<< nl << err << nl
<< "\nFOAM aborting (FOAM_ABORT set)\n" << endl;
error::printStack(Perr);
std::abort();
}
else if (Pstream::parRun())
{
Perr<< nl << err << nl
<< "\nFOAM parallel run exiting\n" << endl;
Pstream::exit(1);
}
else
{
Perr<< nl << err << nl
<< "\nFOAM exiting\n" << endl;
std::exit(1);
}
}
} // End namespace Foam
// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * // // * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
void Foam::functionObjectList::createStateDict() const void Foam::functionObjectList::createStateDict() const
@ -282,7 +331,7 @@ bool Foam::functionObjectList::readFunctionObject
// Search for the functionObject dictionary // Search for the functionObject dictionary
fileName path = functionObjectList::findDict(funcName); fileName path = functionObjectList::findDict(funcName);
if (path == fileName::null) if (path.empty())
{ {
WarningInFunction WarningInFunction
<< "Cannot find functionObject file " << funcName << endl; << "Cannot find functionObject file " << funcName << endl;
@ -291,7 +340,7 @@ bool Foam::functionObjectList::readFunctionObject
// Read the functionObject dictionary // Read the functionObject dictionary
autoPtr<ISstream> fileStreamPtr(fileHandler().NewIFstream(path)); autoPtr<ISstream> fileStreamPtr(fileHandler().NewIFstream(path));
ISstream& fileStream = fileStreamPtr(); ISstream& fileStream = *fileStreamPtr;
dictionary funcsDict(fileStream); dictionary funcsDict(fileStream);
dictionary* funcDictPtr = funcsDict.findDict(funcName); dictionary* funcDictPtr = funcsDict.findDict(funcName);
@ -347,6 +396,45 @@ bool Foam::functionObjectList::readFunctionObject
} }
Foam::functionObjectList::errorHandlingType
Foam::functionObjectList::getOrDefaultErrorHandling
(
const word& key,
const dictionary& dict,
const errorHandlingType deflt
) const
{
const entry* eptr = dict.findEntry(key, keyType::LITERAL);
if (eptr)
{
if (eptr->isDict())
{
Warning
<< "The sub-dictionary '" << key
<< "' masks error handling for functions" << endl;
}
else
{
const word enumName(eptr->get<word>());
if (!errorHandlingNames_.found(enumName))
{
// Failed the name lookup
FatalIOErrorInFunction(dict)
<< enumName << " is not in enumeration: "
<< errorHandlingNames_ << nl
<< exit(FatalIOError);
}
return errorHandlingNames_.get(enumName);
}
}
return deflt;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::functionObjectList::functionObjectList Foam::functionObjectList::functionObjectList
@ -355,15 +443,7 @@ Foam::functionObjectList::functionObjectList
const bool execution const bool execution
) )
: :
PtrList<functionObject>(), functionObjectList(runTime, runTime.controlDict(), execution)
digests_(),
indices_(),
time_(runTime),
parentDict_(runTime.controlDict()),
stateDictPtr_(),
objectsRegistryPtr_(),
execution_(execution),
updated_(false)
{} {}
@ -375,12 +455,14 @@ Foam::functionObjectList::functionObjectList
) )
: :
PtrList<functionObject>(), PtrList<functionObject>(),
errorHandling_(),
digests_(), digests_(),
indices_(), indices_(),
warnings_(),
time_(runTime), time_(runTime),
parentDict_(parentDict), parentDict_(parentDict),
stateDictPtr_(), stateDictPtr_(nullptr),
objectsRegistryPtr_(), objectsRegistryPtr_(nullptr),
execution_(execution), execution_(execution),
updated_(false) updated_(false)
{} {}
@ -442,9 +524,7 @@ Foam::autoPtr<Foam::functionObjectList> Foam::functionObjectList::New
{ {
modifiedControlDict = true; modifiedControlDict = true;
wordList funcNames = args.getList<word>("funcs"); for (const word& funcName : args.getList<word>("funcs"))
for (const word& funcName : funcNames)
{ {
readFunctionObject readFunctionObject
( (
@ -478,17 +558,14 @@ Foam::autoPtr<Foam::functionObjectList> Foam::functionObjectList::New
Foam::label Foam::functionObjectList::triggerIndex() const Foam::label Foam::functionObjectList::triggerIndex() const
{ {
label triggeri = labelMin; return stateDict().getOrDefault<label>("triggerIndex", labelMin);
stateDict().readIfPresent("triggerIndex", triggeri);
return triggeri;
} }
void Foam::functionObjectList::resetState() void Foam::functionObjectList::resetState()
{ {
// Reset (re-read) the state dictionary // Reset (re-read) the state dictionary
stateDictPtr_.clear(); stateDictPtr_.reset(nullptr);
createStateDict(); createStateDict();
} }
@ -540,19 +617,21 @@ const Foam::objectRegistry& Foam::functionObjectList::storedObjects() const
void Foam::functionObjectList::clear() void Foam::functionObjectList::clear()
{ {
PtrList<functionObject>::clear(); PtrList<functionObject>::clear();
errorHandling_.clear();
digests_.clear(); digests_.clear();
indices_.clear(); indices_.clear();
warnings_.clear();
updated_ = false; updated_ = false;
} }
Foam::label Foam::functionObjectList::findObjectID(const word& name) const Foam::label Foam::functionObjectList::findObjectID(const word& objName) const
{ {
label id = 0; label id = 0;
for (const functionObject& funcObj : functions()) for (const functionObject& funcObj : functions())
{ {
if (funcObj.name() == name) if (funcObj.name() == objName)
{ {
return id; return id;
} }
@ -600,27 +679,148 @@ bool Foam::functionObjectList::execute()
read(); read();
} }
auto errIter = errorHandling_.cbegin();
for (functionObject& funcObj : functions()) for (functionObject& funcObj : functions())
{ {
const errorHandlingType errorHandling = *errIter;
++errIter;
const word& objName = funcObj.name(); const word& objName = funcObj.name();
if
(
errorHandling == errorHandlingType::WARN
|| errorHandling == errorHandlingType::IGNORE
)
{ {
addProfiling(fo, "functionObject::" + objName + "::execute"); // Throw FatalError, FatalIOError as exceptions
const bool throwingError = FatalError.throwExceptions();
const bool throwingIOerr = FatalIOError.throwExceptions();
bool hadError = false;
// execute()
try
{
addProfiling
(
fo,
"functionObject::" + objName + "::execute"
);
ok = funcObj.execute() && ok;
}
catch (const Foam::error& err)
{
// Treat IOerror and error identically
uint32_t nWarnings;
hadError = true;
if
(
errorHandling != errorHandlingType::IGNORE
&& (nWarnings = ++warnings_(objName)) <= maxWarnings
)
{
// Trickery to get original message
err.write(Warning, false);
Info<< nl
<< "--> execute() function object '"
<< objName << "'";
if (nWarnings == maxWarnings)
{
Info<< nl << "... silencing further warnings";
}
Info<< nl << endl;
}
}
if (hadError)
{
// Restore previous state
FatalError.throwExceptions(throwingError);
FatalIOError.throwExceptions(throwingIOerr);
continue;
}
// write()
try
{
addProfiling
(
fo,
"functionObject::" + objName + ":write"
);
ok = funcObj.write() && ok;
}
catch (const Foam::error& err)
{
// Treat IOerror and error identically
uint32_t nWarnings;
if
(
errorHandling != errorHandlingType::IGNORE
&& (nWarnings = ++warnings_(objName)) <= maxWarnings
)
{
// Trickery to get original message
err.write(Warning, false);
Info<< nl
<< "--> write() function object '"
<< objName << "'";
if (nWarnings == maxWarnings)
{
Info<< nl << "... silencing further warnings";
}
Info<< nl << endl;
}
}
// Restore previous state
FatalError.throwExceptions(throwingError);
FatalIOError.throwExceptions(throwingIOerr);
}
else
{
// No special trapping of errors
// execute()
{
addProfiling
(
fo,
"functionObject::" + objName + "::execute"
);
ok = funcObj.execute() && ok; ok = funcObj.execute() && ok;
} }
// write()
{ {
addProfiling(fo, "functionObject::" + objName + "::write"); addProfiling
(
fo,
"functionObject::" + objName + ":write"
);
ok = funcObj.write() && ok; ok = funcObj.write() && ok;
} }
} }
} }
}
// Force writing of state dictionary after function object execution // Force writing of state dictionary after function object execution
if (time_.writeTime()) if (time_.writeTime())
{ {
label oldPrecision = IOstream::precision_; const auto oldPrecision = IOstream::precision_;
IOstream::precision_ = 16; IOstream::precision_ = 16;
stateDictPtr_->writeObject stateDictPtr_->writeObject
@ -644,6 +844,8 @@ bool Foam::functionObjectList::execute(const label subIndex)
{ {
for (functionObject& funcObj : functions()) for (functionObject& funcObj : functions())
{ {
// Probably do not need try/catch...
ok = funcObj.execute(subIndex) && ok; ok = funcObj.execute(subIndex) && ok;
} }
} }
@ -666,6 +868,8 @@ bool Foam::functionObjectList::execute
{ {
if (stringOps::match(functionNames, funcObj.name())) if (stringOps::match(functionNames, funcObj.name()))
{ {
// Probably do not need try/catch...
ok = funcObj.execute(subIndex) && ok; ok = funcObj.execute(subIndex) && ok;
} }
} }
@ -686,14 +890,56 @@ bool Foam::functionObjectList::end()
read(); read();
} }
auto errIter = errorHandling_.cbegin();
for (functionObject& funcObj : functions()) for (functionObject& funcObj : functions())
{ {
const errorHandlingType errorHandling = *errIter;
++errIter;
const word& objName = funcObj.name(); const word& objName = funcObj.name();
addProfiling(fo, "functionObject::" + objName + "::end"); // Ignore failure on end() - not much we can do anyhow
// Throw FatalError, FatalIOError as exceptions
const bool throwingError = FatalError.throwExceptions();
const bool throwingIOerr = FatalIOError.throwExceptions();
try
{
addProfiling(fo, "functionObject::" + objName + "::end");
ok = funcObj.end() && ok; ok = funcObj.end() && ok;
} }
catch (const Foam::error& err)
{
// Treat IOerror and error identically
uint32_t nWarnings;
if
(
errorHandling != errorHandlingType::IGNORE
&& (nWarnings = ++warnings_(objName)) <= maxWarnings
)
{
// Trickery to get original message
err.write(Warning, false);
Info<< nl
<< "--> end() function object '"
<< objName << "'";
if (nWarnings == maxWarnings)
{
Info<< nl << "... silencing further warnings";
}
Info<< nl << endl;
}
}
// Restore previous state
FatalError.throwExceptions(throwingError);
FatalIOError.throwExceptions(throwingIOerr);
}
} }
return ok; return ok;
@ -715,7 +961,13 @@ bool Foam::functionObjectList::adjustTimeStep()
{ {
const word& objName = funcObj.name(); const word& objName = funcObj.name();
addProfiling(fo, "functionObject::" + objName + "::adjustTimeStep"); // Probably do not need try/catch...
addProfiling
(
fo,
"functionObject::" + objName + "::adjustTimeStep"
);
ok = funcObj.adjustTimeStep() && ok; ok = funcObj.adjustTimeStep() && ok;
} }
@ -750,8 +1002,10 @@ bool Foam::functionObjectList::read()
{ {
// No functions // No functions
PtrList<functionObject>::clear(); PtrList<functionObject>::clear();
errorHandling_.clear();
digests_.clear(); digests_.clear();
indices_.clear(); indices_.clear();
warnings_.clear();
} }
else if (!entryPtr->isDict()) else if (!entryPtr->isDict())
{ {
@ -767,10 +1021,18 @@ bool Foam::functionObjectList::read()
PtrList<functionObject> newPtrs(functionsDict.size()); PtrList<functionObject> newPtrs(functionsDict.size());
List<SHA1Digest> newDigs(functionsDict.size()); List<SHA1Digest> newDigs(functionsDict.size());
errorHandling_.resize
(
functionsDict.size(),
errorHandlingType::DEFAULT
);
HashTable<label> newIndices; HashTable<label> newIndices;
addProfiling(fo, "functionObjects::read"); addProfiling(fo, "functionObjects::read");
// Top-level "libs" specification (optional)
time_.libs().open time_.libs().open
( (
functionsDict, functionsDict,
@ -778,6 +1040,15 @@ bool Foam::functionObjectList::read()
functionObject::dictionaryConstructorTablePtr_ functionObject::dictionaryConstructorTablePtr_
); );
// Top-level "errors" specification (optional)
const errorHandlingType errorHandlingFallback =
getOrDefaultErrorHandling
(
"errors",
functionsDict,
errorHandlingType::DEFAULT
);
label nFunc = 0; label nFunc = 0;
for (const entry& dEntry : functionsDict) for (const entry& dEntry : functionsDict)
@ -786,7 +1057,7 @@ bool Foam::functionObjectList::read()
if (!dEntry.isDict()) if (!dEntry.isDict())
{ {
if (key != "libs") if (key != "errors" && key != "libs")
{ {
IOWarningInFunction(parentDict_) IOWarningInFunction(parentDict_)
<< "Entry " << key << " is not a dictionary" << endl; << "Entry " << key << " is not a dictionary" << endl;
@ -799,66 +1070,67 @@ bool Foam::functionObjectList::read()
bool enabled = dict.getOrDefault("enabled", true); bool enabled = dict.getOrDefault("enabled", true);
// Per-function "errors" specification
const errorHandlingType errorHandling =
getOrDefaultErrorHandling
(
"errors",
dict,
errorHandlingFallback
);
errorHandling_[nFunc] = errorHandling;
newDigs[nFunc] = dict.digest(); newDigs[nFunc] = dict.digest();
label oldIndex = -1; label oldIndex = -1;
autoPtr<functionObject> objPtr = remove(key, oldIndex); autoPtr<functionObject> objPtr = remove(key, oldIndex);
const bool needsTimeControl =
functionObjects::timeControl::entriesPresent(dict);
if (objPtr) if (objPtr)
{ {
// Re-read if dictionary content changed for // Existing functionObject:
// existing functionObject // Re-read if dictionary content changed and did not
// change timeControl <-> regular
if (enabled && newDigs[nFunc] != digests_[oldIndex]) if (enabled && newDigs[nFunc] != digests_[oldIndex])
{ {
const bool wasTimeControl =
isA<functionObjects::timeControl>(*objPtr);
if (needsTimeControl != wasTimeControl)
{
// Changed from timeControl <-> regular
// Fallthrough to 'new'
objPtr.reset(nullptr);
}
else
{
// Normal read. Assume no errors to trap
addProfiling addProfiling
( (
fo2, fo,
"functionObject::" + objPtr->name() + "::read" "functionObject::" + objPtr->name() + "::read"
); );
if (functionObjects::timeControl::entriesPresent(dict))
{
if (isA<functionObjects::timeControl>(objPtr()))
{
// Already a time control - normal read
enabled = objPtr->read(dict); enabled = objPtr->read(dict);
} }
else
{
// Was not a time control - need to re-create
objPtr.reset
(
new functionObjects::timeControl
(
key,
time_,
dict
)
);
enabled = true;
}
}
else
{
// Plain function object - normal read
enabled = objPtr->read(dict);
}
ok = enabled && ok;
} }
if (!enabled) if (!enabled)
{ {
// Delete disabled or an invalid(read) functionObject // Delete disabled or an invalid(read) functionObject
objPtr.clear(); objPtr.reset(nullptr);
continue; continue;
} }
} }
else if (enabled)
{
autoPtr<functionObject> foPtr;
if (enabled && !objPtr)
{
// Throw FatalError, FatalIOError as exceptions // Throw FatalError, FatalIOError as exceptions
const bool throwingError = FatalError.throwExceptions(); const bool throwingError = FatalError.throwExceptions();
const bool throwingIOerr = FatalIOError.throwExceptions(); const bool throwingIOerr = FatalIOError.throwExceptions();
@ -868,47 +1140,70 @@ bool Foam::functionObjectList::read()
// New functionObject // New functionObject
addProfiling addProfiling
( (
fo2, fo,
"functionObject::" + key + "::new" "functionObject::" + key + "::new"
); );
if (functionObjects::timeControl::entriesPresent(dict)) if (needsTimeControl)
{ {
foPtr.reset objPtr.reset
( (
new functionObjects::timeControl(key, time_, dict) new functionObjects::timeControl(key, time_, dict)
); );
} }
else else
{ {
foPtr = functionObject::New(key, time_, dict); objPtr = functionObject::New(key, time_, dict);
} }
} }
catch (const Foam::IOerror& ioErr)
{
Info<< ioErr << nl << endl;
std::exit(1);
}
catch (const Foam::error& err) catch (const Foam::error& err)
{ {
// Bit of trickery to get the original message objPtr.reset(nullptr); // extra safety
err.write(Warning, false);
InfoInFunction switch (errorHandling)
<< nl {
<< "--> while loading function object '" << key << "'" case errorHandlingType::IGNORE:
<< nl << endl; break;
case errorHandlingType::STRICT:
{
exitNow(err);
break;
} }
// Restore previous exception throwing state case errorHandlingType::DEFAULT:
{
if (isA<Foam::IOerror>(err))
{
// Fatal for Foam::IOerror
exitNow(err);
break;
}
// Emit warning otherwise
[[fallthrough]];
}
case errorHandlingType::WARN:
{
// Trickery to get original message
err.write(Warning, false);
Info<< nl
<< "--> loading function object '"
<< key << "'"
<< nl << endl;
break;
}
}
}
// Restore previous state
FatalError.throwExceptions(throwingError); FatalError.throwExceptions(throwingError);
FatalIOError.throwExceptions(throwingIOerr); FatalIOError.throwExceptions(throwingIOerr);
// Required functionObject to be valid on all processors // Require valid functionObject on all processors
if (returnReduce(bool(foPtr), andOp<bool>())) if (!returnReduce(bool(objPtr), andOp<bool>()))
{
objPtr.reset(foPtr.release());
}
else
{ {
objPtr.reset(nullptr);
ok = false; ok = false;
} }
} }
@ -924,12 +1219,14 @@ bool Foam::functionObjectList::read()
newPtrs.resize(nFunc); newPtrs.resize(nFunc);
newDigs.resize(nFunc); newDigs.resize(nFunc);
errorHandling_.resize(nFunc);
// Updating PtrList of functionObjects deletes any // Updating PtrList of functionObjects deletes any
// existing unused functionObjects // existing unused functionObjects
PtrList<functionObject>::transfer(newPtrs); PtrList<functionObject>::transfer(newPtrs);
digests_.transfer(newDigs); digests_.transfer(newDigs);
indices_.transfer(newIndices); indices_.transfer(newIndices);
warnings_.clear();
} }
return ok; return ok;

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2015-2019 OpenCFD Ltd. Copyright (C) 2015-2020 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -31,6 +31,43 @@ Description
List of function objects with start(), execute() and end() functions List of function objects with start(), execute() and end() functions
that is called for each object. that is called for each object.
\verbatim
functions // sub-dictionary name under the system/controlDict file
{
..optional entries..
<userDict1>
{
// Mandatory entries
type <typeName>;
libs (<libName> .. <libName>);
...
}
<userDict2>
{
...
}
...
}
\endverbatim
with optional entries:
\table
Property | Description | Type | Reqd | Deflt
libs | Preloaded library names | words | no | -
errors | Error handling (default/warn/ignore/strict) | word | no | inherits
\endtable
The optional \c errors entry controls how FatalError is caught
during construction and execute/write. FatalIOError is unaffected.
- \c default : warn on construction errors, fatal on runtime errors
- \c warn : warn on construction and runtime errors
- \c ignore : ignore construction and runtime errors
- \c strict : fatal on construction and runtime errors
.
See also See also
Foam::functionObject Foam::functionObject
Foam::functionObjects::timeControl Foam::functionObjects::timeControl
@ -44,6 +81,7 @@ SourceFiles
#define functionObjectList_H #define functionObjectList_H
#include "PtrList.H" #include "PtrList.H"
#include "Enum.H"
#include "functionObject.H" #include "functionObject.H"
#include "SHA1Digest.H" #include "SHA1Digest.H"
#include "HashTable.H" #include "HashTable.H"
@ -55,7 +93,7 @@ SourceFiles
namespace Foam namespace Foam
{ {
// Forward declarations // Forward Declarations
class argList; class argList;
class mapPolyMesh; class mapPolyMesh;
class wordRe; class wordRe;
@ -68,14 +106,37 @@ class functionObjectList
: :
private PtrList<functionObject> private PtrList<functionObject>
{ {
// Private data // Data Types
//- Handling of construction or execution errors
enum class errorHandlingType : uint8_t
{
DEFAULT = 0, //!< Warn on construct, Fatal on runtime
WARN, //!< Warn on construct, Warn on runtime
IGNORE, //!< Ignore on construct, Ignore on runtime
STRICT, //!< Fatal on construct, Fatal on runtime
};
//- Names for error handling types
static const Enum<errorHandlingType> errorHandlingNames_;
// Private Data
//- A list of error/warning handling
List<errorHandlingType> errorHandling_;
//- A list of SHA1 digests for the function object dictionaries //- A list of SHA1 digests for the function object dictionaries
List<SHA1Digest> digests_; List<SHA1Digest> digests_;
//- Quick lookup of the index into functions/digests //- Quick lookup of the index into functions/digests/errorHandling
HashTable<label> indices_; HashTable<label> indices_;
//- Track the number of warnings per function object and limit
// to a predefined number to avoid flooding the display.
// Clear on re-read of functions.
HashTable<uint32_t> warnings_;
//- Reference to Time //- Reference to Time
const Time& time_; const Time& time_;
@ -119,6 +180,19 @@ class functionObjectList
//- configuration files, add to the given map and recurse //- configuration files, add to the given map and recurse
static void listDir(const fileName& dir, wordHashSet& available); static void listDir(const fileName& dir, wordHashSet& available);
//- Like Enum::getOrDefault, but with additional code to warn if
//- the 'key' is not a primitive entry.
//
// This additional treatment is to ensure that potentially existing
// code with an "errors" functionObject will continue to run.
errorHandlingType getOrDefaultErrorHandling
(
const word& key,
const dictionary& dict,
const errorHandlingType deflt
) const;
//- No copy construct //- No copy construct
functionObjectList(const functionObjectList&) = delete; functionObjectList(const functionObjectList&) = delete;
@ -214,7 +288,7 @@ public:
void clear(); void clear();
//- Find the ID of a given function object by name, -1 if not found. //- Find the ID of a given function object by name, -1 if not found.
label findObjectID(const word& name) const; label findObjectID(const word& objName) const;
//- Print a list of functionObject configuration files in the //- Print a list of functionObject configuration files in the
//- directories located using //- directories located using