Loading...
Searching...
No Matches
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-2023 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
27Note
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
40namespace Foam
41{
44
46
47
48// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
49
50Foam::regIOobject::regIOobject(const IOobject& io, const bool isTimeObject)
51:
52 IOobject(io),
53 registered_(false),
54 ownedByRegistry_(false),
55 eventNo_(isTimeObject ? 0 : db().getEvent()), // No event for top-level Time
56 metaDataPtr_(nullptr),
57 isPtr_(nullptr)
58{
60 {
61 // Register (check-in) with objectRegistry if requested
62 checkIn();
63 }
64}
65
66
67Foam::regIOobject::regIOobject(const regIOobject& rio)
68:
69 IOobject(rio),
70 registered_(false),
71 ownedByRegistry_(false),
72 eventNo_(db().getEvent()),
73 watchFiles_(rio.watchFiles_),
74 watchIndices_(rio.watchIndices_),
75 metaDataPtr_(rio.metaDataPtr_.clone()),
76 isPtr_(nullptr)
77{
78 // Do not register copy with objectRegistry
79}
80
81
82Foam::regIOobject::regIOobject(const regIOobject& rio, bool registerCopy)
83:
84 IOobject(rio),
85 registered_(false),
86 ownedByRegistry_(false),
87 eventNo_(db().getEvent()),
88 metaDataPtr_(rio.metaDataPtr_.clone()),
89 isPtr_(nullptr)
90{
91 if (registerCopy)
92 {
93 if (rio.registered_)
94 {
95 // Unregister the original object
96 const_cast<regIOobject&>(rio).checkOut();
97 }
98 checkIn();
99 }
100}
101
102
104(
105 const word& newName,
106 const regIOobject& rio,
107 bool registerCopy
108)
109:
110 IOobject(newName, rio.instance(), rio.local(), rio.db()),
111 registered_(false),
112 ownedByRegistry_(false),
113 eventNo_(db().getEvent()),
114 metaDataPtr_(rio.metaDataPtr_.clone()),
115 isPtr_(nullptr)
116{
117 if (registerCopy)
118 {
119 // NOTE: could also unregister the original object
120 // if (rio.registered_ && newName == rio.name()) ...
121
122 checkIn();
123 }
124}
125
126
128(
129 const IOobject& io,
130 const regIOobject& rio
131)
132:
133 IOobject(io),
134 registered_(false),
135 ownedByRegistry_(false),
136 eventNo_(db().getEvent()),
137 metaDataPtr_(rio.metaDataPtr_.clone()),
138 isPtr_(nullptr)
139{
141 {
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 // Reset the cache state (if any)
179 db().resetCacheTemporaryObject(this);
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: " << name() << ' '
209 << objectRelPath()
210 << " : the name already exists in the registry" << nl
211 << "Contents:" << flatOutput(db().sortedToc()) << endl
212 << abort(FatalError);
213 }
214 else
215 {
217 << "Failed to register: " << name() << ' '
218 << objectRelPath()
219 << " : the name already exists in the registry" << endl;
220 }
222 }
223
224 return registered_;
225}
226
227
229{
230 forAllReverse(watchIndices_, i)
231 {
232 fileHandler().removeWatch(watchIndices_[i]);
233 }
234 watchIndices_.clear();
235 watchFiles_.clear();
236
237 if (registered_)
238 {
239 registered_ = false;
240
241 return db().checkOut(this);
242 }
243
244 return false;
245}
246
247
248Foam::label Foam::regIOobject::addWatch(const fileName& f)
249{
250 label index = -1;
251
252 if
253 (
254 registered_
255 && readOpt() == IOobjectOption::READ_MODIFIED
256 && time().runTimeModifiable()
257 )
258 {
259 //- 1. Directly add to fileHandler
260 //index = fileHandler().findWatch(watchIndices_, f);
261 //
262 //if (index == -1)
263 //{
264 // index = watchIndices_.size();
265 // watchIndices_.push_back(fileHandler().addWatch(f));
266 //}
267
268 //- 2. Delay adding; add to list and handle in addWatch() later on
269 // Note: what do we return?
270 index = watchFiles_.size();
271 watchFiles_.push_back(f);
272 }
273
274 return index;
275}
276
279{
280 // Everyone or just master
281 const bool masterOnly
282 (
283 global()
285 );
286
287 // if (debug)
288 // {
289 // Pout<< "regIOobject::addWatch " << watchIndices_.size()
290 // << " indices master-only:" << masterOnly
291 // << " watchFiles: " << watchFiles_ << endl;
292 // }
293
294 if
295 (
296 registered_
298 && time().runTimeModifiable()
299 )
300 {
301 fileName f = filePath();
302 if (f.empty())
303 {
304 // We don't have this file but would like to re-read it.
305 // Possibly if master-only reading mode.
306 f = objectPath();
307 }
308
309 label index = fileHandler().findWatch(watchIndices_, f);
310 if (index != -1)
311 {
313 << "Object " << objectPath() << " of type " << type()
314 << " already watched with index " << watchIndices_[index]
315 << abort(FatalError);
316 }
317
318 // If master-only reading only the master will have all dependencies
319 // so broadcast these to other ranks
320
321 if (masterOnly && UPstream::parRun())
322 {
323 // Get all files watched on master, and broadcast at once
324 fileNameList filesToWatch;
325 if (UPstream::master())
326 {
327 const bool oldParRun = UPstream::parRun(false);
328
329 filesToWatch.resize(watchIndices_.size());
330 forAll(watchIndices_, i)
331 {
332 filesToWatch[i] = fileHandler().getFile(watchIndices_[i]);
333 }
334
335 UPstream::parRun(oldParRun);
336 }
337
339 (
341 filesToWatch,
342 watchFiles_
343 );
344
345 // Add master files in same order
346 if (!UPstream::master())
347 {
348 const bool oldParRun = UPstream::parRun(false);
349
350 // Unregister current watched indices
351 forAllReverse(watchIndices_, i)
352 {
353 fileHandler().removeWatch(watchIndices_[i]);
354 }
355
356 // Insert the ones from master, in master order
357 watchIndices_.clear();
358 for (const auto& file : filesToWatch)
359 {
360 watchIndices_.push_back(fileHandler().addWatch(file));
361 }
362
363 UPstream::parRun(oldParRun);
364 }
365
366
367 // Files that were explicitly added via addWatch(const fileName&)
368 // (e.g. through #include)
369 for (const auto& file : watchFiles_)
370 {
371 watchIndices_.push_back(fileHandler().addWatch(file));
372 }
373
374 // Append the local file
375 watchIndices_.push_back(fileHandler().addWatch(f));
376 }
377 else
378 {
379 DynamicList<fileName> filesToWatch
380 (
381 watchIndices_.size()+watchFiles_.size()+1
382 );
383
384 // Get existing watched files from fileHandler
385 for (const label index : watchIndices_)
386 {
387 filesToWatch.push_back(fileHandler().getFile(index));
388 }
389
390 // The files explicitly added from addWatch(const fileName&)
391 // (e.g. through #include)
392 filesToWatch.push_back(std::move(watchFiles_));
393
394 // The local file
395 filesToWatch.push_back(f);
396
397 // Re-do all watches
398 fileHandler().addWatches(*this, filesToWatch);
399 }
400 }
401}
402
404bool Foam::regIOobject::upToDate(const regIOobject& a) const
405{
406 label da = a.eventNo()-eventNo_;
407
408 // In case of overflow *this.event() might be 2G but a.event() might
409 // have overflowed to 0.
410 // Detect this by detecting a massive difference (labelMax/2) between
411 // the two events.
412 //
413 // a *this return
414 // - ----- ------
415 // normal operation:
416 // 11 10 false
417 // 11 11 false
418 // 10 11 true
419 // overflow situation:
420 // 0 big false
421 // big 0 true
422
423 if (da > labelMax/2)
424 {
425 // *this.event overflowed but a.event not yet
426 return true;
427 }
428 else if (da < -labelMax/2)
429 {
430 // a.event overflowed but *this not yet
431 return false;
432 }
433 else if (da < 0)
434 {
435 // My event number higher than a
436 return true;
437 }
438
439 return false;
440}
441
444(
445 const regIOobject& a,
446 const regIOobject& b
447) const
448{
449 return upToDate(a) && upToDate(b);
450}
451
454(
455 const regIOobject& a,
456 const regIOobject& b,
457 const regIOobject& c
458) const
459{
460 return upToDate(a) && upToDate(b) && upToDate(c);
461}
462
465(
466 const regIOobject& a,
467 const regIOobject& b,
468 const regIOobject& c,
469 const regIOobject& d
470) const
471{
472 return upToDate(a) && upToDate(b) && upToDate(c) && upToDate(d);
473}
474
477{
478 eventNo_ = db().getEvent();
479}
480
482void Foam::regIOobject::rename(const word& newName)
483{
484 // Check out of objectRegistry
485 checkOut();
486
487 IOobject::rename(newName);
488
490 {
491 // Re-register object with objectRegistry
492 checkIn();
493 }
494}
495
500}
501
504{
505 // Note: Should be consistent with IOobject::typeHeaderOk(false)
506
507 bool ok = true;
508
509 fileName fName(filePath());
510
511 ok = Foam::fileHandler().readHeader(*this, fName, type());
512
513 if (!ok && IOobject::debug)
514 {
516 << "failed to read header of file " << objectPath()
517 << endl;
518 }
519
520 return ok;
521}
522
524void Foam::regIOobject::operator=(const IOobject& io)
525{
526 // Close any file
527 isPtr_.reset(nullptr);
528
529 // Check out of objectRegistry
530 checkOut();
531
533
535 {
536 // Re-register object with objectRegistry
537 checkIn();
538 }
539}
540
541
542// ************************************************************************* //
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition DynamicList.H:68
void push_back(const T &val)
Copy append an element to the end of this list.
readOption readOpt() const noexcept
Get the read option.
bool registerObject() const noexcept
Should objects created with this IOobject be registered?
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition IOobject.H:191
const Time & time() const noexcept
Return Time associated with the objectRegistry.
Definition IOobject.C:456
const objectRegistry & db() const noexcept
Return the local objectRegistry.
Definition IOobject.C:450
void operator=(const IOobject &io)
Copy assignment, copies all values (except the registry).
Definition IOobject.C:660
static bool fileModificationChecking_masterOnly() noexcept
Test fileModificationChecking for master-only.
Definition IOobjectI.H:23
const fileName & local() const noexcept
Read access to local path component.
Definition IOobjectI.H:301
fileName objectRelPath() const
The object path relative to the case.
Definition IOobject.C:581
fileName localFilePath(const word &typeName, const bool search=true) const
Redirect to fileHandler filePath, searching locally.
Definition IOobject.C:593
const fileName & instance() const noexcept
Read access to instance path component.
Definition IOobjectI.H:289
virtual void rename(const word &newName)
Rename the object.
Definition IOobject.H:697
autoPtr< IOobject > clone() const
Clone.
Definition IOobject.H:641
fileName objectPath() const
The complete path + object name.
Definition IOobjectI.H:313
void resize(const label len)
Adjust allocated size of list.
Definition ListI.H:153
static void broadcasts(const int communicator, Type &value, Args &&... values)
Broadcast multiple items to all communicator ranks. Does nothing in non-parallel.
static bool parRun(const bool on) noexcept
Set as parallel run on/off.
Definition UPstream.H:1669
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition UPstream.H:1714
static label worldComm
Communicator for all ranks. May differ from commGlobal() if local worlds are in use.
Definition UPstream.H:1069
static bool & parRun() noexcept
Test if this a parallel run.
Definition UPstream.H:1681
A class for handling file names.
Definition fileName.H:75
static word defaultRegion
Return the default region name.
Definition polyMesh.H:406
regIOobject is an abstract class derived from IOobject to handle automatic object registration with t...
Definition regIOobject.H:71
void setUpToDate()
Set as up-to-date.
virtual bool global() const
Is object global.
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
virtual fileName filePath() const
Return complete path + object name if the file exists.
bool upToDate(const regIOobject &) const
Return true if up-to-date with respect to given object.
static bool masterOnlyReading
To flag master-only reading of objects.
Definition regIOobject.H:86
bool headerOk()
Read and check header info. Does not check the headerClassName.
label eventNo() const noexcept
Event number at last update.
bool checkOut()
Remove object from registry, and remove all file watches.
void operator=(const regIOobject &)=delete
No copy assignment.
virtual ~regIOobject()
Destructor.
virtual void addWatch()
Add file watch on object (if registered and READ_IF_MODIFIED).
virtual void rename(const word &newName)
Rename.
bool checkIn()
Add object to registry, if not already registered.
A class for handling words, derived from Foam::string.
Definition word.H:66
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition className.H:142
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
bool local
Definition EEqn.H:20
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
const auto & io
auto & name
#define IOWarningInFunction(ios)
Report an IO warning using Foam::Warning.
#define WarningInFunction
Report a warning using Foam::Warning.
Namespace for handling debugging switches.
Definition debug.C:45
Namespace for OpenFOAM.
List< fileName > fileNameList
List of fileName.
refPtr< fileOperation > fileHandler(std::nullptr_t)
Delete current file handler - forwards to fileOperation::handler().
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition POSIX.C:801
constexpr label labelMax
Definition label.H:55
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
Definition FlatOutput.H:217
errorManip< error > abort(error &err)
Definition errorManip.H:139
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50
labelList f(nPoints)
volScalarField & b
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299
#define forAllReverse(list, i)
Reverse loop across all elements in list.
Definition stdFoam.H:315