ENH: improve OFstream append behaviour (#3160)

- previous support for file appending (largely unused) always
  specified opening with the std::ios_base::app flag.

  Now differentiate between append behaviours:

  APPEND_APP
  ~~~~~~~~~~
  Corresponds to std::ios_base::app behaviour:

  - Existing files will be preserved and a seek-to-end is performed at
    every write. With this mode seeks/repositioning within the file
    will effectively be ignored on output.

  APPEND_ATE
  ~~~~~~~~~~
  Largely approximates std::ios_base::ate behaviour:

  - Existing files will be preserved and a seek-to-end is performed
    immediately after opening, but not subsequently. Can use seekp()
    to overwrite parts of a file.
This commit is contained in:
Mark Olesen 2024-05-23 21:41:33 +02:00 committed by Kutalmış Berçin
parent 9f032057b4
commit ee895577ae
13 changed files with 412 additions and 131 deletions

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2022 OpenCFD Ltd.
Copyright (C) 2022-2024 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -32,10 +32,14 @@ Description
#include "IOstreams.H"
#include "OSspecific.H"
#include "argList.H"
#include "clock.H"
#include "Switch.H"
#include "ListOps.H"
using namespace Foam;
std::string time_stamp;
void listFiles(const fileName& dir)
{
wordList files = ListOps::create<word>
@ -55,25 +59,150 @@ void listFiles(const fileName& dir)
}
OSstream& printInfo(OFstream& os)
{
InfoErr
<< "open: " << os.name() << nl
<< "appending: " << Switch::name(os.is_appending())
<< " tellp: "<< os.stdStream().tellp()
<< " gz: " << Switch::name(os.compression()) << nl;
return InfoErr.stream();
}
void withHeader(OFstream& os)
{
const auto tellp = os.stdStream().tellp();
if (tellp <= 0)
{
InfoErr
<< "Add header" << nl;
os << "HEADER: " << time_stamp.c_str() << nl;
}
}
template<class OSstreamType>
void generateLines(OSstreamType& os, label count = 1)
{
for (label line = 1; line <= count; ++line)
{
os << "[" << line
<< "] =============================================" << nl;
}
}
template<class OSstreamType>
void generateContent
(
OSstreamType& os,
const bool with_seekend,
const bool test_overwrite = false,
const int64_t seek_out = -1
)
{
if (with_seekend)
{
os.stdStream().seekp(0, std::ios_base::end);
// OR? os.seek_end();
}
printInfo(os);
withHeader(os);
if (test_overwrite && seek_out >= 0)
{
InfoErr<< "... seekp(" << seek_out << ")" << nl;
auto& oss = os.stdStream();
// Actually std::streampos, but cannot increment that
int64_t pos(seek_out);
const int64_t tellp_end = oss.tellp();
if (pos >= 0 && pos < tellp_end)
{
InfoErr
<< "... fill from " << label(pos)
<< " to " << label(tellp_end) << nl;
oss.seekp(pos);
while (pos < tellp_end)
{
// Fill with char 'X', rely on streambuf buffering
oss << 'X';
++pos;
}
oss.seekp(seek_out);
os << "More content [at " << seek_out << ']' << endl;
}
}
generateLines(os, 4);
printInfo(os)
<< "... sleep" << endl;
listFiles(os.name().path());
sleep(2);
os << "[new content] +++++++++++++++++++++++++++++++++++" << endl;
}
template<class OSstreamType>
void generateOverwriteContent
(
OSstreamType& os,
const bool with_seekend,
const int64_t seek_out = -1
)
{
generateContent(os, with_seekend, true, seek_out);
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int main(int argc, char *argv[])
{
argList::addBoolOption("gz", "Use compression");
argList::addBoolOption("append", "Use append mode");
argList::addBoolOption("append-app", "Use append app mode");
argList::addBoolOption("append-ate", "Use append ate mode");
argList::addBoolOption("seekend", "Seek to end after non-append open");
argList::addOption("seek", "value", "Seek from start (default: 100)");
argList::addBoolOption("atomic", "Use atomic");
argList::addBoolOption("keep", "Do not remove test directory");
argList::addOption("write", "file", "test writing to file");
#include "setRootCase.H"
// Same time-stamp for all generated files
time_stamp = clock::dateTime();
const fileName baseDir("Test-OFstream-directory");
Foam::mkDir(baseDir);
InfoErr<< "mkdir: " << baseDir << endl;
Info<< "start:" << nl;
listFiles(baseDir);
const bool with_seekend = args.found("seekend");
const int seek_out = args.getOrDefault<int>("seek", 100);
IOstreamOption streamOpt;
if (args.found("gz"))
@ -83,10 +212,11 @@ int main(int argc, char *argv[])
IOstreamOption::appendType append =
(
args.found("append")
? IOstreamOption::APPEND
: IOstreamOption::NON_APPEND
args.found("append-app") ? IOstreamOption::APPEND_APP
: args.found("append-ate") ? IOstreamOption::APPEND_ATE
: IOstreamOption::NO_APPEND
);
IOstreamOption::atomicType atomic =
(
args.found("atomic")
@ -97,7 +227,6 @@ int main(int argc, char *argv[])
{
OFstream(baseDir/"dummy")() << "Some file content" << endl;
Foam::ln("dummy", baseDir/"Test2.txt");
Foam::ln("dummy", baseDir/"Test3.txt");
Foam::ln("dummy", baseDir/"Test4.txt");
Foam::ln("dummy", baseDir/"Test4.txt.gz");
@ -114,16 +243,31 @@ int main(int argc, char *argv[])
append
);
os << "=========================" << endl;
generateOverwriteContent(os, with_seekend, seek_out);
}
InfoErr<< "open: " << os.name() << endl;
InfoErr<< "... sleep" << endl;
{
OFstream os
(
atomic,
baseDir/"Test1-app.txt",
streamOpt,
IOstreamOption::APPEND_APP
);
listFiles(baseDir);
generateOverwriteContent(os, with_seekend, seek_out);
}
sleep(2);
{
OFstream os
(
atomic,
baseDir/"Test1-ate.txt",
streamOpt,
IOstreamOption::APPEND_ATE
);
os << "+++++++++++++++++++++++++++++++++++" << endl;
generateOverwriteContent(os, with_seekend, seek_out);
}
{
@ -132,39 +276,21 @@ int main(int argc, char *argv[])
atomic,
baseDir/"Test2.txt",
streamOpt
// NON_APPEND
);
os << "=========================" << endl;
InfoErr<< "open: " << os.name() << endl;
InfoErr<< "... sleep" << endl;
listFiles(baseDir);
sleep(2);
os << "+++++++++++++++++++++++++++++++++++" << endl;
generateContent(os, with_seekend);
}
{
OFstream os
(
atomic,
baseDir/"Test3.txt",
streamOpt,
IOstreamOption::APPEND
IOstreamOption::APPEND_APP
);
os << "=========================" << endl;
InfoErr<< "open: " << os.name() << endl;
InfoErr<< "... sleep" << endl;
listFiles(baseDir);
sleep(2);
os << "+++++++++++++++++++++++++++++++++++" << endl;
generateContent(os, with_seekend, with_seekend);
}
{
OFstream os
@ -174,35 +300,17 @@ int main(int argc, char *argv[])
IOstreamOption::COMPRESSED
);
os << "=========================" << endl;
InfoErr<< "open: " << os.name() << endl;
InfoErr<< "... sleep" << endl;
listFiles(baseDir);
sleep(2);
os << "+++++++++++++++++++++++++++++++++++" << endl;
// No seekend with COMPRESSED
generateContent(os, false);
}
{
OFstream os
(
IOstreamOption::ATOMIC,
baseDir/"Test5.txt"
// ASCII UNCOMPRESSED NON_APPEND
);
os << "=========================" << endl;
InfoErr<< "open: " << os.name() << endl;
InfoErr<< "... sleep" << endl;
listFiles(baseDir);
sleep(2);
os << "+++++++++++++++++++++++++++++++++++" << endl;
generateContent(os, with_seekend);
}
Info<< nl << "done:" << endl;

View File

@ -28,7 +28,8 @@ Class
Foam::IFstream
Description
Input from file stream, using an ISstream
Input from file stream as an ISstream, normally using \c std::ifstream
for the actual input.
SourceFiles
IFstream.C

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2017-2023 OpenCFD Ltd.
Copyright (C) 2017-2024 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -66,7 +66,7 @@ Foam::OFstream::OFstream
(
pathname,
streamOpt,
(IOstreamOption::appendType::APPEND == append),
append,
(IOstreamOption::atomicType::ATOMIC == atomic)
),
OSstream(*(ofstreamPointer::get()), pathname, streamOpt)

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2017-2023 OpenCFD Ltd.
Copyright (C) 2017-2024 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -28,7 +28,29 @@ Class
Foam::OFstream
Description
Output to file stream, using an OSstream
Output to file stream as an OSstream, normally using \c std::ofstream
for the actual output.
Note
The atomic output works by creating an intermediate temporary file,
which is renamed as an atomic operation when closing. It is not
possible, or particularly desirable, to have an atomic in combination
with append behaviour. If both are specified, append has priority.
Note
An output file can be opened in two different \c append modes, both of
which preserve existing files:
-# A common append mode is APPEND_APP, which corresponds to the
\c std::ios_base::app flag.
A seek-to-end is performed at \em every write.
It is thus not possible to use any manual seeks to overwrite parts
of the file.
-# The other append mode is APPEND_ATE, which roughly corresponds to the
\c std::ios_base::ate flag behaviour.
A seek-to-end is performed immediately after opening,
but not subsequently.
Manual seeks can be used to overwrite parts of the file.
.
SourceFiles
OFstream.C
@ -64,53 +86,55 @@ public:
// Constructors
//- Construct a null output file stream.
// Behaves like \c /dev/null and is named accordingly
//- Construct a null output file stream that behaves like \c /dev/null
explicit OFstream(std::nullptr_t);
//- Construct with specified atomic behaviour
//- from pathname, stream option, optional append
//- from pathname, stream option, optional append (see note).
OFstream
(
IOstreamOption::atomicType atomic,
const fileName& pathname,
IOstreamOption streamOpt = IOstreamOption(),
IOstreamOption::appendType append = IOstreamOption::NON_APPEND
IOstreamOption::appendType append = IOstreamOption::NO_APPEND
);
//- Construct from pathname and other specifications
//- Construct from pathname and other specifications.
// See note on append mode.
explicit OFstream
(
const fileName& pathname,
IOstreamOption streamOpt = IOstreamOption(),
IOstreamOption::appendType append = IOstreamOption::NON_APPEND
IOstreamOption::appendType append = IOstreamOption::NO_APPEND
)
:
OFstream(IOstreamOption::NON_ATOMIC, pathname, streamOpt, append)
{}
//- Construct from pathname, format (uncompressed), optional append,
//- Construct from pathname, format (uncompressed),
//- optional append (see note),
//- atomic behaviour as per system default
OFstream
(
const fileName& pathname,
IOstreamOption::streamFormat fmt,
IOstreamOption::compressionType cmp = IOstreamOption::UNCOMPRESSED,
IOstreamOption::appendType append = IOstreamOption::NON_APPEND
IOstreamOption::appendType append = IOstreamOption::NO_APPEND
)
:
OFstream(pathname, IOstreamOption(fmt, cmp), append)
{}
//- Construct with specified atomic behaviour
//- from pathname, format (uncompressed), optional append
//- from pathname, format (uncompressed),
//- optional append (see note).
OFstream
(
IOstreamOption::atomicType atomic,
const fileName& pathname,
IOstreamOption::streamFormat fmt,
IOstreamOption::compressionType cmp = IOstreamOption::UNCOMPRESSED,
IOstreamOption::appendType append = IOstreamOption::NON_APPEND
IOstreamOption::appendType append = IOstreamOption::NO_APPEND
)
:
OFstream(atomic, pathname, IOstreamOption(fmt, cmp), append)
@ -141,6 +165,21 @@ public:
virtual void rewind();
// Output stream modes
//- True if opened in append mode \em and file already existed
bool is_appending() const noexcept
{
return ofstreamPointer::is_appending();
}
//- True if file creation behaves as atomic
bool is_atomic() const noexcept
{
return ofstreamPointer::is_atomic();
}
// Print
//- Print stream description
@ -158,7 +197,7 @@ public:
IOstreamOption::streamFormat fmt,
IOstreamOption::versionNumber ver,
IOstreamOption::compressionType cmp = IOstreamOption::UNCOMPRESSED,
IOstreamOption::appendType append = IOstreamOption::NON_APPEND
IOstreamOption::appendType append = IOstreamOption::NO_APPEND
)
:
OFstream(pathname, IOstreamOption(fmt, ver, cmp), append)

