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-------------------------------------------------------------------------------
11License
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
37namespace Foam
38{
40}
41
43
44
45// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
46
47Foam::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
79Foam::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{
151 if (objectRegistry::debug)
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() == IOobject::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() == IOobject::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 broadcast these to other ranks
295 const bool masterOnly
296 (
297 global()
298 && (
301 )
302 );
303
304 if (masterOnly && Pstream::parRun())
305 {
306 // Get master watched files
307 fileNameList watchFiles;
308 if (Pstream::master())
309 {
310 watchFiles.resize(watchIndices_.size());
311 forAll(watchIndices_, i)
312 {
313 watchFiles[i] = fileHandler().getFile(watchIndices_[i]);
314 }
315 }
316 Pstream::broadcast(watchFiles);
317
318 if (!Pstream::master())
319 {
320 // unregister current ones
321 forAllReverse(watchIndices_, i)
322 {
323 fileHandler().removeWatch(watchIndices_[i]);
324 }
325
326 watchIndices_.clear();
327 forAll(watchFiles, i)
328 {
329 watchIndices_.append(fileHandler().addWatch(watchFiles[i]));
330 }
331 }
332 }
333
334 watchIndices_.append(fileHandler().addWatch(f));
335 }
336}
337
338
340{
341 label da = a.eventNo()-eventNo_;
342
343 // In case of overflow *this.event() might be 2G but a.event() might
344 // have overflowed to 0.
345 // Detect this by detecting a massive difference (labelMax/2) between
346 // the two events.
347 //
348 // a *this return
349 // - ----- ------
350 // normal operation:
351 // 11 10 false
352 // 11 11 false
353 // 10 11 true
354 // overflow situation:
355 // 0 big false
356 // big 0 true
357
358 if (da > labelMax/2)
359 {
360 // *this.event overflowed but a.event not yet
361 return true;
362 }
363 else if (da < -labelMax/2)
364 {
365 // a.event overflowed but *this not yet
366 return false;
367 }
368 else if (da < 0)
369 {
370 // My event number higher than a
371 return true;
372 }
373
374 return false;
375}
376
377
379(
380 const regIOobject& a,
381 const regIOobject& b
382) const
383{
384 return upToDate(a) && upToDate(b);
385}
386
387
389(
390 const regIOobject& a,
391 const regIOobject& b,
392 const regIOobject& c
393) const
394{
395 return upToDate(a) && upToDate(b) && upToDate(c);
396}
397
398
400(
401 const regIOobject& a,
402 const regIOobject& b,
403 const regIOobject& c,
404 const regIOobject& d
405) const
406{
407 return upToDate(a) && upToDate(b) && upToDate(c) && upToDate(d);
408}
409
410
412{
413 eventNo_ = db().getEvent();
414}
415
416
417void Foam::regIOobject::rename(const word& newName)
418{
419 // Check out of objectRegistry
420 checkOut();
421
422 IOobject::rename(newName);
423
424 if (registerObject())
425 {
426 // Re-register object with objectRegistry
427 checkIn();
428 }
429}
430
431
433{
434 return localFilePath(type());
435}
436
437
439{
440 // Note: Should be consistent with IOobject::typeHeaderOk(false)
441
442 bool ok = true;
443
444 fileName fName(filePath());
445
446 ok = Foam::fileHandler().readHeader(*this, fName, type());
447
448 if (!ok && IOobject::debug)
449 {
451 << "failed to read header of file " << objectPath()
452 << endl;
453 }
454
455 return ok;
456}
457
458
459void Foam::regIOobject::operator=(const IOobject& io)
460{
461 // Close any file
462 isPtr_.reset(nullptr);
463
464 // Check out of objectRegistry
465 checkOut();
466
468
469 if (registerObject())
470 {
471 // Re-register object with objectRegistry
472 checkIn();
473 }
474}
475
476
477// ************************************************************************* //
bool upToDate() const
Access to the up-to-date flag.
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:170
bool registerObject() const noexcept
Should object created with this IOobject be registered?
Definition: IOobjectI.H:107
void operator=(const IOobject &io)
Copy assignment, copies all values (except the registry)
Definition: IOobject.C:624
static fileCheckTypes fileModificationChecking
Type of file modification checking.
Definition: IOobject.H:303
virtual void rename(const word &newName)
Rename the object.
Definition: IOobject.H:497
@ MUST_READ_IF_MODIFIED
Definition: IOobject.H:180
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:139
static void broadcast(Type &value, const label comm=UPstream::worldComm)
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:433
A class for handling file names.
Definition: fileName.H:76
virtual bool removeWatch(const label) const
Remove watch on a file (using handle)
virtual label findWatch(const labelList &watchIndices, const fileName &) const
Find index (or -1) of file in list of handles.
virtual bool readHeader(IOobject &, const fileName &, const word &typeName) const =0
Read object header from supplied file.
virtual fileName getFile(const label) const
Get name of file being watched (using handle)
static word defaultRegion
Return the default region name.
Definition: polyMesh.H:321
regIOobject is an abstract class derived from IOobject to handle automatic object registration with t...
Definition: regIOobject.H:76
void setUpToDate()
Set as up-to-date.
Definition: regIOobject.C:411
virtual fileName filePath() const
Return complete path + object name if the file exists.
Definition: regIOobject.C:432
static bool masterOnlyReading
To flag master-only reading of objects.
Definition: regIOobject.H:87
bool headerOk()
Read and check header info. Does not check the headerClassName.
Definition: regIOobject.C:438
label eventNo() const noexcept
Event number at last update.
Definition: regIOobjectI.H:191
bool checkOut()
Remove all file watches and remove object from registry.
Definition: regIOobject.C:224
virtual ~regIOobject()
Destructor.
Definition: regIOobject.C:149
virtual void addWatch()
Add file watch on object (if registered and READ_IF_MODIFIED)
Definition: regIOobject.C:267
virtual void rename(const word &newName)
Rename.
Definition: regIOobject.C:417
bool checkIn()
Add object to registry, if not already registered.
Definition: regIOobject.C:188
splitCell * master() const
Definition: splitCell.H:113
A class for handling words, derived from Foam::string.
Definition: word.H:68
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition: className.H:121
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
IOobject io("surfaceFilmProperties", mesh.time().constant(), mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE, false)
#define IOWarningInFunction(ios)
Report an IO warning using Foam::Warning.
#define WarningInFunction
Report a warning using Foam::Warning.
Namespace for OpenFOAM.
const fileOperation & fileHandler()
Get current file handler.
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: MSwindows.C:598
constexpr label labelMax
Definition: label.H:61
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
errorManip< error > abort(error &err)
Definition: errorManip.H:144
error FatalError
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:59
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
labelList f(nPoints)
volScalarField & b
Definition: createFields.H:27
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333
#define forAllReverse(list, i)
Reverse loop across all elements in list.
Definition: stdFoam.H:346