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