View File

@ -194,20 +194,37 @@ public:
class ofstreamPointer
{
// Private Data Types
//- The file open/creation type (bitmask)
enum modeType : char
{
NONE = 0, // Regular open (truncates existing)
ATOMIC = 0x1, // Atomic file creation
APPENDING = 0x2 // Is appending to an existing file
};
// Private Data
//- The stream pointer (ofstream | ogzstream | ocountstream, ...)
std::unique_ptr<std::ostream> ptr_;
//- Atomic file creation
bool atomic_;
//- File output/creation type (atomic, append etc)
char mode_;
// Private Member Functions
//- Clear any output mode information
void clear_mode() noexcept { mode_ = modeType::NONE; }
protected:
// Protected Member Functions
//- Reopen for compressed/non-compressed
//- Reopen for compressed/non-compressed. Discards append status.
void reopen(const std::string& pathname);
//- Close stream and rename file
@ -245,16 +262,20 @@ public:
//- Construct from pathname, option, append, file handling atomic
// \param pathname The file name to open for writing
// \param streamOpt Respects (UNCOMPRESSED | COMPRESSED)
// \param append Open in append mode
// \param append Open in specified append mode
// \param atomic Write into temporary file (not target file).
// This option should only be used with a stream wrapper
// (eg, OFstream) that handles the final renaming.
//
// \note
// There are two different append modes:
// append at every write, or only append after opening.
explicit ofstreamPointer
(
const fileName& pathname,
IOstreamOption streamOpt = IOstreamOption(),
const bool append = false,
const bool atomic = false
IOstreamOption::appendType append = IOstreamOption::NO_APPEND,
bool atomic = false
);
//- Construct from pathname, compression, append, file handling atomic
@ -268,12 +289,12 @@ public:
(
const fileName& pathname,
IOstreamOption::compressionType comp,
const bool append = false,
const bool atomic = false
IOstreamOption::appendType append = IOstreamOption::NO_APPEND,
bool atomic = false
);
// Member Functions
// Static Functions
//- True if compiled with libz support
static bool supports_gz() noexcept;
@ -293,14 +314,34 @@ public:
//- Which compression type?
IOstreamOption::compressionType whichCompression() const;
//- True if opened in append mode \em and file already existed
bool is_appending() const noexcept
{
return (mode_ & modeType::APPENDING);
}
//- True if file creation behaves as atomic
bool is_atomic() const noexcept
{
return (mode_ & modeType::ATOMIC);
}
// Edit
//- Return managed pointer and release ownership
std::ostream* release() noexcept { return ptr_.release(); }
//- Return managed pointer and release ownership.
std::ostream* release() noexcept
{
clear_mode();
return ptr_.release();
}
//- Replace the managed pointer
void reset(std::ostream* ptr) noexcept { ptr_.reset(ptr); }
void reset(std::ostream* ptr) noexcept
{
clear_mode();
ptr_.reset(ptr);
}
// Operators

View File

@ -88,14 +88,14 @@ Foam::ifstreamPointer::ifstreamPointer
Foam::ofstreamPointer::ofstreamPointer() noexcept
:
ptr_(),
atomic_(false)
mode_(modeType::NONE)
{}
Foam::ofstreamPointer::ofstreamPointer(std::nullptr_t)
:
ptr_(new Foam::ocountstream),
atomic_(false)
mode_(modeType::NONE)
{}
@ -103,27 +103,44 @@ Foam::ofstreamPointer::ofstreamPointer
(
const fileName& pathname,
IOstreamOption streamOpt,
const bool append,
const bool atomic
IOstreamOption::appendType append,
bool atomic
)
:
ptr_(),
atomic_(atomic)
mode_(modeType::NONE)
{
std::ios_base::openmode mode
// Leave std::ios_base::trunc implicitly handled to make things
// easier for append mode.
std::ios_base::openmode openmode
(
std::ios_base::out | std::ios_base::binary
);
if (append)
if (append == IOstreamOption::APPEND_APP)
{
mode |= std::ios_base::app;
openmode |= std::ios_base::app;
// Cannot append to gzstream
streamOpt.compression(IOstreamOption::UNCOMPRESSED);
// Cannot use append + atomic operation, without lots of extra work
atomic_ = false;
atomic = false;
}
else if (append == IOstreamOption::APPEND_ATE)
{
// Handle an "append-like" mode by opening "r+b" and NOT as "ab"
// - file already exists: Sets read position to start
// - file does not exist: Error
openmode |= std::ios_base::in; // [SIC] - use read bit, not append!
// Cannot append to gzstream
streamOpt.compression(IOstreamOption::UNCOMPRESSED);
// Cannot use append + atomic operation, without lots of extra work
atomic = false;
}
@ -146,9 +163,9 @@ Foam::ofstreamPointer::ofstreamPointer
#ifdef HAVE_LIBZ
// TBD:
// atomic_ = true; // Always treat COMPRESSED like an atomic
// atomic = true; // Always treat COMPRESSED like an atomic
const fileName& target = (atomic_ ? pathname_tmp : pathname_gz);
const fileName& target = (atomic ? pathname_tmp : pathname_gz);
// Remove old uncompressed version (if any)
fType = Foam::type(pathname, false);
@ -158,7 +175,7 @@ Foam::ofstreamPointer::ofstreamPointer
}
// Avoid writing into symlinked files (non-append mode)
if (!append || atomic_)
if (atomic || (append == IOstreamOption::NO_APPEND))
{
fType = Foam::type(target, false);
if (fType == fileName::SYMLINK)
@ -167,7 +184,7 @@ Foam::ofstreamPointer::ofstreamPointer
}
}
ptr_.reset(new ogzstream(target, mode));
ptr_.reset(new ogzstream(target, openmode));
#else /* HAVE_LIBZ */
@ -184,7 +201,7 @@ Foam::ofstreamPointer::ofstreamPointer
if (IOstreamOption::COMPRESSED != streamOpt.compression())
{
const fileName& target = (atomic_ ? pathname_tmp : pathname);
const fileName& target = (atomic ? pathname_tmp : pathname);
// Remove old compressed version (if any)
fType = Foam::type(pathname_gz, false);
@ -194,7 +211,7 @@ Foam::ofstreamPointer::ofstreamPointer
}
// Avoid writing into symlinked files (non-append mode)
if (!append || atomic_)
if (atomic || (append == IOstreamOption::NO_APPEND))
{
fType = Foam::type(target, false);
if (fType == fileName::SYMLINK)
@ -203,7 +220,75 @@ Foam::ofstreamPointer::ofstreamPointer
}
}
ptr_.reset(new std::ofstream(target, mode));
// File pointer (std::ofstream)
auto filePtr = std::make_unique<std::ofstream>(target, openmode);
if (append == IOstreamOption::APPEND_APP)
{
// Final handling for append 'app' (always non-atomic)
// Set output position to the end (like std::ios_base::ate)
// but only to test if the file had a size.
// No real performance problem since any subsequent write
// will do the same anyhow.
filePtr->seekp(0, std::ios_base::end);
if (filePtr->tellp() <= 0)
{
// Did not open an existing file
append = IOstreamOption::NO_APPEND;
}
}
else if (append == IOstreamOption::APPEND_ATE)
{
// Final handling for append 'ate' (always non-atomic)
if (filePtr->good())
{
// Success if file already exists.
// Set output position to the end - like std::ios_base::ate
filePtr->seekp(0, std::ios_base::end);
if (filePtr->tellp() <= 0)
{
// Did not open an existing file
append = IOstreamOption::NO_APPEND;
}
}
else
{
// Error if file does not already exist.
// Reopen as regular output mode only.
// Did not open an existing file
append = IOstreamOption::NO_APPEND;
if (filePtr->is_open())
{
filePtr->close();
}
filePtr->clear();
filePtr->open
(
target,
(std::ios_base::out | std::ios_base::binary)
);
}
}
ptr_.reset(filePtr.release());
}
// Is appending to an existing file
if (append != IOstreamOption::NO_APPEND)
{
mode_ = modeType::APPENDING;
}
// An atomic output operation (normally not appending!)
if (atomic)
{
mode_ |= modeType::ATOMIC;
}
}
@ -212,8 +297,8 @@ Foam::ofstreamPointer::ofstreamPointer
(
const fileName& pathname,
IOstreamOption::compressionType comp,
const bool append,
const bool atomic
IOstreamOption::appendType append,
bool atomic
)
:
ofstreamPointer
@ -237,12 +322,12 @@ void Foam::ifstreamPointer::open
// Forcibly close old stream (if any)
ptr_.reset(nullptr);
const std::ios_base::openmode mode
const std::ios_base::openmode openmode
(
std::ios_base::in | std::ios_base::binary
);
ptr_.reset(new std::ifstream(pathname, mode));
ptr_.reset(new std::ifstream(pathname, openmode));
if (!ptr_->good())
{
@ -254,7 +339,7 @@ void Foam::ifstreamPointer::open
{
#ifdef HAVE_LIBZ
ptr_.reset(new igzstream(pathname_gz, mode));
ptr_.reset(new igzstream(pathname_gz, openmode));
#else /* HAVE_LIBZ */
@ -311,7 +396,7 @@ void Foam::ofstreamPointer::reopen(const std::string& pathname)
gz->close();
gz->clear();
if (atomic_)
if (mode_ & modeType::ATOMIC)
{
gz->open
(
@ -341,10 +426,11 @@ void Foam::ofstreamPointer::reopen(const std::string& pathname)
}
file->clear();
// Don't need original request to append since rewind implies
// trashing that anyhow.
// Invalidate the appending into existing file information
// since rewind usually means overwrite
mode_ &= ~modeType::APPENDING;
if (atomic_)
if (mode_ & modeType::ATOMIC)
{
file->open
(
@ -367,7 +453,13 @@ void Foam::ofstreamPointer::reopen(const std::string& pathname)
void Foam::ofstreamPointer::close(const std::string& pathname)
{
if (!atomic_ || pathname.empty()) return;
// Invalidate the appending into existing file information
mode_ &= ~modeType::APPENDING;
if (pathname.empty() || !(mode_ & modeType::ATOMIC))
{
return;
}
#ifdef HAVE_LIBZ
auto* gz = dynamic_cast<ogzstream*>(ptr_.get());

View File

@ -107,7 +107,7 @@ public:
const label comm,
const fileName& pathname,
IOstreamOption streamOpt = IOstreamOption(),
IOstreamOption::appendType append = IOstreamOption::NON_APPEND,
IOstreamOption::appendType append = IOstreamOption::NO_APPEND,
const bool writeOnProc = true
);
@ -118,7 +118,7 @@ public:
const label comm,
const fileName& pathname,
IOstreamOption streamOpt = IOstreamOption(),
IOstreamOption::appendType append = IOstreamOption::NON_APPEND,
IOstreamOption::appendType append = IOstreamOption::NO_APPEND,
const bool writeOnProc = true
)
:
@ -140,7 +140,7 @@ public:
IOstreamOption::atomicType atomic,
const fileName& pathname,
IOstreamOption streamOpt = IOstreamOption(),
IOstreamOption::appendType append = IOstreamOption::NON_APPEND,
IOstreamOption::appendType append = IOstreamOption::NO_APPEND,
const bool writeOnProc = true
)
:
@ -161,7 +161,7 @@ public:
(
const fileName& pathname,
IOstreamOption streamOpt = IOstreamOption(),
IOstreamOption::appendType append = IOstreamOption::NON_APPEND,
IOstreamOption::appendType append = IOstreamOption::NO_APPEND,
const bool writeOnProc = true
)
:

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2015 OpenFOAM Foundation
Copyright (C) 2018-2023 OpenCFD Ltd.
Copyright (C) 2018-2024 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -36,9 +36,6 @@ Description
The compression (UNCOMPRESSED | COMPRESSED) is typically controlled
by switch values (true/false, on/off, ...).
Additionally, some enumerations are defined (APPEND, NON_APPEND, ...)
that are useful, verbose alternatives to bool values.
SourceFiles
IOstreamOption.C
@ -84,11 +81,14 @@ public:
COMPRESSED //!< compression = true
};
//- File appending (NON_APPEND | APPEND)
//- File appending (NO_APPEND | APPEND_APP | APPEND_ATE)
enum appendType : char
{
NON_APPEND = 0, //!< append = false
APPEND //!< append = true
NO_APPEND = 0, //!< no append (truncates existing)
APPEND_APP, //!< append (seek end each write)
APPEND_ATE, //!< append (seek end after open)
NON_APPEND = NO_APPEND, //!< old name for NO_APPEND
APPEND = APPEND_APP //!< old name for APPEND_APP
};
//- Atomic operations (output)

View File

@ -80,7 +80,7 @@ bool Foam::OFstreamCollator::writeFile
osPtr.reset(new OFstream(atomic, fName, streamOpt, append));
auto& os = *osPtr;
if (append == IOstreamOption::NON_APPEND)
if (append == IOstreamOption::NO_APPEND)
{
// No IOobject so cannot use IOobject::writeHeader

View File

@ -190,7 +190,7 @@ bool Foam::fileOperations::collatedFileOperation::appendObject
// UNCOMPRESSED (binary only)
IOstreamOption(IOstreamOption::BINARY, streamOpt.version()),
// Append on sub-ranks
(isIOmaster ? IOstreamOption::NON_APPEND : IOstreamOption::APPEND)
(isIOmaster ? IOstreamOption::NO_APPEND : IOstreamOption::APPEND_APP)
);
if (!os.good())
@ -384,7 +384,7 @@ bool Foam::fileOperations::collatedFileOperation::writeObject
comm_,
pathName,
streamOpt,
IOstreamOption::NON_APPEND,
IOstreamOption::NO_APPEND,
writeOnProc
);
@ -431,7 +431,7 @@ bool Foam::fileOperations::collatedFileOperation::writeObject
comm_,
pathName,
streamOpt,
IOstreamOption::NON_APPEND,
IOstreamOption::NO_APPEND,
writeOnProc
);

