collatedFileOperation.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | Copyright (C) 2017 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "collatedFileOperation.H"
28 #include "Pstream.H"
29 #include "Time.H"
31 #include "decomposedBlockData.H"
32 #include "registerSwitch.H"
33 #include "masterOFstream.H"
34 #include "OFstream.H"
35 
36 /* * * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * */
37 
38 namespace Foam
39 {
40 namespace fileOperations
41 {
42  defineTypeNameAndDebug(collatedFileOperation, 0);
44  (
45  fileOperation,
46  collatedFileOperation,
47  word
48  );
49 
51  (
52  debug::floatOptimisationSwitch("maxThreadFileBufferSize", 1e9)
53  );
55  (
56  "maxThreadFileBufferSize",
57  float,
59  );
60 }
61 }
62 
63 
64 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
65 
66 bool Foam::fileOperations::collatedFileOperation::appendObject
67 (
68  const regIOobject& io,
69  const fileName& pathName,
71  IOstream::versionNumber ver,
73 ) const
74 {
75  // Append to processors/ file
76 
77  fileName prefix;
78  fileName postfix;
79  label proci = splitProcessorPath(io.objectPath(), prefix, postfix);
80 
81  if (debug)
82  {
83  Pout<< "writeObject:" << " : For local object : "
84  << io.name()
85  << " appending processor " << proci
86  << " data to " << pathName << endl;
87  }
88 
89  if (proci == -1)
90  {
92  << "Not a valid processor path " << pathName
93  << exit(FatalError);
94  }
95 
96 
97  // Create string from all data to write
98  string buf;
99  {
100  OStringStream os(fmt, ver);
101  if (proci == 0)
102  {
103  if (!io.writeHeader(os))
104  {
105  return false;
106  }
107  }
108 
109  // Write the data to the Ostream
110  if (!io.writeData(os))
111  {
112  return false;
113  }
114 
115  if (proci == 0)
116  {
118  }
119 
120  buf = os.str();
121  }
122 
123 
124  bool append = (proci > 0);
125 
126  // Note: cannot do append + compression. This is a limitation
127  // of ogzstream (or rather most compressed formats)
128 
129  OFstream os
130  (
131  pathName,
133  ver,
134  IOstream::UNCOMPRESSED, // no compression
135  append
136  );
137 
138  if (!os.good())
139  {
141  << "Cannot open for appending"
142  << exit(FatalIOError);
143  }
144 
145  if (proci == 0)
146  {
148  << "FoamFile\n{\n"
149  << " version " << os.version() << ";\n"
150  << " format " << os.format() << ";\n"
151  << " class " << decomposedBlockData::typeName
152  << ";\n"
153  << " location " << pathName << ";\n"
154  << " object " << pathName.name() << ";\n"
155  << "}" << nl;
156  IOobject::writeDivider(os) << nl;
157  }
158 
159  // Write data
160  UList<char> slice
161  (
162  const_cast<char*>(buf.data()),
163  label(buf.size())
164  );
165  os << nl << "// Processor" << proci << nl << slice << nl;
166 
167  return os.good();
168 }
169 
170 
171 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
172 
174 (
175  const bool verbose
176 )
177 :
179  writer_(maxThreadFileBufferSize)
180 {
181  if (verbose)
182  {
183  Info<< "I/O : " << typeName
184  << " (maxThreadFileBufferSize " << maxThreadFileBufferSize
185  << ')' << endl;
186 
187  if (maxThreadFileBufferSize == 0)
188  {
189  Info<< " Threading not activated "
190  "since maxThreadFileBufferSize = 0." << nl
191  << " Writing may run slowly for large file sizes."
192  << endl;
193  }
194  else
195  {
196  Info<< " Threading activated "
197  "since maxThreadFileBufferSize > 0." << nl
198  << " Requires thread support enabled in MPI, "
199  "otherwise the simulation" << nl
200  << " may \"hang\". If thread support cannot be "
201  "enabled, deactivate threading" << nl
202  << " by setting maxThreadFileBufferSize to 0 in "
203  "$FOAM_ETC/controlDict"
204  << endl;
205  }
206 
207  if
208  (
211  )
212  {
214  << "Resetting fileModificationChecking to inotify" << endl;
215  }
216 
217  if
218  (
221  )
222  {
224  << "Resetting fileModificationChecking to timeStamp" << endl;
225  }
226  }
227 }
228 
229 
230 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
231 
233 {}
234 
235 
236 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
237 
239 (
240  const IOobject& io,
241  const word& typeName
242 ) const
243 {
244  // Replacement for objectPath
245  if (io.time().processorCase())
246  {
248  (
249  io,
251  io.instance()
252  );
253  }
254  else
255  {
257  (
258  io,
260  io.instance()
261  );
262  }
263 }
264 
265 
267 (
268  const regIOobject& io,
272  const bool valid
273 ) const
274 {
275  const Time& tm = io.time();
276  const fileName& inst = io.instance();
277 
278  if (inst.isAbsolute() || !tm.processorCase())
279  {
280  mkDir(io.path());
281  fileName pathName(io.objectPath());
282 
283  if (debug)
284  {
285  Pout<< "writeObject:"
286  << " : For object : " << io.name()
287  << " falling back to master-only output to " << io.path()
288  << endl;
289  }
290 
291  masterOFstream os
292  (
293  pathName,
294  fmt,
295  ver,
296  cmp,
297  false,
298  valid
299  );
300 
301  // If any of these fail, return (leave error handling to Ostream class)
302  if (!os.good())
303  {
304  return false;
305  }
306  if (!io.writeHeader(os))
307  {
308  return false;
309  }
310  // Write the data to the Ostream
311  if (!io.writeData(os))
312  {
313  return false;
314  }
316 
317  return true;
318  }
319  else
320  {
321  // Construct the equivalent processors/ directory
322  fileName path(processorsPath(io, inst));
323 
324  mkDir(path);
325  fileName pathName(path/io.name());
326 
327  if (io.global())
328  {
329  if (debug)
330  {
331  Pout<< "writeObject:" << " : For global object : " << io.name()
332  << " falling back to master-only output to " << pathName
333  << endl;
334  }
335 
336  masterOFstream os
337  (
338  pathName,
339  fmt,
340  ver,
341  cmp,
342  false,
343  valid
344  );
345 
346  // If any of these fail, return (leave error handling to Ostream
347  // class)
348  if (!os.good())
349  {
350  return false;
351  }
352  if (!io.writeHeader(os))
353  {
354  return false;
355  }
356  // Write the data to the Ostream
357  if (!io.writeData(os))
358  {
359  return false;
360  }
362 
363  return true;
364  }
365  else if (!Pstream::parRun())
366  {
367  // Special path for e.g. decomposePar. Append to
368  // processors/ file
369  if (debug)
370  {
371  Pout<< "writeObject:"
372  << " : For object : " << io.name()
373  << " appending to " << pathName << endl;
374  }
375 
376  return appendObject(io, pathName, fmt, ver, cmp);
377  }
378  else
379  {
380  if (debug)
381  {
382  Pout<< "writeObject:"
383  << " : For object : " << io.name()
384  << " starting collating output to " << pathName << endl;
385  }
386 
387  threadedCollatedOFstream os(writer_, pathName, fmt, ver, cmp);
388 
389  // If any of these fail, return (leave error handling to Ostream
390  // class)
391  if (!os.good())
392  {
393  return false;
394  }
395  if (Pstream::master() && !io.writeHeader(os))
396  {
397  return false;
398  }
399  // Write the data to the Ostream
400  if (!io.writeData(os))
401  {
402  return false;
403  }
404  if (Pstream::master())
405  {
407  }
408 
409  return true;
410  }
411  }
412 }
413 
414 
415 // ************************************************************************* //
virtual const fileName & name() const
Return the name of the stream.
Definition: OSstream.H:88
bool processorCase() const
Return true if this is a processor case.
Definition: TimePaths.H:90
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
const word & name() const
Return name.
Definition: IOobject.H:291
A class for handling file names.
Definition: fileName.H:69
static Stream & writeBanner(Stream &os, bool noHint=false)
Write the standard OpenFOAM file/dictionary banner.
Definition: IOobjectI.H:45
float floatOptimisationSwitch(const char *name, const float defaultValue=0)
Lookup optimisation switch or add default value.
Definition: debug.C:196
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
error FatalError
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:319
static Stream & writeDivider(Stream &os)
Write the standard file section divider.
Definition: IOobjectI.H:98
collatedFileOperation(const bool verbose)
Construct null.
Master-only drop-in replacement for OFstream.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:253
static bool master(const label communicator=0)
Am I the master process.
Definition: UPstream.H:412
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:68
bool good() const
Return true if next operation might succeed.
Definition: IOstream.H:333
static fileName objectPath(const IOobject &, const pathType &, const word &)
Construct filePath.
Macros for easy insertion into run-time selection tables.
fileName path() const
Return complete path.
Definition: IOobject.C:385
addToRunTimeSelectionTable(fileOperation, collatedFileOperation, word)
bool isAbsolute() const
Return true if file name is absolute.
Definition: fileName.C:58
virtual fileName objectPath(const IOobject &io, const word &typeName) const
Generate disk file name for object. Opposite of filePath.
A class for handling words, derived from string.
Definition: word.H:59
Master-only drop-in replacement for OFstream.
streamFormat
Enumeration for the format of data in the stream.
Definition: IOstream.H:86
compressionType
Enumeration for the format of data in the stream.
Definition: IOstream.H:193
static const char nl
Definition: Ostream.H:262
virtual bool writeObject(const regIOobject &, IOstream::streamFormat format=IOstream::ASCII, IOstream::versionNumber version=IOstream::currentVersion, IOstream::compressionType compression=IOstream::UNCOMPRESSED, const bool valid=true) const
Writes a regIOobject (so header, contents and divider).
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
static fileCheckTypes fileModificationChecking
Type of file modification checking.
Definition: IOobject.H:208
bool mkDir(const fileName &, mode_t=0777)
Make a directory and return an error if it could not be created.
Definition: POSIX.C:297
static float maxThreadFileBufferSize
Max size of thread buffer size. This is the overall size of.
virtual bool global() const
Is object global.
Definition: regIOobject.H:299
static bool & parRun()
Is this a parallel run?
Definition: UPstream.H:394
const fileName & instance() const
Definition: IOobject.H:386
static Stream & writeEndDivider(Stream &os)
Write the standard end file divider.
Definition: IOobjectI.H:108
#define WarningInFunction
Report a warning using Foam::Warning.
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:331
const Time & time() const
Return time.
Definition: IOobject.C:337
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
registerOptSwitch("maxThreadFileBufferSize", float, collatedFileOperation::maxThreadFileBufferSize)
Version number type.
Definition: IOstream.H:96
regIOobject is an abstract class derived from IOobject to handle automatic object registration with t...
Definition: regIOobject.H:65
bool writeHeader(Ostream &) const
Write header.
messageStream Info
defineTypeNameAndDebug(collatedFileOperation, 0)
virtual bool writeData(Ostream &) const =0
Pure virtual writaData function.
fileOperations that performs all file operations on the master processor. Requires the calls to be pa...
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:92
fileName objectPath() const
Return complete path + object name.
Definition: IOobject.H:412
Namespace for OpenFOAM.
IOerror FatalIOError