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  // Revoke any registry ownership: we are already deleting
182  ownedByRegistry_ = false;
183 
184  // Remove registered object from objectRegistry
185  checkOut();
186 }
187 
188 
189 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
190 
192 {
193  if (!registered_)
194  {
195  // multiple checkin of same object is disallowed - this would mess up
196  // any mapping
197  registered_ = db().checkIn(*this);
198 
199  // check-in on defaultRegion is allowed to fail, since subsetted meshes
200  // are created with the same name as their originating mesh
201  if (!registered_ && debug && name() != polyMesh::defaultRegion)
202  {
203  if (debug == 2)
204  {
205  // for ease of finding where attempted duplicate check-in
206  // originated
208  << "failed to register object " << objectPath()
209  << " the name already exists in the objectRegistry" << endl
210  << "Contents:" << db().sortedToc()
211  << abort(FatalError);
212  }
213  else
214  {
216  << "failed to register object " << objectPath()
217  << " the name already exists in the objectRegistry"
218  << endl;
219  }
220  }
221  }
222 
223  return registered_;
224 }
225 
226 
228 {
229  forAllReverse(watchIndices_, i)
230  {
231  fileHandler().removeWatch(watchIndices_[i]);
232  }
233  watchIndices_.clear();
234 
235  if (registered_)
236  {
237  registered_ = false;
238 
239  return db().checkOut(this);
240  }
241 
242  return false;
243 }
244 
245 
246 Foam::label Foam::regIOobject::addWatch(const fileName& f)
247 {
248  label index = -1;
249 
250  if
251  (
252  registered_
253  && readOpt() == IOobject::MUST_READ_IF_MODIFIED
254  && time().runTimeModifiable()
255  )
256  {
257  index = fileHandler().findWatch(watchIndices_, f);
258 
259  if (index == -1)
260  {
261  index = watchIndices_.size();
262  watchIndices_.append(fileHandler().addWatch(f));
263  }
264  }
265 
266  return index;
267 }
268 
269 
271 {
272  if
273  (
274  registered_
275  && readOpt() == IOobject::MUST_READ_IF_MODIFIED
276  && time().runTimeModifiable()
277  )
278  {
279  fileName f = filePath();
280  if (!f.size())
281  {
282  // We don't have this file but would like to re-read it.
283  // Possibly if master-only reading mode.
284  f = objectPath();
285  }
286 
287  label index = fileHandler().findWatch(watchIndices_, f);
288  if (index != -1)
289  {
291  << "Object " << objectPath() << " of type " << type()
292  << " already watched with index " << watchIndices_[index]
293  << abort(FatalError);
294  }
295 
296  // If master-only reading only the master will have all dependencies
297  // so broadcast these to other ranks
298  const bool masterOnly
299  (
300  global()
301  && (
304  )
305  );
306 
307  if (masterOnly && Pstream::parRun())
308  {
309  // Get master watched files
310  fileNameList watchFiles;
311  if (Pstream::master())
312  {
313  watchFiles.resize(watchIndices_.size());
314  forAll(watchIndices_, i)
315  {
316  watchFiles[i] = fileHandler().getFile(watchIndices_[i]);
317  }
318  }
319  Pstream::broadcast(watchFiles);
320 
321  if (!Pstream::master())
322  {
323  // unregister current ones
324  forAllReverse(watchIndices_, i)
325  {
326  fileHandler().removeWatch(watchIndices_[i]);
327  }
328 
329  watchIndices_.clear();
330  forAll(watchFiles, i)
331  {
332  watchIndices_.append(fileHandler().addWatch(watchFiles[i]));
333  }
334  }
335  }
336 
337  watchIndices_.append(fileHandler().addWatch(f));
338  }
339 }
340 
341 
342 bool Foam::regIOobject::upToDate(const regIOobject& a) const
343 {
344  label da = a.eventNo()-eventNo_;
345 
346  // In case of overflow *this.event() might be 2G but a.event() might
347  // have overflowed to 0.
348  // Detect this by detecting a massive difference (labelMax/2) between
349  // the two events.
350  //
351  // a *this return
352  // - ----- ------
353  // normal operation:
354  // 11 10 false
355  // 11 11 false
356  // 10 11 true
357  // overflow situation:
358  // 0 big false
359  // big 0 true
360 
361  if (da > labelMax/2)
362  {
363  // *this.event overflowed but a.event not yet
364  return true;
365  }
366  else if (da < -labelMax/2)
367  {
368  // a.event overflowed but *this not yet
369  return false;
370  }
371  else if (da < 0)
372  {
373  // My event number higher than a
374  return true;
375  }
376 
377  return false;
378 }
379 
380 
382 (
383  const regIOobject& a,
384  const regIOobject& b
385 ) const
386 {
387  return upToDate(a) && upToDate(b);
388 }
389 
390 
392 (
393  const regIOobject& a,
394  const regIOobject& b,
395  const regIOobject& c
396 ) const
397 {
398  return upToDate(a) && upToDate(b) && upToDate(c);
399 }
400 
401 
403 (
404  const regIOobject& a,
405  const regIOobject& b,
406  const regIOobject& c,
407  const regIOobject& d
408 ) const
409 {
410  return upToDate(a) && upToDate(b) && upToDate(c) && upToDate(d);
411 }
412 
415 {
416  eventNo_ = db().getEvent();
417 }
418 
419 
420 void Foam::regIOobject::rename(const word& newName)
421 {
422  // Check out of objectRegistry
423  checkOut();
424 
425  IOobject::rename(newName);
426 
427  if (registerObject())
428  {
429  // Re-register object with objectRegistry
430  checkIn();
431  }
432 }
433 
436 {
437  return localFilePath(type());
438 }
439 
440 
442 {
443  // Note: Should be consistent with IOobject::typeHeaderOk(false)
444 
445  bool ok = true;
446 
447  fileName fName(filePath());
448 
449  ok = Foam::fileHandler().readHeader(*this, fName, type());
450 
451  if (!ok && IOobject::debug)
452  {
453  IOWarningInFunction(fName)
454  << "failed to read header of file " << objectPath()
455  << endl;
456  }
457 
458  return ok;
459 }
460 
461 
462 void Foam::regIOobject::operator=(const IOobject& io)
463 {
464  // Close any file
465  isPtr_.reset(nullptr);
466 
467  // Check out of objectRegistry
468  checkOut();
469 
471 
472  if (registerObject())
473  {
474  // Re-register object with objectRegistry
475  checkIn();
476  }
477 }
478 
479 
480 // ************************************************************************* //
bool upToDate(const regIOobject &) const
Return true if up-to-date with respect to given object.
Definition: regIOobject.C:335
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:118
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:565
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:407
virtual void rename(const word &newName)
Rename the object.
Definition: IOobject.H:626
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:639
bool headerOk()
Read and check header info. Does not check the headerClassName.
Definition: regIOobject.C:434
autoPtr< fileOperation > fileHandler(std::nullptr_t)
Delete current file handler.
virtual fileName filePath() const
Return complete path + object name if the file exists.
Definition: regIOobject.C:428
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:413
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: POSIX.C:752
IOobject io("surfaceFilmProperties", mesh.time().constant(), mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE, false)
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
Reading required, file watched for runTime modification.
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:220
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:313
virtual void addWatch()
Add file watch on object (if registered and READ_IF_MODIFIED)
Definition: regIOobject.C:263
virtual void rename(const word &newName)
Rename.
Definition: regIOobject.C:413
labelList f(nPoints)
static bool masterOnlyReading
To flag master-only reading of objects.
Definition: regIOobject.H:87
#define WarningInFunction
Report a warning using Foam::Warning.
const dimensionedScalar c
Speed of light in a vacuum.
static bool master(const label communicator=worldComm)
Am I the master rank.
Definition: UPstream.H:672
regIOobject is an abstract class derived from IOobject to handle automatic object registration with t...
Definition: regIOobject.H:69
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:429
List< fileName > fileNameList
A List of fileNames.
Definition: fileNameList.H:54
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:166
bool checkIn()
Add object to registry, if not already registered.
Definition: regIOobject.C:184
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
Namespace for OpenFOAM.
virtual ~regIOobject()
Destructor.
Definition: regIOobject.C:145