ENH: avoid unnecessary disk access in writeDictionary (#2362)

- added in special handling for monitoring controlDict.

  Since controlDict is an unwatchedIOdictionary (not IOdictionary) and
  not registered either, the usual objectRegistry caching is not
  available. Instead, access directly from Time.

  Left the balance of the file handling largely intact (for handling
  unregistered dictionaries) but could potentially revisit in the
  future and attempt master-only file access if required. However,
  most other IOdictionary types will be registered, otherwise the
  READ_IF_MODIFIED mechanism would not really work properly.
This commit is contained in:
Mark Olesen
2022-02-11 17:39:11 +01:00
parent cbc86d6a88
commit 24bee96db2
2 changed files with 81 additions and 74 deletions

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2013-2017 OpenFOAM Foundation Copyright (C) 2013-2017 OpenFOAM Foundation
Copyright (C) 2016-2020 OpenCFD Ltd. Copyright (C) 2016-2022 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -56,11 +56,10 @@ void Foam::functionObjects::writeDictionary::writeHeader()
{ {
if (firstChange_) if (firstChange_)
{ {
Info<< type() << " " << name() << " write:" << nl << endl;
IOobject::writeDivider(Info);
Info<< endl;
firstChange_ = false; firstChange_ = false;
Info<< type() << ' ' << name() << " write:" << nl << nl;
IOobject::writeDivider(Info) << endl;
} }
} }
@ -71,16 +70,16 @@ void Foam::functionObjects::writeDictionary::checkDictionary
const label dicti const label dicti
) )
{ {
if (dict.digest() != digests_[dicti]) const auto digest(dict.digest());
if (digests_[dicti] != digest)
{ {
digests_[dicti] = digest;
writeHeader(); writeHeader();
dict.writeEntry(Info);
digests_[dicti] = dict.digest(); Info<< nl;
IOobject::writeDivider(Info) << endl;
Info<< dict.dictName() << dict << nl;
IOobject::writeDivider(Info);
Info<< endl;
} }
} }
@ -121,13 +120,12 @@ Foam::functionObjects::writeDictionary::writeDictionary
const dictionary& dict const dictionary& dict
) )
: :
regionFunctionObject(name, runTime, dict), functionObjects::regionFunctionObject(name, runTime, dict),
dictNames_(), dictNames_(),
digests_(), digests_(),
firstChange_(true) firstChange_(true)
{ {
read(dict); read(dict);
execute();
} }
@ -137,21 +135,18 @@ bool Foam::functionObjects::writeDictionary::read(const dictionary& dict)
{ {
regionFunctionObject::read(dict); regionFunctionObject::read(dict);
wordList dictNames(dict.get<wordList>("dictNames")); // Make unique
wordHashSet uniqueNames(dictNames); dictNames_ = wordHashSet(dict.get<wordList>("dictNames")).sortedToc();
dictNames_ = uniqueNames.toc();
digests_.setSize(dictNames_.size(), SHA1Digest()); digests_.resize(dictNames_.size());
digests_ = SHA1Digest();
Info<< type() << " " << name() << ": monitoring dictionaries:" << nl; Info<< type() << ' ' << name() << ": monitoring dictionaries:" << nl;
if (dictNames_.size()) for (const word& dictName : dictNames_)
{ {
for (const word & dictName : dictNames_) Info<< " " << dictName << nl;
{
Info<< " " << dictName << endl;
} }
} if (dictNames_.empty())
else
{ {
Info<< " none" << nl; Info<< " none" << nl;
} }
@ -161,6 +156,53 @@ bool Foam::functionObjects::writeDictionary::read(const dictionary& dict)
} }
bool Foam::functionObjects::writeDictionary::performCheck()
{
// Restart reporting cycle
firstChange_ = true;
forAll(dictNames_, dicti)
{
// Also search parent (eg, Time) as too
const auto* dictptr =
obr_.cfindObject<IOdictionary>(dictNames_[dicti], true);
if (dictptr)
{
checkDictionary(*dictptr, dicti);
}
else if (dictNames_[dicti] == Time::controlDictName)
{
// Slight hack. controlDict an unwatchedIOdictionary
// (not IOdictionary) and not registered on Time either
// - grab directly from Time
checkDictionary(obr_.time().controlDict(), dicti);
}
else
{
const bool ok
(
tryDirectory(obr_.time().timeName(), dicti)
|| tryDirectory(obr_.time().constant(), dicti)
|| tryDirectory(obr_.time().system(), dicti)
);
if (!ok)
{
writeHeader();
Info<< " Unable to locate dictionary "
<< dictNames_[dicti] << nl << nl;
IOobject::writeDivider(Info) << endl;
}
}
}
return true;
}
bool Foam::functionObjects::writeDictionary::execute() bool Foam::functionObjects::writeDictionary::execute()
{ {
return true; return true;
@ -169,44 +211,7 @@ bool Foam::functionObjects::writeDictionary::execute()
bool Foam::functionObjects::writeDictionary::write() bool Foam::functionObjects::writeDictionary::write()
{ {
firstChange_ = true; performCheck();
forAll(dictNames_, dicti)
{
const IOdictionary* dictptr =
obr_.cfindObject<IOdictionary>(dictNames_[dicti]);
if (dictptr)
{
checkDictionary(*dictptr, dicti);
}
else
{
bool processed = tryDirectory(obr_.time().timeName(), dicti);
if (!processed)
{
processed = tryDirectory(obr_.time().constant(), dicti);
}
if (!processed)
{
processed = tryDirectory(obr_.time().system(), dicti);
}
if (!processed)
{
writeHeader();
Info<< " Unable to locate dictionary " << dictNames_[dicti]
<< nl << endl;
IOobject::writeDivider(Info);
Info<< endl;
}
}
}
return true; return true;
} }

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2013-2016 OpenFOAM Foundation Copyright (C) 2013-2016 OpenFOAM Foundation
Copyright (C) 2016-2019 OpenCFD Ltd. Copyright (C) 2016-2022 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -31,15 +31,15 @@ Group
grpUtilitiesFunctionObjects grpUtilitiesFunctionObjects
Description Description
Writes dictionaries on start-up and on change. Reports dictionary contents on change.
SourceFiles SourceFiles
writeDictionary.C writeDictionary.C
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#ifndef functionObjects_writeDictionary_H #ifndef Foam_functionObjects_writeDictionary_H
#define functionObjects_writeDictionary_H #define Foam_functionObjects_writeDictionary_H
#include "regionFunctionObject.H" #include "regionFunctionObject.H"
#include "wordList.H" #include "wordList.H"
@ -58,18 +58,17 @@ namespace functionObjects
class writeDictionary class writeDictionary
: :
public regionFunctionObject public functionObjects::regionFunctionObject
{ {
// Private data // Private Data
//- Names of dictionaries to monitor //- Names of dictionaries to monitor
wordList dictNames_; wordList dictNames_;
//- List of changed dictionaries (only those registered to database) //- Digest of dictionary contents
List<SHA1Digest> digests_; List<SHA1Digest> digests_;
//- Flag to indicate the first time that a dictionary is been changed //- First time that checking has been called (per execution cycle)
//- (per call to execute)
bool firstChange_; bool firstChange_;
@ -81,9 +80,12 @@ class writeDictionary
//- Helper to check and write the dictionary if its sha1 has changed //- Helper to check and write the dictionary if its sha1 has changed
void checkDictionary(const dictionary& dict, const label dicti); void checkDictionary(const dictionary& dict, const label dicti);
//- Helper to write the dictionary if found at location //- Attempt read dictionary at location
bool tryDirectory(const word& location, const label dicti); bool tryDirectory(const word& location, const label dicti);
//- Check all dictionaries
bool performCheck();
//- No copy construct //- No copy construct
writeDictionary(const writeDictionary&) = delete; writeDictionary(const writeDictionary&) = delete;