From 2ae4bf73d9415973a485816225c59e9d761b7035 Mon Sep 17 00:00:00 2001 From: Will Bainbridge <http://cfd.direct> Date: Wed, 27 Jun 2018 11:45:58 +0100 Subject: [PATCH] fileHandler: Added flush method This method waits until all the threads have completed IO operations and then clears any cached information about the files on disk. This replaces the deactivation of threading by means of zeroing the buffer size when writing and reading of a file happen in sequence. It also allows paraFoam to update the list of available times. Patch contributed by Mattijs Janssens Resolves bug report https://bugs.openfoam.org/view.php?id=2962 --- .../twoPhaseMixtureThermo.C | 12 +++-------- .../mesh/manipulation/setSet/setSet.C | 10 ++++++---- .../mesh/manipulation/topoSet/topoSet.C | 11 +++++----- .../decomposePar/decomposePar.C | 20 +++++++++---------- .../graphics/PVReaders/vtkPVFoam/vtkPVFoam.C | 10 ++++------ .../PVReaders/vtkPVFoam/vtkPVFoamUpdateInfo.C | 6 +++++- .../collatedFileOperation.C | 12 +++++++++++ .../collatedFileOperation.H | 3 +++ .../fileOperation/fileOperation.C | 11 ++++++++++ .../fileOperation/fileOperation.H | 3 +++ .../masterUncollatedFileOperation.C | 7 +++++++ .../masterUncollatedFileOperation.H | 3 +++ 12 files changed, 71 insertions(+), 37 deletions(-) diff --git a/applications/solvers/multiphase/compressibleInterFoam/twoPhaseMixtureThermo/twoPhaseMixtureThermo.C b/applications/solvers/multiphase/compressibleInterFoam/twoPhaseMixtureThermo/twoPhaseMixtureThermo.C index f1145196b1a..762f487ad16 100644 --- a/applications/solvers/multiphase/compressibleInterFoam/twoPhaseMixtureThermo/twoPhaseMixtureThermo.C +++ b/applications/solvers/multiphase/compressibleInterFoam/twoPhaseMixtureThermo/twoPhaseMixtureThermo.C @@ -50,12 +50,6 @@ Foam::twoPhaseMixtureThermo::twoPhaseMixtureThermo thermo1_(nullptr), thermo2_(nullptr) { - // Note: we're writing files to be read in immediately afterwards. - // Avoid any thread-writing problems. - float bufSz = - fileOperations::collatedFileOperation::maxThreadFileBufferSize; - fileOperations::collatedFileOperation::maxThreadFileBufferSize = 0; - { volScalarField T1(IOobject::groupName("T", phase1Name()), T_); T1.write(); @@ -66,9 +60,9 @@ Foam::twoPhaseMixtureThermo::twoPhaseMixtureThermo T2.write(); } - fileOperations::collatedFileOperation::maxThreadFileBufferSize = - bufSz; - + // Note: we're writing files to be read in immediately afterwards. + // Avoid any thread-writing problems. + fileHandler().flush(); thermo1_ = rhoThermo::New(U.mesh(), phase1Name()); thermo2_ = rhoThermo::New(U.mesh(), phase2Name()); diff --git a/applications/utilities/mesh/manipulation/setSet/setSet.C b/applications/utilities/mesh/manipulation/setSet/setSet.C index 7735602a137..bc800b920ae 100644 --- a/applications/utilities/mesh/manipulation/setSet/setSet.C +++ b/applications/utilities/mesh/manipulation/setSet/setSet.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation \\/ M anipulation | Copyright (C) 2017-2018 OpenCFD Ltd. ------------------------------------------------------------------------------- License @@ -51,7 +51,6 @@ Description #include "faceZoneSet.H" #include "pointZoneSet.H" #include "timeSelector.H" -#include "collatedFileOperation.H" #include <stdio.h> @@ -283,6 +282,9 @@ void removeZone { WarningInFunction << "Failed writing zone " << setName << endl; } + zones.write(); + // Force flushing so we know it has finished writing + fileHandler().flush(); } } @@ -541,6 +543,8 @@ bool doCommand << "Failed writing set " << currentSet.objectPath() << endl; } + // Make sure writing is finished + fileHandler().flush(); } } } @@ -732,8 +736,6 @@ int main(int argc, char *argv[]) // Specific to topoSet/setSet: quite often we want to block upon writing // a set so we can immediately re-read it. So avoid use of threading // for set writing. - fileOperations::collatedFileOperation::maxThreadFileBufferSize = 0; - timeSelector::addOptions(true, false); #include "addRegionOption.H" argList::addBoolOption("noVTK", "Do not write VTK files"); diff --git a/applications/utilities/mesh/manipulation/topoSet/topoSet.C b/applications/utilities/mesh/manipulation/topoSet/topoSet.C index 225cd611d4a..9878b75b3c5 100644 --- a/applications/utilities/mesh/manipulation/topoSet/topoSet.C +++ b/applications/utilities/mesh/manipulation/topoSet/topoSet.C @@ -43,7 +43,6 @@ Description #include "faceZoneSet.H" #include "pointZoneSet.H" #include "IOdictionary.H" -#include "collatedFileOperation.H" using namespace Foam; @@ -91,6 +90,7 @@ void removeZone { WarningInFunction << "Failed writing zone " << setName << endl; } + fileHandler().flush(); } } @@ -199,11 +199,6 @@ polyMesh::readUpdateState meshReadUpdate(polyMesh& mesh) int main(int argc, char *argv[]) { - // Specific to topoSet/setSet: quite often we want to block upon writing - // a set so we can immediately re-read it. So avoid use of threading - // for set writing. - fileOperations::collatedFileOperation::maxThreadFileBufferSize = 0; - timeSelector::addOptions(true, false); #include "addDictOption.H" #include "addRegionOption.H" @@ -307,6 +302,7 @@ int main(int argc, char *argv[]) << "Failed writing set " << currentSet().objectPath() << endl; } + fileHandler().flush(); } break; @@ -347,6 +343,7 @@ int main(int argc, char *argv[]) << "Failed writing set " << currentSet().objectPath() << endl; } + fileHandler().flush(); } break; @@ -359,6 +356,7 @@ int main(int argc, char *argv[]) << "Failed writing set " << currentSet().objectPath() << endl; } + fileHandler().flush(); break; case topoSetSource::INVERT: @@ -370,6 +368,7 @@ int main(int argc, char *argv[]) << "Failed writing set " << currentSet().objectPath() << endl; } + fileHandler().flush(); break; case topoSetSource::REMOVE: diff --git a/applications/utilities/parallelProcessing/decomposePar/decomposePar.C b/applications/utilities/parallelProcessing/decomposePar/decomposePar.C index 92cbf96ba04..f11942fba95 100644 --- a/applications/utilities/parallelProcessing/decomposePar/decomposePar.C +++ b/applications/utilities/parallelProcessing/decomposePar/decomposePar.C @@ -108,7 +108,6 @@ Usage #include "pointFieldDecomposer.H" #include "lagrangianFieldDecomposer.H" #include "decompositionModel.H" -#include "collatedFileOperation.H" #include "faCFD.H" #include "emptyFaPatch.H" @@ -523,12 +522,6 @@ int main(int argc, char *argv[]) // Decompose the mesh if (!decomposeFieldsOnly) { - // Disable buffering when writing mesh since we need to read - // it later on when decomposing the fields - float bufSz = - fileOperations::collatedFileOperation::maxThreadFileBufferSize; - fileOperations::collatedFileOperation::maxThreadFileBufferSize = 0; - mesh.decomposeMesh(); mesh.writeDecomposition(decomposeSets); @@ -587,8 +580,7 @@ int main(int argc, char *argv[]) << " for use in manual decomposition." << endl; } - fileOperations::collatedFileOperation::maxThreadFileBufferSize = - bufSz; + fileHandler().flush(); } @@ -1486,8 +1478,14 @@ int main(int argc, char *argv[]) fieldDecomposer.decomposeFields(areaScalarFields); fieldDecomposer.decomposeFields(areaVectorFields); - fieldDecomposer.decomposeFields(areaSphericalTensorFields); - fieldDecomposer.decomposeFields(areaSymmTensorFields); + fieldDecomposer.decomposeFields + ( + areaSphericalTensorFields + ); + fieldDecomposer.decomposeFields + ( + areaSymmTensorFields + ); fieldDecomposer.decomposeFields(areaTensorFields); fieldDecomposer.decomposeFields(edgeScalarFields); diff --git a/applications/utilities/postProcessing/graphics/PVReaders/vtkPVFoam/vtkPVFoam.C b/applications/utilities/postProcessing/graphics/PVReaders/vtkPVFoam/vtkPVFoam.C index 3dc56dc5d0f..1cf6e69aaf7 100644 --- a/applications/utilities/postProcessing/graphics/PVReaders/vtkPVFoam/vtkPVFoam.C +++ b/applications/utilities/postProcessing/graphics/PVReaders/vtkPVFoam/vtkPVFoam.C @@ -194,7 +194,8 @@ int Foam::vtkPVFoam::setTime(const std::vector<double>& requestTimes) Time& runTime = dbPtr_(); - // Get times list + // Get times list. Flush first to force refresh. + fileHandler().flush(); instantList Times = runTime.times(); int nearestIndex = timeIndex_; @@ -301,11 +302,6 @@ Foam::vtkPVFoam::vtkPVFoam fileName FileName(vtkFileName); - // Make sure not to use the threaded version - it does not like - // being loaded as a shared library - static cleanup order is problematic. - // For now just disable the threaded writer. - fileOperations::collatedFileOperation::maxThreadFileBufferSize = 0; - // avoid argList and get rootPath/caseName directly from the file fileName fullCasePath(FileName.path()); @@ -729,6 +725,8 @@ std::vector<double> Foam::vtkPVFoam::findTimes(const bool skipZero) const if (dbPtr_.valid()) { const Time& runTime = dbPtr_(); + // Get times list. Flush first to force refresh. + fileHandler().flush(); instantList timeLst = runTime.times(); // find the first time for which this mesh appears to exist diff --git a/applications/utilities/postProcessing/graphics/PVReaders/vtkPVFoam/vtkPVFoamUpdateInfo.C b/applications/utilities/postProcessing/graphics/PVReaders/vtkPVFoam/vtkPVFoamUpdateInfo.C index 26ef1d660c2..5a5b0222eaa 100644 --- a/applications/utilities/postProcessing/graphics/PVReaders/vtkPVFoam/vtkPVFoamUpdateInfo.C +++ b/applications/utilities/postProcessing/graphics/PVReaders/vtkPVFoam/vtkPVFoamUpdateInfo.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation \\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd. ------------------------------------------------------------------------------- License @@ -225,6 +225,9 @@ void Foam::vtkPVFoam::updateInfoLagrangian // List of lagrangian objects across all times HashSet<fileName> names; + // Get times list. Flush first to force refresh. + fileHandler().flush(); + for (const instant& t : dbPtr_().times()) { names.insert @@ -697,6 +700,7 @@ void Foam::vtkPVFoam::updateInfoLagrangianFields // to some of the clouds. HashTable<wordHashSet> fields; + fileHandler().flush(); for (const instant& t : dbPtr_().times()) { for (const auto& cloudName : cloudNames) diff --git a/src/OpenFOAM/global/fileOperations/collatedFileOperation/collatedFileOperation.C b/src/OpenFOAM/global/fileOperations/collatedFileOperation/collatedFileOperation.C index 058ff4728ee..67d1985ec05 100644 --- a/src/OpenFOAM/global/fileOperations/collatedFileOperation/collatedFileOperation.C +++ b/src/OpenFOAM/global/fileOperations/collatedFileOperation/collatedFileOperation.C @@ -611,6 +611,18 @@ bool Foam::fileOperations::collatedFileOperation::writeObject } } +void Foam::fileOperations::collatedFileOperation::flush() const +{ + if (debug) + { + Pout<< "collatedFileOperation::flush : clearing and waiting for thread" + << endl; + } + masterUncollatedFileOperation::flush(); + // Wait for thread to finish (note: also removes thread) + writer_.waitAll(); +} + Foam::word Foam::fileOperations::collatedFileOperation::processorsDir ( diff --git a/src/OpenFOAM/global/fileOperations/collatedFileOperation/collatedFileOperation.H b/src/OpenFOAM/global/fileOperations/collatedFileOperation/collatedFileOperation.H index f03e2ae43a1..f24dc52c9df 100644 --- a/src/OpenFOAM/global/fileOperations/collatedFileOperation/collatedFileOperation.H +++ b/src/OpenFOAM/global/fileOperations/collatedFileOperation/collatedFileOperation.H @@ -155,6 +155,9 @@ public: // Other + //- Forcibly wait until all output done. Flush any cached data + virtual void flush() const; + //- Actual name of processors dir virtual word processorsDir(const IOobject&) const; diff --git a/src/OpenFOAM/global/fileOperations/fileOperation/fileOperation.C b/src/OpenFOAM/global/fileOperations/fileOperation/fileOperation.C index 927ca6f96c5..7f556ae3803 100644 --- a/src/OpenFOAM/global/fileOperations/fileOperation/fileOperation.C +++ b/src/OpenFOAM/global/fileOperations/fileOperation/fileOperation.C @@ -991,6 +991,17 @@ Foam::label Foam::fileOperation::nProcs } +void Foam::fileOperation::flush() const +{ + if (debug) + { + Pout<< "fileOperation::flush : clearing processor directories cache" + << endl; + } + procsDirs_.clear(); +} + + Foam::fileName Foam::fileOperation::processorsCasePath ( const IOobject& io, diff --git a/src/OpenFOAM/global/fileOperations/fileOperation/fileOperation.H b/src/OpenFOAM/global/fileOperations/fileOperation/fileOperation.H index b236e9eb458..214ead34db4 100644 --- a/src/OpenFOAM/global/fileOperations/fileOperation/fileOperation.H +++ b/src/OpenFOAM/global/fileOperations/fileOperation/fileOperation.H @@ -514,6 +514,9 @@ public: virtual void setTime(const Time&) const {} + //- Forcibly wait until all output done. Flush any cached data + virtual void flush() const; + //- Generate path (like io.path) from root+casename with any // 'processorXXX' replaced by procDir (usually 'processsors') fileName processorsCasePath diff --git a/src/OpenFOAM/global/fileOperations/masterUncollatedFileOperation/masterUncollatedFileOperation.C b/src/OpenFOAM/global/fileOperations/masterUncollatedFileOperation/masterUncollatedFileOperation.C index b1d1f031308..18ff87a6cb6 100644 --- a/src/OpenFOAM/global/fileOperations/masterUncollatedFileOperation/masterUncollatedFileOperation.C +++ b/src/OpenFOAM/global/fileOperations/masterUncollatedFileOperation/masterUncollatedFileOperation.C @@ -2561,6 +2561,13 @@ Foam::fileOperations::masterUncollatedFileOperation::NewOFstream } +void Foam::fileOperations::masterUncollatedFileOperation::flush() const +{ + fileOperation::flush(); + times_.clear(); +} + + Foam::label Foam::fileOperations::masterUncollatedFileOperation::addWatch ( const fileName& fName diff --git a/src/OpenFOAM/global/fileOperations/masterUncollatedFileOperation/masterUncollatedFileOperation.H b/src/OpenFOAM/global/fileOperations/masterUncollatedFileOperation/masterUncollatedFileOperation.H index 03c100921d1..545f20041b7 100644 --- a/src/OpenFOAM/global/fileOperations/masterUncollatedFileOperation/masterUncollatedFileOperation.H +++ b/src/OpenFOAM/global/fileOperations/masterUncollatedFileOperation/masterUncollatedFileOperation.H @@ -769,6 +769,9 @@ public: //- Callback for time change virtual void setTime(const Time&) const; + //- Forcibly wait until all output done. Flush any cached data + virtual void flush() const; + //- Return cached times const HashPtrTable<instantList>& times() const { -- GitLab