regIOobject.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) 2018-2022 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 Note
28  Included by global/globals.C
29 
30 \*---------------------------------------------------------------------------*/
31 
32 #include "regIOobject.H"
33 #include "Time.H"
34 #include "polyMesh.H"
35 #include "dictionary.H"
36 #include "fileOperation.H"
37 
38 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
39 
40 namespace Foam
41 {
42  defineTypeNameAndDebug(regIOobject, 0);
43 }
44 
46 
47 
48 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
49 
50 Foam::regIOobject::regIOobject(const IOobject& io, const bool isTimeObject)
51 :
52  IOobject(io),
53  registered_(false),
54  ownedByRegistry_(false),
55  watchIndices_(),
56  eventNo_(isTimeObject ? 0 : db().getEvent()), // No event for top-level Time
57  metaDataPtr_(nullptr),
58  isPtr_(nullptr)
59 {
60  if (registerObject())
61  {
62  // Register (check-in) with objectRegistry if requested
63  checkIn();
64  }
65 }
66 
67 
68 Foam::regIOobject::regIOobject(const regIOobject& rio)
69 :
70  IOobject(rio),
71  registered_(false),
72  ownedByRegistry_(false),
73  watchIndices_(rio.watchIndices_),
74  eventNo_(db().getEvent()),
75  metaDataPtr_(rio.metaDataPtr_.clone()),
76  isPtr_(nullptr)
77 {
78  // Do not register copy with objectRegistry
79 }
80 
81 
82 Foam::regIOobject::regIOobject(const regIOobject& rio, bool registerCopy)
83 :
84  IOobject(rio),
85  registered_(false),
86  ownedByRegistry_(false),
87  watchIndices_(),
88  eventNo_(db().getEvent()),
89  metaDataPtr_(rio.metaDataPtr_.clone()),
90  isPtr_(nullptr)
91 {
92  if (registerCopy)
93  {
94  if (rio.registered_)
95  {
96  // Unregister the original object
97  const_cast<regIOobject&>(rio).checkOut();
98  }
99  checkIn();
100  }
101 }
102 
103 
105 (
106  const word& newName,
107  const regIOobject& rio,
108  bool registerCopy
109 )
110 :
111  IOobject(newName, rio.instance(), rio.local(), rio.db()),
112  registered_(false),
113  ownedByRegistry_(false),
114  watchIndices_(),
115  eventNo_(db().getEvent()),
116  metaDataPtr_(rio.metaDataPtr_.clone()),
117  isPtr_(nullptr)
118 {
119  if (registerCopy)
120  {
121  // NOTE: could also unregister the original object
122  // if (rio.registered_ && newName == rio.name()) ...
124  checkIn();
125  }
126 }
127 
128 
130 (
131  const IOobject& io,
132  const regIOobject& rio
133 )
134 :
135  IOobject(io),
136  registered_(false),
137  ownedByRegistry_(false),
138  watchIndices_(),
139  eventNo_(db().getEvent()),
140  metaDataPtr_(rio.metaDataPtr_.clone()),
141  isPtr_(nullptr)
142 {
143  if (registerObject())
144  {
146  }
147 }
148 
149 
150 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
151 
153 {
155  {
156  Pout<< "Destroy regIOobject: " << name()
157  << " type=" << type()
158  << " registered=" << registered_
159  << " owned=" << ownedByRegistry_
160  << " directory=" << path()
161  << endl;
162  }
163 
164  // Deletion of a regIOobject should remove itself from its registry
165  // (ie, checkOut), but there are different paths for destruction to occur.
166  // The complications are only when the object is ownedByRegistry.
167  //
168  // 1. The objectRegistry clear()/erase() is called (and object is
169  // 'ownedByRegistry').
170  //
171  // - Mark as unowned/unregistered prior to deletion.
172  // This ensures that this checkOut() only clears file watches and
173  // does nothing else.
174  //
175  // 2. The regIOobject is deleted directly (and also 'ownedByRegistry').
176  //
177  // - Mark as unowned (but keep as registered) prior to triggering
178  // checkOut(). By being 'unowned', the registry will not attempt a
179  // second deletion when the object name is removed from the registry.
180 
181  // Reset the cache state (if any)
182  db().resetCacheTemporaryObject(this);
183 
184  // Revoke any registry ownership: we are already deleting
185  ownedByRegistry_ = false;
186 
187  // Remove registered object from objectRegistry
188  checkOut();
189 }
190 
191 
192 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
193 
195 {
196  if (!registered_)
197  {
198  // multiple checkin of same object is disallowed - this would mess up
199  // any mapping
200  registered_ = db().checkIn(*this);
201 
202  // check-in on defaultRegion is allowed to fail, since subsetted meshes
203  // are created with the same name as their originating mesh
204  if (!registered_ && debug && name() != polyMesh::defaultRegion)
205  {
206  if (debug == 2)
207  {
208  // for ease of finding where attempted duplicate check-in
209  // originated
211  << "failed to register object " << objectPath()
212  << " the name already exists in the objectRegistry" << endl
213  << "Contents:" << db().sortedToc()
214  << abort(FatalError);
215  }
216  else
217  {
219  << "failed to register object " << objectPath()
220  << " the name already exists in the objectRegistry"
221  << endl;
222  }
223  }
224  }
225 
226  return registered_;
227 }
228 
229 
231 {
232  forAllReverse(watchIndices_, i)
233  {
234  fileHandler().removeWatch(watchIndices_[i]);
235  }
236  watchIndices_.clear();
237 
238  if (registered_)
239  {
240  registered_ = false;
241 
242  return db().checkOut(this);
243  }
244 
245  return false;
246 }
247 
248 
249 Foam::label Foam::regIOobject::addWatch(const fileName& f)
250 {
251  label index = -1;
252 
253  if
254  (
255  registered_
256  && readOpt() == IOobject::MUST_READ_IF_MODIFIED
257  && time().runTimeModifiable()
258  )
259  {
260  index = fileHandler().findWatch(watchIndices_, f);
261 
262  if (index == -1)
263  {
264  index = watchIndices_.size();
265  watchIndices_.append(fileHandler().addWatch(f));
266  }
267  }
268 
269  return index;
270 }
271 
272 
274 {
275  if
276  (
277  registered_
278  && readOpt() == IOobject::MUST_READ_IF_MODIFIED
279  && time().runTimeModifiable()
280  )
281  {
282  fileName f = filePath();
283  if (!f.size())
284  {
285  // We don't have this file but would like to re-read it.
286  // Possibly if master-only reading mode.
287  f = objectPath();
288  }
289 
290  label index = fileHandler().findWatch(watchIndices_, f);
291  if (index != -1)
292  {
294  << "Object " << objectPath() << " of type " << type()
295  << " already watched with index " << watchIndices_[index]
296  << abort(FatalError);
297  }
298 
299  // If master-only reading only the master will have all dependencies
300  // so broadcast these to other ranks
301  const bool masterOnly
302  (
303  global()
304  && (
307  )
308  );
309 
310  if (masterOnly && Pstream::parRun())
311  {
312  // Get master watched files
313  fileNameList watchFiles;
314  if (Pstream::master())
315  {
316  watchFiles.resize(watchIndices_.size());
317  forAll(watchIndices_, i)
318  {
319  watchFiles[i] = fileHandler().getFile(watchIndices_[i]);
320  }
321  }
322  Pstream::broadcast(watchFiles);
323 
324  if (!Pstream::master())
325  {
326  // unregister current ones
327  forAllReverse(watchIndices_, i)
328  {
329  fileHandler().removeWatch(watchIndices_[i]);
330  }
331 
332  watchIndices_.clear();
333  forAll(watchFiles, i)
334  {
335  watchIndices_.append(fileHandler().addWatch(watchFiles[i]));
336  }
337  }
338  }
339 
340  watchIndices_.append(fileHandler().addWatch(f));
341  }
342 }
343 
344 
345 bool Foam::regIOobject::upToDate(const regIOobject& a) const
346 {
347  label da = a.eventNo()-eventNo_;
348 
349  // In case of overflow *this.event() might be 2G but a.event() might
350  // have overflowed to 0.
351  // Detect this by detecting a massive difference (labelMax/2) between
352  // the two events.
353  //
354  // a *this return
355  // - ----- ------
356  // normal operation:
357  // 11 10 false
358  // 11 11 false
359  // 10 11 true
360  // overflow situation:
361  // 0 big false
362  // big 0 true
363 
364  if (da > labelMax/2)
365  {
366  // *this.event overflowed but a.event not yet
367  return true;
368  }
369  else if (da < -labelMax/2)
370  {
371  // a.event overflowed but *this not yet
372  return false;
373  }
374  else if (da < 0)
375  {
376  // My event number higher than a
377  return true;
378  }
379 
380  return false;
381 }
382 
383 
385 (
386  const regIOobject& a,
387  const regIOobject& b
388 ) const
389 {
390  return upToDate(a) && upToDate(b);
391 }
392 
393 
395 (
396  const regIOobject& a,
397  const regIOobject& b,
398  const regIOobject& c
399 ) const
400 {
401  return upToDate(a) && upToDate(b) && upToDate(c);
402 }
403 
404 
406 (
407  const regIOobject& a,
408  const regIOobject& b,
409  const regIOobject& c,
410  const regIOobject& d
411 ) const
412 {
413  return upToDate(a) && upToDate(b) && upToDate(c) && upToDate(d);
414 }
415 
418 {
419  eventNo_ = db().getEvent();
420 }
421 
422 
423 void Foam::regIOobject::rename(const word& newName)
424 {
425  // Check out of objectRegistry
426  checkOut();
427 
428  IOobject::rename(newName);
429 
430  if (registerObject())
431  {
432  // Re-register object with objectRegistry
433  checkIn();
434  }
435 }
436 
439 {
440  return localFilePath(type());
441 }
442 
443 
445 {
446  // Note: Should be consistent with IOobject::typeHeaderOk(false)
447 
448  bool ok = true;
449 
450  fileName fName(filePath());
451 
452  ok = Foam::fileHandler().readHeader(*this, fName, type());
453 
454  if (!ok && IOobject::debug)
455  {
456  IOWarningInFunction(fName)
457  << "failed to read header of file " << objectPath()
458  << endl;
459  }
460 
461  return ok;
462 }
463 
464 
465 void Foam::regIOobject::operator=(const IOobject& io)
466 {
467  // Close any file
468  isPtr_.reset(nullptr);
469 
470  // Check out of objectRegistry
471  checkOut();
472 
474 
475  if (registerObject())
476  {
477  // Re-register object with objectRegistry
478  checkIn();
479  }
480 }
481 
482 
483 // ************************************************************************* //
bool upToDate(const regIOobject &) const
Return true if up-to-date with respect to given object.
Definition: regIOobject.C:338
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
A class for handling file names.
Definition: fileName.H:71
void operator=(const IOobject &io)
Copy assignment, copies all values (except the registry)
Definition: IOobject.C:563
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:132
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
void setUpToDate()
Set as up-to-date.
Definition: regIOobject.C:410
virtual void rename(const word &newName)
Rename the object.
Definition: IOobject.H:648
regIOobject(const IOobject &io, const bool isTimeObject=false)
Construct from IOobject. The optional flag adds special handling if the object is the top-level regIO...
Definition: regIOobject.C:43
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:487
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:1004
bool headerOk()
Read and check header info. Does not check the headerClassName.
Definition: regIOobject.C:437
refPtr< fileOperation > fileHandler(std::nullptr_t)
Delete current file handler - forwards to fileOperation::handler()
virtual fileName filePath() const
Return complete path + object name if the file exists.
Definition: regIOobject.C:431
static void broadcast(Type &value, const label comm=UPstream::worldComm)
Broadcast content (contiguous or non-contiguous) to all processes in communicator.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:414
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: POSIX.C:799
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:52
const dimensionedScalar b
Wien displacement law constant: default SI units: [m.K].
Definition: createFields.H:27
A class for handling words, derived from Foam::string.
Definition: word.H:63
static word defaultRegion
Return the default region name.
Definition: polyMesh.H:397
bool local
Definition: EEqn.H:20
errorManip< error > abort(error &err)
Definition: errorManip.H:139
bool checkOut()
Remove all file watches and remove object from registry.
Definition: regIOobject.C:223
int debug
Static debugging option.
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
defineTypeNameAndDebug(combustionModel, 0)
static fileCheckTypes fileModificationChecking
Type of file modification checking.
Definition: IOobject.H:326
virtual void addWatch()
Add file watch on object (if registered and READ_IF_MODIFIED)
Definition: regIOobject.C:266
virtual void rename(const word &newName)
Rename.
Definition: regIOobject.C:416
labelList f(nPoints)
static bool masterOnlyReading
To flag master-only reading of objects.
Definition: regIOobject.H:83
#define WarningInFunction
Report a warning using Foam::Warning.
const dimensionedScalar c
Speed of light in a vacuum.
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition: UPstream.H:1037
regIOobject is an abstract class derived from IOobject to handle automatic object registration with t...
Definition: regIOobject.H:65
constexpr label labelMax
Definition: label.H:55
bool registerObject() const noexcept
Should objects created with this IOobject be registered?
#define IOWarningInFunction(ios)
Report an IO warning using Foam::Warning.
#define forAllReverse(list, i)
Reverse loop across all elements in list.
Definition: stdFoam.H:430
IOobject io("surfaceFilmProperties", mesh.time().constant(), mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE, IOobject::NO_REGISTER)
List< fileName > fileNameList
List of fileName.
Definition: fileNameList.H:32
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:171
bool checkIn()
Add object to registry, if not already registered.
Definition: regIOobject.C:187
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
Namespace for OpenFOAM.
virtual ~regIOobject()
Destructor.
Definition: regIOobject.C:145