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 // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
145 
146 // A file is 'outside' of the case if it has been specified using an
147 // absolute path.
148 //
149 // Like 'fileName::isAbsolute' but with even fewer checks since the
150 // swapping of '\\' with '/' will have already occurred.
151 static inline bool file_isOutsideCase(const std::string& str)
152 {
153  return !str.empty() &&
154  (
155  // Starts with '/'
156  (str[0] == '/')
157 
158 #ifdef _WIN32
159  // Filesytem root - eg, d:/path
160  || (
161  (str.length() > 2 && str[1] == ':')
162  && (str[2] == '/')
163  )
164 #endif
165  );
166 }
167 
168 
169 // * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * * //
170 
172 (
173  const fileName& path,
174  fileName& instance,
175  fileName& local,
176  word& name
177 )
178 {
179  // Convert explicit relative file-system path to absolute file-system path.
180  if (path.starts_with("./") || path.starts_with("../"))
181  {
182  fileName absPath(cwd()/path);
183  absPath.clean(); // Remove unneeded ".."
184 
185  return fileNameComponents(absPath, instance, local, name);
186  }
187 
188  instance.clear();
189  local.clear();
190  name.clear();
191 
192  // Called with directory
193  if (isDir(path))
194  {
196  << " called with directory: " << path << endl;
197 
198  return false;
199  }
200 
201  const auto first = path.find('/');
202  const auto last = path.rfind('/');
203 
204  // The raw length of name (without validating for word chars)
205  auto nameLen = path.size();
206 
207  if (first == std::string::npos)
208  {
209  // No '/' found (or empty entirely)
210  // => no instance or local
211 
213  }
214  else if
215  (
216  first == 0
217  #ifdef _WIN32
218  || (first == 2 && path[1] == ':') // Eg, d:/path
219  #endif
220  )
221  {
222  // Absolute path (starts with '/' or 'd:/')
223  // => no local
224 
225  instance = path.substr(0, last);
226 
227  const std::string ending = path.substr(last+1);
228  nameLen = ending.size(); // The raw length of name
229  name = word::validate(ending);
230  }
231  else
232  {
233  // Normal case.
234  // First part is instance, remainder is local
235  instance = path.substr(0, first);
236 
237  if (last > first)
238  {
239  // With local
240  local = path.substr(first+1, last-first-1);
241  }
242 
243  const std::string ending = path.substr(last+1);
244  nameLen = ending.size(); // The raw length of name
245  name = word::validate(ending);
246  }
247 
248  // Check for valid (and stripped) name, regardless of the debug level
249  if (!nameLen || nameLen != name.size())
250  {
252  << "has invalid word for name: \"" << name
253  << "\"\nwhile processing path: " << path << endl;
254 
255  return false;
256  }
257 
258  return true;
259 }
260 
261 
263 (
264  const IOobject& io,
265  const fileName& altFile,
266  const word& ioName
267 )
268 {
269  if (altFile.empty())
270  {
271  return io;
272  }
273 
274  // Construct from file path instead
275 
276  fileName altPath = altFile;
277 
278  if (isDir(altPath))
279  {
280  // Resolve directories as well
281 
282  if (ioName.empty())
283  {
284  altPath /= io.name();
285  }
286  else
287  {
288  altPath /= ioName;
289  }
290  }
291  altPath.expand();
292 
293 
294  return
295  IOobject
296  (
297  altPath,
298  io.db(),
299  io.readOpt(),
301  io.registerObject(),
302  io.globalObject()
303  );
304 }
305 
306 
308 {
309  const auto i = name.rfind('.');
310 
311  if (i == std::string::npos || i == 0)
312  {
313  return word();
314  }
315 
316  return name.substr(i+1);
317 }
318 
319 
321 {
322  const auto i = name.rfind('.');
323 
324  if (i == std::string::npos || i == 0)
325  {
326  return name;
327  }
328 
329  return name.substr(0, i);
330 }
331 
332 
333 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
334 
335 Foam::IOobject::IOobject(const objectRegistry& registry, IOobjectOption ioOpt)
336 :
337  IOobjectOption(ioOpt),
338  objState_(objectState::GOOD),
339  sizeofLabel_(static_cast<unsigned char>(sizeof(label))),
340  sizeofScalar_(static_cast<unsigned char>(sizeof(scalar))),
341  db_(registry)
342 {}
343 
344 
345 Foam::IOobject::IOobject
346 (
347  const word& name,
348  const fileName& instance,
349  const objectRegistry& registry,
350  IOobjectOption ioOpt
351 )
352 :
353  IOobject(registry, ioOpt)
354 {
355  name_ = name;
356  instance_ = instance;
357 
359  {
361  << "Constructing IOobject: " << name_ << endl;
362  }
363 }
364 
365 
366 Foam::IOobject::IOobject
367 (
368  const word& name,
369  const fileName& instance,
370  const fileName& local,
371  const objectRegistry& registry,
372  IOobjectOption ioOpt
373 )
374 :
375  IOobject(registry, ioOpt)
376 {
377  name_ = name;
378  instance_ = instance;
379  local_ = local;
380 
382  {
384  << "Constructing IOobject: " << name_ << endl;
385  }
386 }
387 
388 
389 Foam::IOobject::IOobject
390 (
391  const fileName& path,
392  const objectRegistry& registry,
393  IOobjectOption ioOpt
394 )
395 :
396  IOobject(registry, ioOpt)
397 {
398  if (!fileNameComponents(path, instance_, local_, name_))
399  {
401  << " invalid path specification"
402  << exit(FatalError);
403  }
404 
406  {
408  << "Constructing IOobject: " << name_ << endl;
409  }
410 }
411 
412 
413 Foam::IOobject::IOobject
414 (
415  const IOobject& io,
416  const objectRegistry& registry
417 )
418 :
419  IOobjectOption(static_cast<IOobjectOption>(io)),
420  objState_(io.objState_),
421  sizeofLabel_(io.sizeofLabel_),
422  sizeofScalar_(io.sizeofScalar_),
423 
424  name_(io.name_),
425  headerClassName_(io.headerClassName_),
426  note_(io.note_),
427  instance_(io.instance_),
428  local_(io.local_),
429 
430  db_(registry)
431 {}
432 
433 
434 Foam::IOobject::IOobject
435 (
436  const IOobject& io,
437  const word& name
438 )
439 :
440  IOobjectOption(static_cast<IOobjectOption>(io)),
441  objState_(io.objState_),
442  sizeofLabel_(io.sizeofLabel_),
443  sizeofScalar_(io.sizeofScalar_),
444 
445  name_(name),
446  headerClassName_(io.headerClassName_),
447  note_(io.note_),
448  instance_(io.instance_),
449  local_(io.local_),
451  db_(io.db_)
452 {}
453 
454 
455 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
458 {
459  return db_;
460 }
461 
464 {
465  return db_.time();
466 }
467 
470 {
471  return time().rootPath();
472 }
473 
476 {
477  return time().caseName();
478 }
479 
482 {
483  return time().globalCaseName();
484 }
485 
486 
488 {
489  if (file_isOutsideCase(instance()))
490  {
491  return instance();
492  }
493 
494  return rootPath()/caseName()/instance()/db_.dbDir()/local();
495 }
496 
497 
499 {
500  if (file_isOutsideCase(instance()))
501  {
502  return instance();
503  }
504 
505  return rootPath()/globalCaseName()/instance()/db_.dbDir()/local();
506 }
507 
508 
510 (
511  const word& instance,
512  const fileName& local
513 ) const
514 {
515  // Note: can only be called with relative instance since is word type
516  return rootPath()/caseName()/instance/db_.dbDir()/local;
517 }
518 
519 
521 (
522  const word& instance,
523  const fileName& local
524 ) const
525 {
526  // Note: can only be called with relative instance since is word type
527  return rootPath()/globalCaseName()/instance/db_.dbDir()/local;
528 }
529 
530 
532 {
533  if (file_isOutsideCase(instance()))
534  {
535  return instance()/name();
536  }
537 
538  return instance()/db_.dbDir()/local()/name();
539 }
540 
541 
543 (
544  const word& typeName,
545  const bool search
546 ) const
547 {
548  // Do not check for undecomposed files
549  return fileHandler().filePath(false, *this, typeName, search);
550 }
551 
552 
554 (
555  const word& typeName,
556  const bool search
557 ) const
558 {
559  // Check for undecomposed files
560  return fileHandler().filePath(true, *this, typeName, search);
561 }
562 
563 
564 // Foam::fileName Foam::IOobject::filePath
565 // (
566 // const bool isGlobal,
567 // const word& typeName,
568 // const bool search
569 // ) const
570 // {
571 // return fileHandler().filePath(isGlobal, *this, typeName, search);
572 // }
573 
574 
575 void Foam::IOobject::setBad(const string& s)
576 {
577  if (objState_ != objectState::GOOD)
578  {
580  << "Recurrent failure for object " << s
581  << exit(FatalError);
582  }
583 
584  if (error::level)
585  {
587  << "Broken object " << s << info() << endl;
588  }
589 
590  objState_ = objectState::BAD;
591 }
592 
593 
594 void Foam::IOobject::resetHeader(const word& newName)
595 {
596  if (!newName.empty())
597  {
598  name_ = newName;
599  }
600  objState_ = objectState::GOOD;
601  sizeofLabel_ = static_cast<unsigned char>(sizeof(label));
602  sizeofScalar_ = static_cast<unsigned char>(sizeof(scalar));
603  headerClassName_.clear();
604  note_.clear();
605 }
606 
607 
608 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
609 
611 {
612  readOpt(io.readOpt());
613  writeOpt(io.writeOpt());
614  // No change to registerObject
615  globalObject(io.globalObject());
616 
617  objState_ = io.objState_;
618  sizeofLabel_ = io.sizeofLabel_;
619  sizeofScalar_ = io.sizeofScalar_;
620 
621  name_ = io.name_;
622  headerClassName_ = io.headerClassName_;
623  note_ = io.note_;
624  instance_ = io.instance_;
625  local_ = io.local_;
626 }
627 
628 
629 // ************************************************************************* //
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:165
A class for handling file names.
Definition: fileName.H:72
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:547
static float fileModificationSkew
Time skew (seconds) for file modification checks.
Definition: IOobject.H:348
static void writeData(Ostream &os, const Type &val)
void operator=(const IOobject &io)
Copy assignment, copies all values (except the registry)
Definition: IOobject.C:603
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:598
const word & name() const noexcept
Return the object name.
Definition: IOobjectI.H:195
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:531
word member() const
Return member (name without the extension)
Definition: IOobjectI.H:207
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:568
word group() const
Return group (extension part of name)
Definition: IOobjectI.H:201
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 for the object (with instance, local,...).
Definition: IOobject.C:480
registerOptSwitch("fileModificationSkew", float, Foam::IOobject::fileModificationSkew)
const fileName & caseName() const noexcept
Return the Time::caseName()
Definition: IOobject.C:468
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 expressions::valueTypeCode::INVALID.
Definition: exprTraits.C:127
A class for handling words, derived from Foam::string.
Definition: word.H:63
fileCheckTypes
Enumeration defining the file checking options.
Definition: IOobject.H:192
static int maxFileModificationPolls
Max number of times to poll for file modification changes.
Definition: IOobject.H:353
const objectRegistry & db() const noexcept
Return the local objectRegistry.
Definition: IOobject.C:450
static bool file_isOutsideCase(const std::string &str)
Definition: IOobject.C:144
fileName localFilePath(const word &typeName, const bool search=true) const
Redirect to fileHandler filePath, searching locally.
Definition: IOobject.C:536
bool local
Definition: EEqn.H:20
const fileName & globalCaseName() const noexcept
Return the Time::globalCaseName()
Definition: IOobject.C:474
const Time & time() const noexcept
Return Time associated with the objectRegistry.
Definition: IOobject.C:456
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:56
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:203
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:343
const fileName & instance() const noexcept
Read access to instance path component.
Definition: IOobjectI.H:266
static char scopeSeparator
Character for scoping object names (&#39;:&#39; or &#39;_&#39;)
Definition: IOobject.H:338
bool starts_with(char c) const
True if string starts with given character (cf. C++20)
Definition: string.H:435
const fileName & rootPath() const noexcept
Return the Time::rootPath()
Definition: IOobject.C:462
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...
Definition: error.H:64
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:524
bool registerObject() const noexcept
Should objects created with this IOobject be registered?
fileName globalPath() const
The complete global path for the object (with instance, local,...)
Definition: IOobject.C:491
fileName search(const word &file, const fileName &directory)
Recursively search the given directory for the file.
Definition: fileName.C:642
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:278
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:587
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:172
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:256
#define InfoInFunction
Report an information message using Foam::Info.