View File

@ -81,7 +81,7 @@ Foam::threadedCollatedOFstream::~threadedCollatedOFstream()
str(),
IOstreamOption(IOstreamOption::BINARY, version(), compression_),
atomic_,
IOstreamOption::NON_APPEND,
IOstreamOption::NO_APPEND,
useThread_,
headerEntries_
);

View File

@ -2505,7 +2505,7 @@ Foam::fileOperations::masterUncollatedFileOperation::NewOFstream
comm_,
pathName,
streamOpt,
IOstreamOption::NON_APPEND,
IOstreamOption::NO_APPEND,
writeOnProc
)
);
@ -2529,7 +2529,7 @@ Foam::fileOperations::masterUncollatedFileOperation::NewOFstream
comm_,
pathName,
streamOpt,
IOstreamOption::NON_APPEND,
IOstreamOption::NO_APPEND,
writeOnProc
)
);

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2016-2023 OpenCFD Ltd.
Copyright (C) 2016-2024 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -1291,7 +1291,7 @@ bool Foam::lumpedPointMovement::writeData
const Tuple2<scalar, scalar>* timesWritten
) const
{
if (!Pstream::master())
if (!UPstream::master())
{
return false;
}
@ -1306,13 +1306,13 @@ bool Foam::lumpedPointMovement::writeData
writeData(os, forces, moments, outputFormat_, timesWritten);
}
// Log output
// Log output - simple append to existing
{
OFstream os
(
coupler().resolveFile(logName_),
IOstreamOption(),
IOstreamOption::APPEND
IOstreamOption::APPEND_ATE
);
writeData(os, forces, moments, outputFormatType::PLAIN, timesWritten);