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