ENH: Foam::readLink(..)

- recover the target of symbolic links.
  This is needed when re-creating a file tree on another rank.

ENH: handle checkGzip, followLink flags in fileHander filePath()

- previously just relied on the backend defaults, now pass through
- separate init(...) for common constructor init steps
This commit is contained in:
mattijs 2022-11-24 09:00:00 +00:00 committed by Mark Olesen
parent 478c1b2312
commit 286c6ce7d8
18 changed files with 296 additions and 135 deletions

View File

@ -940,13 +940,24 @@ bool Foam::ln(const fileName& src, const fileName& dst)
if (MSwindows::debug)
{
Info<< "MSwindows does not support ln - softlinking" << endl;
Info<< "MSwindows does not support softlinks" << endl;
}
return false;
}
Foam::fileName Foam::readLink(const fileName& link)
{
if (MSwindows::debug)
{
Info<< "MSwindows does not support softlinks" << endl;
}
return fileName();
}
bool Foam::mv(const fileName& src, const fileName& dst, const bool followLink)
{
if (MSwindows::debug)
@ -954,7 +965,7 @@ bool Foam::mv(const fileName& src, const fileName& dst, const bool followLink)
Info<< "Move : " << src << " to " << dst << endl;
}
// Ignore an empty names => always false
// Ignore empty names => always false
if (src.empty() || dst.empty())
{
return false;

View File

@ -1169,7 +1169,7 @@ bool Foam::ln(const fileName& src, const fileName& dst)
{
//InfoInFunction
Pout<< FUNCTION_NAME
<< " : Create softlink from : " << src << " to " << dst << endl;
<< " : Create symlink from : " << src << " to " << dst << endl;
if ((POSIX::debug & 2) && !Pstream::master())
{
error::printStack(Pout);
@ -1216,6 +1216,40 @@ bool Foam::ln(const fileName& src, const fileName& dst)
}
Foam::fileName Foam::readLink(const fileName& link)
{
if (POSIX::debug)
{
//InfoInFunction
Pout<< FUNCTION_NAME
<< " : Returning symlink destination for : " << link << endl;
if ((POSIX::debug & 2) && !Pstream::master())
{
error::printStack(Pout);
}
}
if (link.empty())
{
// Treat an empty path as a no-op.
return fileName();
}
fileName result;
result.resize(1024); // Should be large enough (mostly relative anyhow)
ssize_t len = ::readlink(link.c_str(), &(result.front()), result.size());
if (len > 0)
{
result.resize(len);
return result;
}
// Failure: return empty result
return fileName();
}
bool Foam::mv(const fileName& src, const fileName& dst, const bool followLink)
{
if (POSIX::debug)
@ -1228,7 +1262,7 @@ bool Foam::mv(const fileName& src, const fileName& dst, const bool followLink)
}
}
// Ignore an empty names => always false
// Ignore empty names => always false
if (src.empty() || dst.empty())
{
return false;

View File

@ -195,13 +195,14 @@ void Foam::Time::setControls()
// Check if time directory exists
// If not increase time precision to see if it is formatted differently.
// Note: do not use raw fileHandler().exists(...) since does not check
// Note: - do not use raw fileHandler().exists(...) since does not check
// alternative processorsDDD directories naming
if (fileHandler().filePath(timePath()).empty())
// - do not look for compressed (is directory)
if (fileHandler().filePath(timePath(), false).empty())
{
int oldPrecision = precision_;
const int oldPrecision = precision_;
int requiredPrecision = -1;
bool found = false;
word oldTime(timeName());
for
(
@ -218,14 +219,10 @@ void Foam::Time::setControls()
{
break;
}
oldTime = newTime;
oldTime = std::move(newTime);
// Check the existence of the time directory with the new format
//found = fileHandler().exists(timePath(), false);
const fileName dirName(fileHandler().filePath(timePath()));
found = !dirName.empty();
if (found)
// Does a time directory exist with the new format?
if (!fileHandler().filePath(timePath(), false).empty())
{
requiredPrecision = precision_;
}

View File

@ -414,6 +414,15 @@ public:
return runTimeModifiable_;
}
//- Set re-reading support on/off (use with caution).
// \return the previous value
Switch runTimeModifiable(const Switch sw) noexcept
{
Switch old(runTimeModifiable_);
runTimeModifiable_ = sw;
return old;
}
//- Read control dictionary, update controls and time
virtual bool read();

View File

@ -579,7 +579,8 @@ bool Foam::Time::writeObject
(
fileHandler().filePath
(
objectRegistry::path(previousWriteTimes_.pop())
objectRegistry::path(previousWriteTimes_.pop()),
false // No .gz check (is directory)
)
);
}

View File

@ -241,6 +241,51 @@ static void printHostsSubscription(const UList<string>& hostProcs)
Info<< ')' << nl;
}
static bool printRootsSubscription
(
const UList<string>& hostProcs,
const UList<fileName>& roots
)
{
if (hostProcs.size() == roots.size()+1)
{
// Sort roots according to hostProc
DynamicList<string> sortedProcs;
DynamicList<label> sortedRoots;
forAll(roots, i)
{
const fileName& root = roots[i];
const string& host = hostProcs[i+1];
const label index = sortedProcs.find(host);
if (index == -1)
{
sortedProcs.append(host);
sortedRoots.append(i);
}
else if (roots[sortedRoots[index]] != root)
{
// Not properly sorted...
return false;
}
}
Info<< "Roots :\n(" << nl;
forAll(sortedProcs, i)
{
Info<< " (" << sortedProcs[i].c_str() << ' '
<< roots[sortedRoots[i]] << ')' << nl;
}
Info<< ')' << nl;
return true;
}
return false;
}
} // End namespace Foam
@ -1184,6 +1229,7 @@ void Foam::argList::parse
stringList hostMachine;
stringList hostProcs;
const int writeHostsSwitch = Foam::debug::infoSwitch("writeHosts", 1);
const int writeRootsSwitch = Foam::debug::infoSwitch("writeRoots", 1);
// Collect machine/pid, and check that the build is identical
if (runControl_.parRun())
@ -1615,7 +1661,7 @@ void Foam::argList::parse
// Clear here to ensures it doesn't show in the jobInfo
hostProcs.clear();
}
if (!debug::infoSwitch("writeRoots", 1))
if (!writeRootsSwitch)
{
roots.clear();
}
@ -1654,7 +1700,17 @@ void Foam::argList::parse
}
if (roots.size())
{
Info<< "Roots : " << roots << nl;
bool hasPrinted = false;
if (writeRootsSwitch == 1)
{
// Compact output
hasPrinted = printRootsSubscription(hostProcs, roots);
}
if (writeRootsSwitch && !hasPrinted)
{
// Full output
Info<< "Roots : " << roots << nl;
}
}
Info<< "Pstream initialized with:" << nl
<< " floatTransfer : " << Pstream::floatTransfer << nl
@ -2000,7 +2056,7 @@ bool Foam::argList::checkRootCase() const
return false;
}
const fileName pathDir(fileHandler().filePath(path()));
const fileName pathDir(fileHandler().filePath(path(), false));
if (checkProcessorDirectories_ && pathDir.empty() && Pstream::master())
{

View File

@ -258,6 +258,17 @@ bool Foam::fileOperations::collatedFileOperation::appendObject
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
void Foam::fileOperations::collatedFileOperation::init(bool verbose)
{
verbose = (verbose && Foam::infoDetailLevel > 0);
if (verbose)
{
this->printBanner(ioRanks_.size());
}
}
Foam::fileOperations::collatedFileOperation::collatedFileOperation
(
bool verbose
@ -281,10 +292,7 @@ Foam::fileOperations::collatedFileOperation::collatedFileOperation
nProcs_(Pstream::nProcs()),
ioRanks_(ioRanks())
{
if (verbose && Foam::infoDetailLevel > 0)
{
this->printBanner(ioRanks_.size());
}
init(verbose);
}
@ -302,10 +310,7 @@ Foam::fileOperations::collatedFileOperation::collatedFileOperation
nProcs_(Pstream::nProcs()),
ioRanks_(ioRanks)
{
if (verbose && Foam::infoDetailLevel > 0)
{
this->printBanner(ioRanks_.size());
}
init(verbose);
}

View File

@ -67,6 +67,11 @@ class collatedFileOperation
:
public masterUncollatedFileOperation
{
// Private Member Functions
//- Any initialisation steps after constructing
void init(bool verbose);
protected:
// Protected Data

View File

@ -123,6 +123,17 @@ Foam::labelList Foam::fileOperations::hostCollatedFileOperation::subRanks
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
void Foam::fileOperations::hostCollatedFileOperation::init(bool verbose)
{
verbose = (verbose && Foam::infoDetailLevel > 0);
if (verbose)
{
this->printBanner(ioRanks_.size());
}
}
Foam::fileOperations::hostCollatedFileOperation::hostCollatedFileOperation
(
bool verbose
@ -140,10 +151,7 @@ Foam::fileOperations::hostCollatedFileOperation::hostCollatedFileOperation
false // verbose
)
{
if (verbose && Foam::infoDetailLevel > 0)
{
this->printBanner(ioRanks_.size());
}
init(verbose);
}

View File

@ -77,12 +77,14 @@ class hostCollatedFileOperation
:
public collatedFileOperation
{
// Private Member Functions
// Private Member Functions
//- Any initialisation steps after constructing
void init(bool verbose);
//- Get the list of processors part of this set
static labelList subRanks(const label n);
public:
//- Runtime type information

View File

@ -59,6 +59,8 @@ namespace Foam
);
}
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
const Foam::Enum<Foam::fileOperation::pathType>
Foam::fileOperation::pathTypeNames_
({
@ -792,7 +794,12 @@ bool Foam::fileOperation::writeObject
}
Foam::fileName Foam::fileOperation::filePath(const fileName& fName) const
Foam::fileName Foam::fileOperation::filePath
(
const fileName& fName,
const bool checkGzip,
const bool followLink
) const
{
if (debug)
{
@ -820,7 +827,7 @@ Foam::fileName Foam::fileOperation::filePath(const fileName& fName) const
const fileName& procDir = dirIdx.first();
fileName collatedName(path/procDir/local);
if (exists(collatedName))
if (exists(collatedName, checkGzip, followLink))
{
if (debug)
{
@ -831,7 +838,7 @@ Foam::fileName Foam::fileOperation::filePath(const fileName& fName) const
}
}
if (exists(fName))
if (exists(fName, checkGzip, followLink))
{
if (debug)
{
@ -844,7 +851,8 @@ Foam::fileName Foam::fileOperation::filePath(const fileName& fName) const
{
Pout<< "fileOperation::filePath : Not found" << endl;
}
return fileName::null;
return fileName();
}
@ -992,7 +1000,8 @@ Foam::instantList Foam::fileOperation::findTimes
if (debug)
{
Pout<< "fileOperation::findTimes : Found times:" << times << endl;
Pout<< "fileOperation::findTimes : Found times:" << flatOutput(times)
<< endl;
}
return times;
}
@ -1177,7 +1186,7 @@ Foam::fileNameList Foam::fileOperation::readObjects
fileName path(db.path(instance, db.dbDir()/local));
newInstance = word::null;
newInstance.clear();
fileNameList objectNames;
if (Foam::isDir(path))
@ -1311,7 +1320,7 @@ Foam::fileName Foam::fileOperation::processorsPath
return dir.path()/procsDir;
}
return fileName::null;
return fileName();
}
@ -1502,7 +1511,7 @@ const Foam::fileOperation& Foam::fileHandler()
{
if (!fileOperation::fileHandlerPtr_)
{
word handler(getEnv("FOAM_FILEHANDLER"));
word handler(Foam::getEnv("FOAM_FILEHANDLER"));
if (handler.empty())
{

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2017 OpenFOAM Foundation
Copyright (C) 2020-2021 OpenCFD Ltd.
Copyright (C) 2020-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -70,6 +70,8 @@ class fileOperation
{
public:
// Public Data Types
//- Enumeration for the location of an IOobject
enum pathType : int
{
@ -274,7 +276,7 @@ public:
virtual bool exists
(
const fileName&,
const bool checkGzip=true,
const bool checkGzip = true,
const bool followLink = true
) const = 0;
@ -290,7 +292,7 @@ public:
virtual bool isFile
(
const fileName&,
const bool checkGzip=true,
const bool checkGzip = true,
const bool followLink = true
) const = 0;
@ -367,14 +369,6 @@ public:
const bool emptyOnly = false
) const = 0;
// //- Open a shared library. Return handle to library. Print error
// // message if library cannot be loaded (check = true)
// virtual void* dlOpen
// (
// const fileName& lib,
// const bool check = true
// ) const = 0;
// (reg)IOobject functionality
@ -456,9 +450,14 @@ public:
// Filename (not IOobject) operations
//- Search for a file or directory. Use IOobject version in
// preference
virtual fileName filePath(const fileName&) const;
//- Search for a file or directory.
//- Use IOobject version in preference
virtual fileName filePath
(
const fileName&,
const bool checkGzip = true,
const bool followLink = true
) const;
//- Generate an ISstream that reads a file
virtual autoPtr<ISstream> NewIFstream(const fileName&) const = 0;
@ -607,6 +606,24 @@ public:
};
//- Read pathType as an integer value
inline Istream& operator>>(Istream& is, fileOperation::pathType& b)
{
int val(0);
is >> val;
b = static_cast<fileOperation::pathType>(val);
return is;
}
//- Write pathType as an integer value
inline Ostream& operator<<(Ostream& os, const fileOperation::pathType b)
{
os << static_cast<int>(b);
return os;
}
// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
// Note: defined in fileOperation.C

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2017-2018 OpenFOAM Foundation
Copyright (C) 2019-2021 OpenCFD Ltd.
Copyright (C) 2019-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -50,17 +50,37 @@ Foam::fileOperations::fileOperationInitialise::fileOperationInitialise
char**& argv
)
{
// Filter out commonly known arguments
const string s("-ioRanks");
// Check for -ioRanks, which requires an argument
int index = -1;
for (int i=1; i<argc-1; i++)
for (int argi = 1; argi < argc; ++argi)
{
if (argv[i] == s)
if (argv[argi][0] == '-')
{
index = i;
Foam::setEnv("FOAM_IORANKS", argv[i+1], true);
break;
const char *optName = &argv[argi][1];
if (strcmp(optName, "ioRanks") == 0)
{
if (argi < argc-1)
{
index = argi;
Foam::setEnv("FOAM_IORANKS", argv[argi+1], true);
break;
}
else
{
// No argument to -ioRanks.
// Give error message as in argList.
// Slight problem: Pstream not yet initialised so
// - no master-only output
// - no early exit
Info<< nl
<< "Error: option '-ioRanks' requires a list of"
" IO ranks as argument" << nl << nl;
//Pstream::exit(1); // works for serial and parallel
}
}
}
}

View File

@ -715,21 +715,7 @@ Foam::fileOperations::masterUncollatedFileOperation::read
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::fileOperations::masterUncollatedFileOperation::
masterUncollatedFileOperation
(
bool verbose
)
:
fileOperation
(
UPstream::allocateCommunicator
(
UPstream::worldComm,
subRanks(Pstream::nProcs())
)
),
myComm_(comm_)
void Foam::fileOperations::masterUncollatedFileOperation::init(bool verbose)
{
verbose = (verbose && Foam::infoDetailLevel > 0);
@ -763,6 +749,26 @@ masterUncollatedFileOperation
}
Foam::fileOperations::masterUncollatedFileOperation::
masterUncollatedFileOperation
(
bool verbose
)
:
fileOperation
(
UPstream::allocateCommunicator
(
UPstream::worldComm,
subRanks(Pstream::nProcs())
)
),
myComm_(comm_)
{
init(verbose);
}
Foam::fileOperations::masterUncollatedFileOperation::
masterUncollatedFileOperation
(
@ -773,35 +779,7 @@ masterUncollatedFileOperation
fileOperation(comm),
myComm_(-1)
{
verbose = (verbose && Foam::infoDetailLevel > 0);
if (verbose)
{
DetailInfo
<< "I/O : " << typeName
<< " (maxMasterFileBufferSize " << maxMasterFileBufferSize << ')'
<< endl;
}
if (IOobject::fileModificationChecking == IOobject::timeStampMaster)
{
if (verbose)
{
WarningInFunction
<< "Resetting fileModificationChecking to timeStamp" << endl;
}
IOobject::fileModificationChecking = IOobject::timeStamp;
}
else if (IOobject::fileModificationChecking == IOobject::inotifyMaster)
{
if (verbose)
{
WarningInFunction
<< "Resetting fileModificationChecking to inotify"
<< endl;
}
IOobject::fileModificationChecking = IOobject::inotify;
}
init(verbose);
}

View File

@ -88,6 +88,11 @@ class masterUncollatedFileOperation
:
public fileOperation
{
// Private Member Functions
//- Any initialisation steps after constructing
void init(bool verbose);
protected:
// Protected Data
@ -351,7 +356,7 @@ protected:
(
(isFile_ ? Foam::isFile(f) : Foam::isDir(f))
? f
: fileName::null
: fileName::null // const reference, not temporary
);
}
};
@ -426,7 +431,7 @@ protected:
(
const bool checkGlobal,
const bool isFile,
const IOobject&,
const IOobject& io,
const bool search,
pathType& searchType,
word& processorsDir,
@ -615,14 +620,6 @@ public:
const bool emptyOnly = false
) const;
// //- Open a shared library. Return handle to library. Print error
// // message if library cannot be loaded (check = true)
// virtual void* dlOpen
// (
// const fileName& lib,
// const bool check = true
// ) const;
// (reg)IOobject functinality

View File

@ -176,6 +176,18 @@ Foam::fileOperations::uncollatedFileOperation::lookupProcessorsPath
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
void Foam::fileOperations::uncollatedFileOperation::init(bool verbose)
{
verbose = (verbose && Foam::infoDetailLevel > 0);
if (verbose)
{
DetailInfo
<< "I/O : " << typeName << endl;
}
}
Foam::fileOperations::uncollatedFileOperation::uncollatedFileOperation
(
bool verbose
@ -183,11 +195,7 @@ Foam::fileOperations::uncollatedFileOperation::uncollatedFileOperation
:
fileOperation(Pstream::worldComm)
{
if (verbose)
{
DetailInfo
<< "I/O : " << typeName << endl;
}
init(verbose);
}

View File

@ -53,6 +53,11 @@ class uncollatedFileOperation
:
public fileOperation
{
// Private Member Functions
//- Any initialisation steps after constructing
void init(bool verbose);
protected:
// Protected Member Functions
@ -215,14 +220,6 @@ public:
const bool emptyOnly = false
) const;
// //- Open a shared library. Return handle to library. Print error
// // message if library cannot be loaded (check = true)
// virtual void* dlOpen
// (
// const fileName& lib,
// const bool check = true
// ) const;
// (reg)IOobject functionality

View File

@ -144,8 +144,8 @@ fileName::Type type(const fileName& name, const bool followLink=true);
bool exists
(
const fileName& name,
const bool checkGzip=true,
const bool followLink=true
const bool checkGzip = true,
const bool followLink = true
);
//- Does the name exist as a DIRECTORY in the file system?
@ -158,8 +158,8 @@ bool isDir(const fileName& name, const bool followLink=true);
bool isFile
(
const fileName& name,
const bool checkGzip=true,
const bool followLink=true
const bool checkGzip = true,
const bool followLink = true
);
//- Return size of file or -1 on failure (normally follows symbolic links).
@ -197,6 +197,13 @@ bool cp(const fileName& src, const fileName& dst, const bool followLink=true);
// but also produces a warning.
bool ln(const fileName& src, const fileName& dst);
//- Return the contents (target) of a symlink.
// For example, returns \c target for <code>ln -s target linkName</code>
//
// An empty link name is a no-op that always returns an empty string.
// Following a non-link is an error that returns an empty string.
fileName readLink(const fileName& link);
//- Rename src to dst.
// An empty source or destination name is a no-op that always returns false.
bool mv