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  const_cast<regIOobject&>(rio).checkOut();
113  }
114  checkIn();
115  }
116 }
117 
118 
120 (
121  const word& newName,
122  const regIOobject& rio,
123  bool registerCopy
124 )
125 :
126  IOobject(newName, rio.instance(), rio.local(), rio.db()),
127  registered_(false),
128  ownedByRegistry_(false),
129  watchIndices_(),
130  eventNo_(db().getEvent()),
131  isPtr_(nullptr)
132 {
133  if (registerCopy)
134  {
135  checkIn();
136  }
137 }
138 
139 
141 (
142  const IOobject& io,
143  const regIOobject& rio
144 )
145 :
146  IOobject(io),
147  registered_(false),
148  ownedByRegistry_(false),
149  watchIndices_(),
150  eventNo_(db().getEvent()),
151  isPtr_(nullptr)
152 {
153  if (registerObject())
154  {
155  checkIn();
156  }
157 }
158 
159 
160 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
161 
163 {
165  {
166  Pout<< "Destroy regIOobject: " << name()
167  << " type=" << type()
168  << " registered=" << registered_
169  << " owned=" << ownedByRegistry_
170  << " directory=" << path()
171  << endl;
172  }
173 
174  // Deletion of a regIOobject should remove itself from its registry
175  // (ie, checkOut), but there are different paths for destruction to occur.
176  // The complications are only when the object is ownedByRegistry.
177  //
178  // 1. The objectRegistry clear()/erase() is called (and object is
179  // 'ownedByRegistry').
180  //
181  // - Mark as unowned/unregistered prior to deletion.
182  // This ensures that this checkOut() only clears file watches and
183  // does nothing else.
184  //
185  // 2. The regIOobject is deleted directly (and also 'ownedByRegistry').
186  //
187  // - Mark as unowned (but keep as registered) prior to triggering
188  // checkOut(). By being 'unowned', the registry will not attempt a
189  // second deletion when the object name is removed from the registry.
190 
191  // Revoke any registry ownership: we are already deleting
192  ownedByRegistry_ = false;
193 
194  // Remove registered object from objectRegistry
195  checkOut();
196 }
197 
198 
199 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
200 
202 {
203  if (!registered_)
204  {
205  // multiple checkin of same object is disallowed - this would mess up
206  // any mapping
207  registered_ = db().checkIn(*this);
208 
209  // check-in on defaultRegion is allowed to fail, since subsetted meshes
210  // are created with the same name as their originating mesh
211  if (!registered_ && debug && name() != polyMesh::defaultRegion)
212  {
213  if (debug == 2)
214  {
215  // for ease of finding where attempted duplicate check-in
216  // originated
218  << "failed to register object " << objectPath()
219  << " the name already exists in the objectRegistry" << endl
220  << "Contents:" << db().sortedToc()
221  << abort(FatalError);
222  }
223  else
224  {
226  << "failed to register object " << objectPath()
227  << " the name already exists in the objectRegistry"
228  << endl;
229  }
230  }
231  }
232 
233  return registered_;
234 }
235 
236 
238 {
239  forAllReverse(watchIndices_, i)
240  {
241  fileHandler().removeWatch(watchIndices_[i]);
242  }
243  watchIndices_.clear();
244 
245  if (registered_)
246  {
247  registered_ = false;
248 
249  return db().checkOut(this);
250  }
251 
252  return false;
253 }
254 
255 
257 {
258  label index = -1;
259 
260  if
261  (
262  registered_
263  && readOpt() == MUST_READ_IF_MODIFIED
264  && time().runTimeModifiable()
265  )
266  {
267  index = fileHandler().findWatch(watchIndices_, f);
268 
269  if (index == -1)
270  {
271  index = watchIndices_.size();
272  watchIndices_.append(fileHandler().addWatch(f));
273  }
274  }
275 
276  return index;
277 }
278 
279 
281 {
282  if
283  (
284  registered_
285  && readOpt() == MUST_READ_IF_MODIFIED
286  && time().runTimeModifiable()
287  )
288  {
289  fileName f = filePath();
290  if (!f.size())
291  {
292  // We don't have this file but would like to re-read it.
293  // Possibly if master-only reading mode.
294  f = objectPath();
295  }
296 
297  label index = fileHandler().findWatch(watchIndices_, f);
298  if (index != -1)
299  {
301  << "Object " << objectPath() << " of type " << type()
302  << " already watched with index " << watchIndices_[index]
303  << abort(FatalError);
304  }
305 
306  // If master-only reading only the master will have all dependencies
307  // so scatter these to slaves
308  bool masterOnly =
309  global()
310  && (
311  regIOobject::fileModificationChecking == timeStampMaster
312  || regIOobject::fileModificationChecking == inotifyMaster
313  );
314 
315  if (masterOnly && Pstream::parRun())
316  {
317  // Get master watched files
318  fileNameList watchFiles;
319  if (Pstream::master())
320  {
321  watchFiles.setSize(watchIndices_.size());
322  forAll(watchIndices_, i)
323  {
324  watchFiles[i] = fileHandler().getFile(watchIndices_[i]);
325  }
326  }
327  Pstream::scatter(watchFiles);
328 
329  if (!Pstream::master())
330  {
331  // unregister current ones
332  forAllReverse(watchIndices_, i)
333  {
334  fileHandler().removeWatch(watchIndices_[i]);
335  }
336 
337  watchIndices_.clear();
338  forAll(watchFiles, i)
339  {
340  watchIndices_.append(fileHandler().addWatch(watchFiles[i]));
341  }
342  }
343  }
344 
345  watchIndices_.append(fileHandler().addWatch(f));
346  }
347 }
348 
349 
351 {
352  label da = a.eventNo()-eventNo_;
353 
354  // In case of overflow *this.event() might be 2G but a.event() might
355  // have overflowed to 0.
356  // Detect this by detecting a massive difference (labelMax/2) between
357  // the two events.
358  //
359  // a *this return
360  // - ----- ------
361  // normal operation:
362  // 11 10 false
363  // 11 11 false
364  // 10 11 true
365  // overflow situation:
366  // 0 big false
367  // big 0 true
368 
369  if (da > labelMax/2)
370  {
371  // *this.event overflowed but a.event not yet
372  return true;
373  }
374  else if (da < -labelMax/2)
375  {
376  // a.event overflowed but *this not yet
377  return false;
378  }
379  else if (da < 0)
380  {
381  // My event number higher than a
382  return true;
383  }
384 
385  return false;
386 }
387 
388 
390 (
391  const regIOobject& a,
392  const regIOobject& b
393 ) const
394 {
395  return upToDate(a) && upToDate(b);
396 }
397 
398 
400 (
401  const regIOobject& a,
402  const regIOobject& b,
403  const regIOobject& c
404 ) const
405 {
406  return upToDate(a) && upToDate(b) && upToDate(c);
407 }
408 
409 
411 (
412  const regIOobject& a,
413  const regIOobject& b,
414  const regIOobject& c,
415  const regIOobject& d
416 ) const
417 {
418  return upToDate(a) && upToDate(b) && upToDate(c) && upToDate(d);
419 }
420 
421 
423 {
424  eventNo_ = db().getEvent();
425 }
426 
427 
428 void Foam::regIOobject::rename(const word& newName)
429 {
430  // Check out of objectRegistry
431  checkOut();
432 
433  IOobject::rename(newName);
434 
435  if (registerObject())
436  {
437  // Re-register object with objectRegistry
438  checkIn();
439  }
440 }
441 
442 
444 {
445  return localFilePath(type());
446 }
447 
448 
450 {
451  // Note: Should be consistent with IOobject::typeHeaderOk(false)
452 
453  bool ok = true;
454 
455  fileName fName(filePath());
456 
457  ok = Foam::fileHandler().readHeader(*this, fName, type());
458 
459  if (!ok && IOobject::debug)
460  {
461  IOWarningInFunction(fName)
462  << "failed to read header of file " << objectPath()
463  << endl;
464  }
465 
466  return ok;
467 }
468 
469 
470 void Foam::regIOobject::operator=(const IOobject& io)
471 {
472  // Close any file
473  isPtr_.clear();
474 
475  // Check out of objectRegistry
476  checkOut();
477 
479 
480  if (registerObject())
481  {
482  // Re-register object with objectRegistry
483  checkIn();
484  }
485 }
486 
487 
488 // ************************************************************************* //
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:65
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:312
Foam::regIOobject::upToDate
bool upToDate(const regIOobject &) const
Return true if up-to-date with respect to given object.
Definition: regIOobject.C:350
Foam::regIOobject::fileModificationSkew
static float fileModificationSkew
Definition: regIOobject.H:131
Foam::IOobject::instance
const fileName & instance() const
Definition: IOobjectI.H:167
Foam::regIOobject::addWatch
virtual void addWatch()
Add file watch on object (if registered and READ_IF_MODIFIED)
Definition: regIOobject.C:280
Foam::regIOobject::regIOobject
regIOobject(const IOobject &io, const bool isTime=false)
Definition: regIOobject.C:70
Foam::UPstream::parRun
static bool & parRun()
Is this a parallel run?
Definition: UPstream.H:414
Foam::regIOobject::checkIn
bool checkIn()
Add object to registry, if not already registered.
Definition: regIOobject.C:201
Foam::IOobject::fileModificationChecking
static fileCheckTypes fileModificationChecking
Type of file modification checking.
Definition: IOobject.H:207
Foam::regIOobject::maxFileModificationPolls
static int maxFileModificationPolls
Definition: regIOobject.H:133
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:1181
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:337
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:83
Foam::Pout
prefixOSstream Pout
An Ostream wrapper for parallel output to std::cout.
polyMesh.H
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:290
Foam::fileOperation::getFile
virtual fileName getFile(const label) const
Get name of file being watched (using handle)
Definition: fileOperation.C:645
Foam::IOobject::db
const objectRegistry & db() const
Return the local objectRegistry.
Definition: IOobject.C:432
Foam::IOobject::registerObject
bool registerObject() const
Should object created with this IOobject be registered?
Definition: IOobjectI.H:88
Foam::IOobject::local
const fileName & local() const
Definition: IOobjectI.H:179
Foam::label
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:62
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:85
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:137
registerOptSwitch
registerOptSwitch("fileModificationSkew", float, Foam::regIOobject::fileModificationSkew)
Foam::IOobject::rename
virtual void rename(const word &newName)
Rename.
Definition: IOobject.H:368
Foam::regIOobject::setUpToDate
void setUpToDate()
Set as up-to-date.
Definition: regIOobject.C:422
Foam::fileOperation::removeWatch
virtual bool removeWatch(const label) const
Remove watch on a file (using handle)
Definition: fileOperation.C:585
Foam::IOobject::operator=
void operator=(const IOobject &io)
Definition: IOobject.C:524
Foam::UPstream::master
static bool master(const label communicator=0)
Am I the master process.
Definition: UPstream.H:438
Time.H
Foam::regIOobject
regIOobject is an abstract class derived from IOobject to handle automatic object registration with t...
Definition: regIOobject.H:67
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:355
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:237
f
labelList f(nPoints)
Foam::regIOobject::rename
virtual void rename(const word &newName)
Rename.
Definition: regIOobject.C:428
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:443
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:592
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:303
registerSwitch.H
IOWarningInFunction
#define IOWarningInFunction(ios)
Report an IO warning using Foam::Warning.
Definition: messageStream.H:306
Foam::regIOobject::~regIOobject
virtual ~regIOobject()
Destructor.
Definition: regIOobject.C:162
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:294
Foam::regIOobject::headerOk
bool headerOk()
Read and check header info.
Definition: regIOobject.C:449