IOobject.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 | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2017 OpenFOAM Foundation
9  Copyright (C) 2016-2023 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "IOobject.H"
30 #include "Time.H"
31 #include "Istream.H"
32 #include "registerSwitch.H"
33 
34 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
35 
36 namespace Foam
37 {
38  defineTypeNameAndDebug(IOobject, 0);
39 }
40 
41 bool Foam::IOobject::bannerEnabled_(true);
42 
44 (
45  #ifdef _WIN32
46  // Windows: using ':' causes scoping conflicts with d:/path etc
47  Foam::debug::infoSwitch("scopeSeparator", '_')
48  #else
49  Foam::debug::infoSwitch("scopeSeparator", ':')
50  #endif
51 );
52 
53 const Foam::Enum
54 <
56 >
58 ({
59  { fileCheckTypes::timeStamp, "timeStamp" },
60  { fileCheckTypes::timeStampMaster, "timeStampMaster" },
61  { fileCheckTypes::inotify, "inotify" },
62  { fileCheckTypes::inotifyMaster, "inotifyMaster" },
63 });
64 
65 // Default fileCheck type
67 (
68  fileCheckTypesNames.get
69  (
70  "fileModificationChecking",
72  )
73 );
74 
75 
77 (
78  Foam::debug::floatOptimisationSwitch("fileModificationSkew", 30)
79 );
81 (
82  "fileModificationSkew",
83  float,
85 );
86 
88 (
89  Foam::debug::optimisationSwitch("maxFileModificationPolls", 1)
90 );
92 (
93  "maxFileModificationPolls",
94  int,
96 );
97 
98 
100 namespace Foam
101 {
102  // Register re-reader
103  class addfileModificationCheckingToOpt
104  :
106  {
107  public:
108 
109  addfileModificationCheckingToOpt
110  (const addfileModificationCheckingToOpt&) = delete;
111 
112  void operator=
113  (const addfileModificationCheckingToOpt&) = delete;
114 
115  explicit addfileModificationCheckingToOpt(const char* name)
116  :
117  ::Foam::simpleRegIOobject(Foam::debug::addOptimisationObject, name)
118  {}
119 
120  virtual ~addfileModificationCheckingToOpt() = default;
121 
122  virtual void readData(Foam::Istream& is)
123  {
126  }
127 
128  virtual void writeData(Foam::Ostream& os) const
129  {
132  }
133  };
134 
135  addfileModificationCheckingToOpt addfileModificationCheckingToOpt_
136  (
137  "fileModificationChecking"
138  );
139 
140 } // End namespace Foam
142 
143 
144 // * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * * //
145 
147 (
148  const fileName& path,
149  fileName& instance,
150  fileName& local,
151  word& name
152 )
153 {
154  // Convert explicit relative file-system path to absolute file-system path.
155  if (path.starts_with("./") || path.starts_with("../"))
156  {
157  fileName absPath(cwd()/path);
158  absPath.clean(); // Remove unneeded ".."
159 
160  return fileNameComponents(absPath, instance, local, name);
161  }
162 
163  instance.clear();
164  local.clear();
165  name.clear();
166 
167  // Called with directory
168  if (isDir(path))
169  {
171  << " called with directory: " << path << endl;
172 
173  return false;
174  }
175 
176  const auto first = path.find('/');
177  const auto last = path.rfind('/');
178 
179  // The raw length of name (without validating for word chars)
180  auto nameLen = path.size();
181 
182  if (first == std::string::npos)
183  {
184  // No '/' found (or empty entirely)
185  // => no instance or local
186 
188  }
189  else if
190  (
191  first == 0
192  #ifdef _WIN32
193  || (first == 2 && path[1] == ':') // Eg, d:/path
194  #endif
195  )
196  {
197  // Absolute path (starts with '/' or 'd:/')
198  // => no local
199 
200  instance = path.substr(0, last);
201 
202  const std::string ending = path.substr(last+1);
203  nameLen = ending.size(); // The raw length of name
204  name = word::validate(ending);
205  }
206  else
207  {
208  // Normal case.
209  // First part is instance, remainder is local
210  instance = path.substr(0, first);
211 
212  if (last > first)
213  {
214  // With local
215  local = path.substr(first+1, last-first-1);
216  }
217 
218  const std::string ending = path.substr(last+1);
219  nameLen = ending.size(); // The raw length of name
220  name = word::validate(ending);
221  }
222 
223  // Check for valid (and stripped) name, regardless of the debug level
224  if (!nameLen || nameLen != name.size())
225  {
227  << "has invalid word for name: \"" << name
228  << "\"\nwhile processing path: " << path << endl;
229 
230  return false;
231  }
232 
233  return true;
234 }
235 
236 
238 (
239  const IOobject& io,
240  const fileName& altFile,
241  const word& ioName
242 )
243 {
244  if (altFile.empty())
245  {
246  return io;
247  }
248 
249  // Construct from file path instead
250 
251  fileName altPath = altFile;
252 
253  if (isDir(altPath))
254  {
255  // Resolve directories as well
256 
257  if (ioName.empty())
258  {
259  altPath /= io.name();
260  }
261  else
262  {
263  altPath /= ioName;
264  }
265  }
266  altPath.expand();
267 
268 
269  return
270  IOobject
271  (
272  altPath,
273  io.db(),
274  io.readOpt(),
276  io.registerObject(),
277  io.globalObject()
278  );
279 }
280 
281 
283 {
284  const auto i = name.rfind('.');
285 
286  if (i == std::string::npos || i == 0)
287  {
288  return word();
289  }
290 
291  return name.substr(i+1);
292 }
293 
294 
296 {
297  const auto i = name.rfind('.');
298 
299  if (i == std::string::npos || i == 0)
300  {
301  return name;
302  }
303 
304  return name.substr(0, i);
305 }
306 
307 
308 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
309 
310 Foam::IOobject::IOobject(const objectRegistry& registry, IOobjectOption ioOpt)
311 :
312  IOobjectOption(ioOpt),
313  objState_(objectState::GOOD),
314  sizeofLabel_(static_cast<unsigned char>(sizeof(label))),
315  sizeofScalar_(static_cast<unsigned char>(sizeof(scalar))),
316  db_(registry)
317 {}
318 
319 
320 Foam::IOobject::IOobject
321 (
322  const word& name,
323  const fileName& instance,
324  const objectRegistry& registry,
325  IOobjectOption ioOpt
326 )
327 :
328  IOobject(registry, ioOpt)
329 {
330  name_ = name;
331  instance_ = instance;
332 
334  {
336  << "Constructing IOobject: " << name_ << endl;
337  }
338 }
339 
340 
341 Foam::IOobject::IOobject
342 (
343  const word& name,
344  const fileName& instance,
345  const fileName& local,
346  const objectRegistry& registry,
347  IOobjectOption ioOpt
348 )
349 :
350  IOobject(registry, ioOpt)
351 {
352  name_ = name;
353  instance_ = instance;
354  local_ = local;
355 
357  {
359  << "Constructing IOobject: " << name_ << endl;
360  }
361 }
362 
363 
364 Foam::IOobject::IOobject
365 (
366  const fileName& path,
367  const objectRegistry& registry,
368  IOobjectOption ioOpt
369 )
370 :
371  IOobject(registry, ioOpt)
372 {
373  if (!fileNameComponents(path, instance_, local_, name_))
374  {
376  << " invalid path specification"
377  << exit(FatalError);
378  }
379 
381  {
383  << "Constructing IOobject: " << name_ << endl;
384  }
385 }
386 
387 
388 Foam::IOobject::IOobject
389 (
390  const IOobject& io,
391  const objectRegistry& registry
392 )
393 :
394  IOobjectOption(static_cast<IOobjectOption>(io)),
395  objState_(io.objState_),
396  sizeofLabel_(io.sizeofLabel_),
397  sizeofScalar_(io.sizeofScalar_),
398 
399  name_(io.name_),
400  headerClassName_(io.headerClassName_),
401  note_(io.note_),
402  instance_(io.instance_),
403  local_(io.local_),
404 
405  db_(registry)
406 {}
407 
408 
409 Foam::IOobject::IOobject
410 (
411  const IOobject& io,
412  const word& name
413 )
414 :
415  IOobjectOption(static_cast<IOobjectOption>(io)),
416  objState_(io.objState_),
417  sizeofLabel_(io.sizeofLabel_),
418  sizeofScalar_(io.sizeofScalar_),
419 
420  name_(name),
421  headerClassName_(io.headerClassName_),
422  note_(io.note_),
423  instance_(io.instance_),
424  local_(io.local_),
426  db_(io.db_)
427 {}
428 
429 
430 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
433 {
434  return db_;
435 }
436 
439 {
440  return db_.time();
441 }
442 
445 {
446  return time().rootPath();
447 }
448 
451 {
452  return time().caseName();
453 }
454 
455 
457 {
458  // A file is 'outside' of the case if it has been specified using an
459  // absolute path
460 
461  const auto first = instance().find('/');
462 
463  if
464  (
465  first == 0
466  #ifdef _WIN32
467  || (first == 2 && instance()[1] == ':') // Eg, d:/path
468  #endif
469  )
470  {
471  // Absolute path (starts with '/' or 'd:/')
472  return instance();
473  }
474 
475  return rootPath()/caseName()/instance()/db_.dbDir()/local();
476 }
477 
478 
480 (
481  const word& instance,
482  const fileName& local
483 ) const
484 {
485  // Note: can only be called with relative instance since is word type
486  return rootPath()/caseName()/instance/db_.dbDir()/local;
487 }
488 
489 
491 {
492  // A file is 'outside' of the case if it has been specified using an
493  // absolute path
494 
495  const auto first = instance().find('/');
496 
497  if
498  (
499  first == 0
500  #ifdef _WIN32
501  || (first == 2 && instance()[1] == ':') // Eg, d:/path
502  #endif
503  )
504  {
505  // Absolute path (starts with '/' or 'd:/')
506  return instance()/name();
507  }
508 
509  return instance()/db_.dbDir()/local()/name();
510 }
511 
512 
514 (
515  const word& typeName,
516  const bool search
517 ) const
518 {
519  // Do not check for undecomposed files
520  return fileHandler().filePath(false, *this, typeName, search);
521 }
522 
523 
525 (
526  const word& typeName,
527  const bool search
528 ) const
529 {
530  // Check for undecomposed files
531  return fileHandler().filePath(true, *this, typeName, search);
532 }
533 
534 
535 void Foam::IOobject::setBad(const string& s)
536 {
537  if (objState_ != objectState::GOOD)
538  {
540  << "Recurrent failure for object " << s
541  << exit(FatalError);
542  }
543 
544  if (error::level)
545  {
547  << "Broken object " << s << info() << endl;
548  }
549 
550  objState_ = objectState::BAD;
551 }
552 
553 
554 void Foam::IOobject::resetHeader(const word& newName)
555 {
556  if (!newName.empty())
557  {
558  name_ = newName;
559  }
560  objState_ = objectState::GOOD;
561  sizeofLabel_ = static_cast<unsigned char>(sizeof(label));
562  sizeofScalar_ = static_cast<unsigned char>(sizeof(scalar));
563  headerClassName_.clear();
564  note_.clear();
565 }
566 
567 
568 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
569 
571 {
572  readOpt(io.readOpt());
573  writeOpt(io.writeOpt());
574  // No change to registerObject
575  globalObject(io.globalObject());
576 
577  objState_ = io.objState_;
578  sizeofLabel_ = io.sizeofLabel_;
579  sizeofScalar_ = io.sizeofScalar_;
580 
581  name_ = io.name_;
582  headerClassName_ = io.headerClassName_;
583  note_ = io.note_;
584  instance_ = io.instance_;
585  local_ = io.local_;
586 }
587 
588 
589 // ************************************************************************* //
static word validate(const std::string &s, const bool prefix=false)
Construct validated word (no invalid characters).
Definition: word.C:39
Abstract base class for registered object with I/O. Used in debug symbol registration.
EnumType read(Istream &is) const
Read a word from Istream and return the corresponding enumeration.
Definition: Enum.C:102
static bool fileNameComponents(const fileName &path, fileName &instance, fileName &local, word &name)
Split path into instance, local, name components.
Definition: IOobject.C:140
A class for handling file names.
Definition: fileName.H:71
readOption readOpt() const noexcept
Get the read option.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
fileName globalFilePath(const word &typeName, const bool search=true) const
Redirect to fileHandler filePath, searching up if in parallel.
Definition: IOobject.C:518
static float fileModificationSkew
Time skew (seconds) for file modification checks.
Definition: IOobject.H:331
static void writeData(Ostream &os, const Type &val)
void operator=(const IOobject &io)
Copy assignment, copies all values (except the registry)
Definition: IOobject.C:563
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:578
const word & name() const noexcept
Return the object name.
Definition: IOobjectI.H:162
An Istream is an abstract base class for all input systems (streams, files, token lists etc)...
Definition: Istream.H:57
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:487
word member() const
Return member (name without the extension)
Definition: IOobjectI.H:174
refPtr< fileOperation > fileHandler(std::nullptr_t)
Delete current file handler - forwards to fileOperation::handler()
void setBad(const string &s)
Set the object state to bad.
Definition: IOobject.C:528
word group() const
Return group (extension part of name)
Definition: IOobjectI.H:168
int infoSwitch(const char *name, const int deflt=0)
Lookup info switch or add default value.
Definition: debug.C:228
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:69
fileName path() const
The complete path.
Definition: IOobject.C:449
registerOptSwitch("fileModificationSkew", float, Foam::IOobject::fileModificationSkew)
bool isDir(const fileName &name, const bool followLink=true)
Does the name exist as a DIRECTORY in the file system?
Definition: POSIX.C:860
bool globalObject() const noexcept
True if object is treated the same for all processors.
writeOption writeOpt() const noexcept
Get the write option.
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:52
A class for handling words, derived from Foam::string.
Definition: word.H:63
fileCheckTypes
Enumeration defining the file checking options.
Definition: IOobject.H:191
static int maxFileModificationPolls
Max number of times to poll for file modification changes.
Definition: IOobject.H:336
const objectRegistry & db() const noexcept
Return the local objectRegistry.
Definition: IOobject.C:425
fileName localFilePath(const word &typeName, const bool search=true) const
Redirect to fileHandler filePath, searching locally.
Definition: IOobject.C:507
bool local
Definition: EEqn.H:20
const Time & time() const noexcept
Return Time associated with the objectRegistry.
Definition: IOobject.C:431
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:55
const direction noexcept
Definition: Scalar.H:258
int optimisationSwitch(const char *name, const int deflt=0)
Lookup optimisation switch or add default value.
Definition: debug.C:234
int debug
Static debugging option.
static const Enum< fileCheckTypes > fileCheckTypesNames
Names for the fileCheckTypes.
Definition: IOobject.H:202
OBJstream os(runTime.globalPath()/outputName)
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
defineTypeNameAndDebug(combustionModel, 0)
static bool clean(std::string &str)
Cleanup filename string, possibly applies other transformations such as changing the path separator e...
Definition: fileName.C:192
static fileCheckTypes fileModificationChecking
Type of file modification checking.
Definition: IOobject.H:326
const fileName & instance() const noexcept
Read access to instance path component.
Definition: IOobjectI.H:233
static char scopeSeparator
Character for scoping object names (&#39;:&#39; or &#39;_&#39;)
Definition: IOobject.H:321
const fileName & rootPath() const
Return the Time::rootPath()
Definition: IOobject.C:437
bool starts_with(char c) const
True if string starts with given character (cf. C++20)
Definition: string.H:414
float floatOptimisationSwitch(const char *name, const float deflt=0)
Lookup optimisation switch or add default value.
Definition: debug.C:240
#define WarningInFunction
Report a warning using Foam::Warning.
Enum is a wrapper around a list of names/values that represent particular enumeration (or int) values...
string & expand(const bool allowEmpty=false)
Inplace expand initial tags, tildes, and all occurrences of environment variables as per stringOps::e...
Definition: string.C:166
A simple container of IOobject preferences. Can also be used for general handling of read/no-read/rea...
fileName cwd()
The physical or logical current working directory path name.
Definition: POSIX.C:590
fileName objectRelPath() const
The object path relative to the root.
Definition: IOobject.C:483
bool registerObject() const noexcept
Should objects created with this IOobject be registered?
fileName search(const word &file, const fileName &directory)
Recursively search the given directory for the file.
Definition: fileName.C:640
dictionary & optimisationSwitches()
The OptimisationSwitches sub-dictionary in the central controlDict(s).
Definition: debug.C:216
IOobject io("surfaceFilmProperties", mesh.time().constant(), mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE, IOobject::NO_REGISTER)
Registry of regIOobjects.
void addOptimisationObject(const char *name, simpleRegIOobject *obj)
Register optimisation switch read/write object.
Definition: debug.C:259
const fileName & local() const noexcept
Read access to local path component.
Definition: IOobjectI.H:245
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
void resetHeader(const word &newName=word::null)
Clear various bits (headerClassName, note, sizeof...) that would be obtained when reading from a file...
Definition: IOobject.C:547
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:171
const fileName & caseName() const
Return the Time::caseName()
Definition: IOobject.C:443
static int level
The output level (verbosity) of messages.
Namespace for OpenFOAM.
static IOobject selectIO(const IOobject &io, const fileName &altFile, const word &ioName="")
Return the IOobject, but also consider an alternative file name.
Definition: IOobject.C:231
#define InfoInFunction
Report an information message using Foam::Info.