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 |
-------------------------------------------------------------------------------
Copyright (C) 2013-2017 OpenFOAM Foundation
Copyright (C) 2016-2020 OpenCFD Ltd.
Copyright (C) 2016-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -56,11 +56,10 @@ void Foam::functionObjects::writeDictionary::writeHeader()
{
if (firstChange_)
{
Info<< type() << " " << name() << " write:" << nl << endl;
IOobject::writeDivider(Info);
Info<< endl;
firstChange_ = false;
Info<< type() << ' ' << name() << " write:" << nl << nl;
IOobject::writeDivider(Info) << endl;
}
}
@ -71,16 +70,16 @@ void Foam::functionObjects::writeDictionary::checkDictionary
const label dicti
)
{
if (dict.digest() != digests_[dicti])
const auto digest(dict.digest());
if (digests_[dicti] != digest)
{
digests_[dicti] = digest;
writeHeader();
digests_[dicti] = dict.digest();
Info<< dict.dictName() << dict << nl;
IOobject::writeDivider(Info);
Info<< endl;
dict.writeEntry(Info);
Info<< nl;
IOobject::writeDivider(Info) << endl;
}
}
@ -121,13 +120,12 @@ Foam::functionObjects::writeDictionary::writeDictionary
const dictionary& dict
)
:
regionFunctionObject(name, runTime, dict),
functionObjects::regionFunctionObject(name, runTime, dict),
dictNames_(),
digests_(),
firstChange_(true)
{
read(dict);
execute();
}
@ -137,21 +135,18 @@ bool Foam::functionObjects::writeDictionary::read(const dictionary& dict)
{
regionFunctionObject::read(dict);
wordList dictNames(dict.get<wordList>("dictNames"));
wordHashSet uniqueNames(dictNames);
dictNames_ = uniqueNames.toc();
// Make unique
dictNames_ = wordHashSet(dict.get<wordList>("dictNames")).sortedToc();
digests_.setSize(dictNames_.size(), SHA1Digest());
digests_.resize(dictNames_.size());
digests_ = SHA1Digest();
Info<< type() << " " << name() << ": monitoring dictionaries:" << nl;
if (dictNames_.size())
Info<< type() << ' ' << name() << ": monitoring dictionaries:" << nl;
for (const word& dictName : dictNames_)
{
for (const word & dictName : dictNames_)
{
Info<< " " << dictName << endl;
}
Info<< " " << dictName << nl;
}
else
if (dictNames_.empty())
{
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()
{
return true;
@ -169,44 +211,7 @@ bool Foam::functionObjects::writeDictionary::execute()
bool Foam::functionObjects::writeDictionary::write()
{
firstChange_ = true;
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;
}
}
}
performCheck();
return true;
}

View File

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