masterUncollatedFileOperation.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) 2017-2018 OpenFOAM Foundation
9  Copyright (C) 2019-2022 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 
31 #include "Pstream.H"
32 #include "Time.H"
33 #include "instant.H"
34 #include "IFstream.H"
35 #include "IListStream.H"
36 #include "masterOFstream.H"
37 #include "decomposedBlockData.H"
38 #include "registerSwitch.H"
39 #include "dummyISstream.H"
40 #include "SubList.H"
41 #include "unthreadedInitialise.H"
42 #include "bitSet.H"
43 
44 /* * * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * */
45 
46 namespace Foam
47 {
48 namespace fileOperations
49 {
50  defineTypeNameAndDebug(masterUncollatedFileOperation, 0);
52  (
53  fileOperation,
54  masterUncollatedFileOperation,
55  word
56  );
57 
59  (
60  Foam::debug::floatOptimisationSwitch("maxMasterFileBufferSize", 1e9)
61  );
63  (
64  "maxMasterFileBufferSize",
65  float,
67  );
68 
69  // Mark as not needing threaded mpi
71  (
72  fileOperationInitialise,
73  masterUncollatedFileOperationInitialise,
74  word,
75  masterUncollated
76  );
77 }
78 }
79 
80 
81 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
82 
84 (
85  const label n
86 )
87 {
88  labelList mainRanks(fileOperation::ioRanks());
89 
90  if (mainRanks.empty())
91  {
92  return identity(n);
93  }
94  else
95  {
96  DynamicList<label> subRanks(n);
97 
98  if (!mainRanks.found(0))
99  {
101  << "Rank 0 (master) should be in the IO ranks. Currently "
102  << mainRanks << nl
103  << exit(FatalError);
104  }
105 
106  // The lowest numbered rank is the IO rank
107  const bitSet isIOrank(n, mainRanks);
108 
109  for (label proci = Pstream::myProcNo(); proci >= 0; --proci)
110  {
111  if (isIOrank[proci])
112  {
113  // Found my master. Collect all processors with same master
114  subRanks.append(proci);
115  for
116  (
117  label rank = proci+1;
118  rank < n && !isIOrank[rank];
119  ++rank
120  )
121  {
122  subRanks.append(rank);
123  }
124  break;
125  }
126  }
127  return subRanks;
128  }
129 }
130 
131 
134 (
135  const instantList& timeDirs,
136  const instant& t
137 )
138 {
139  // Note:
140  // - times will include constant (with value 0) as first element.
141  // For backwards compatibility make sure to find 0 in preference
142  // to constant.
143  // - list is sorted so could use binary search
144 
145  forAllReverse(timeDirs, i)
146  {
147  if (t.equal(timeDirs[i].value()))
148  {
149  return timeDirs[i].name();
150  }
151  }
153  return word::null;
154 }
155 
156 
159 (
160  const bool checkGlobal,
161  const bool isFile,
162  const IOobject& io,
163  const bool search,
164  pathType& searchType,
165  word& procsDir,
166  word& newInstancePath
167 ) const
168 {
169  procsDir = word::null;
170  newInstancePath = word::null;
171 
172  if (io.instance().isAbsolute())
173  {
174  fileName objPath = io.instance()/io.name();
175 
176  if (isFileOrDir(isFile, objPath))
177  {
178  searchType = fileOperation::ABSOLUTE;
179  return objPath;
180  }
181  else
182  {
183  searchType = fileOperation::NOTFOUND;
184  return fileName::null;
185  }
186  }
187  else
188  {
189  // 1. Check the writing fileName
190  fileName writePath(objectPath(io, io.headerClassName()));
191 
192  if (isFileOrDir(isFile, writePath))
193  {
194  searchType = fileOperation::WRITEOBJECT;
195  return writePath;
196  }
197 
198  // 2. Check processors/
199  if (io.time().processorCase())
200  {
201  refPtr<dirIndexList> pDirs(lookupProcessorsPath(io.objectPath()));
202 
203  for (const dirIndex& dirIdx : pDirs())
204  {
205  const fileName& pDir = dirIdx.first();
206  fileName objPath =
207  processorsPath(io, io.instance(), pDir)
208  /io.name();
209  if (objPath != writePath && isFileOrDir(isFile, objPath))
210  {
211  searchType = dirIdx.second().first();
212  procsDir = pDir;
213  return objPath;
214  }
215  }
216  }
217  {
218  // 3. Check local
219  fileName localPath = io.objectPath();
220 
221  if
222  (
223  localPath != writePath
224  && isFileOrDir(isFile, localPath)
225  )
226  {
227  searchType = fileOperation::OBJECT;
228  return localPath;
229  }
230  }
231 
232 
233 
234  // Any global checks
235  if
236  (
237  checkGlobal
238  && io.time().processorCase()
239  && (
240  io.instance() == io.time().system()
241  || io.instance() == io.time().constant()
242  )
243  )
244  {
245  fileName parentPath =
246  io.rootPath()/io.time().globalCaseName()
247  /io.instance()/io.db().dbDir()/io.local()/io.name();
248 
249  if (isFileOrDir(isFile, parentPath))
250  {
251  searchType = fileOperation::PARENTOBJECT;
252  return parentPath;
253  }
254  }
255 
256  // Check for approximately same time. E.g. if time = 1e-2 and
257  // directory is 0.01 (due to different time formats)
258  const auto pathFnd = times_.cfind(io.time().path());
259 
260  if (search && pathFnd.found())
261  {
262  newInstancePath = findInstancePath
263  (
264  *pathFnd(),
265  instant(io.instance())
266  );
267 
268  if (newInstancePath.size() && newInstancePath != io.instance())
269  {
270  // 1. Try processors equivalent
271  refPtr<dirIndexList> pDirs
272  (
273  lookupProcessorsPath(io.objectPath())
274  );
275 
276  for (const dirIndex& dirIdx : pDirs())
277  {
278  const fileName& pDir = dirIdx.first();
279 
280  fileName fName
281  (
282  processorsPath(io, newInstancePath, pDir)
283  /io.name()
284  );
285  if (isFileOrDir(isFile, fName))
286  {
287  switch (dirIdx.second().first())
288  {
290  {
291  searchType =
293  }
294  break;
296  {
297  searchType = fileOperation::PROCBASEINSTANCE;
298  }
299  break;
301  {
302  searchType = fileOperation::PROCINSTANCE;
303  }
304  break;
305  default:
306  break;
307  }
308  procsDir = pDir;
309  return fName;
310  }
311  }
312 
313 
314  // 2. Check local
315  fileName fName
316  (
317  io.rootPath()/io.caseName()
318  /newInstancePath/io.db().dbDir()/io.local()/io.name()
319  );
320  if (isFileOrDir(isFile, fName))
321  {
322  searchType = fileOperation::FINDINSTANCE;
323  return fName;
324  }
325  }
326  }
327 
328  searchType = fileOperation::NOTFOUND;
330  }
331 }
332 
333 
336 (
337  const IOobject& io,
338  const pathType& searchType,
339  const word& procDir,
340  const word& instancePath
341 ) const
342 {
343  // Replacement for IOobject::objectPath()
344 
345  switch (searchType)
346  {
348  {
349  return io.instance()/io.name();
350  }
351  break;
352 
354  {
355  return io.path()/io.name();
356  }
357  break;
358 
360  {
361  return objectPath(io, io.headerClassName());
362  }
363  break;
364 
366  {
367  // Uncollated type, e.g. processor1
368  const word procName
369  (
371  );
372  return
373  processorsPath
374  (
375  io,
376  io.instance(),
377  (
379  ? procName
380  : procDir
381  )
382  )
383  /io.name();
384  }
385  break;
386 
388  {
389  // Collated, e.g. processors4
390  return
391  processorsPath(io, io.instance(), procDir)
392  /io.name();
393  }
394  break;
395 
397  {
398  // Processors directory locally provided by the fileHandler itself
399  return
400  processorsPath(io, io.instance(), processorsDir(io))
401  /io.name();
402  }
403  break;
404 
406  {
407  return
408  io.rootPath()/io.time().globalCaseName()
409  /io.instance()/io.db().dbDir()/io.local()/io.name();
410  }
411  break;
412 
414  {
415  return
416  io.rootPath()/io.caseName()
417  /instancePath/io.db().dbDir()/io.local()/io.name();
418  }
419  break;
420 
422  {
423  // Uncollated type, e.g. processor1
424  const word procName
425  (
426  "processor"
428  );
429  return
430  processorsPath
431  (
432  io,
433  instancePath,
434  (
436  ? procName
437  : procDir
438  )
439  )
440  /io.name();
441  }
442  break;
443 
445  {
446  // Collated, e.g. processors4
447  return
448  processorsPath(io, instancePath, procDir)
449  /io.name();
450  }
451  break;
452 
454  {
455  // Processors directory locally provided by the fileHandler itself
456  return
457  processorsPath(io, instancePath, processorsDir(io))
458  /io.name();
459  }
460  break;
461 
463  {
464  return fileName::null;
465  }
466  break;
467 
468  default:
469  {
472  }
473  }
474 }
475 
476 
478 (
479  const fileName& filePath,
480  const labelUList& procs,
481  PstreamBuffers& pBufs
482 )
483 {
484  IFstream ifs(filePath, IOstreamOption::BINARY);
485 
486  if (!ifs.good())
487  {
488  FatalIOErrorInFunction(filePath)
489  << "Cannot open file " << filePath
490  << exit(FatalIOError);
491  }
492 
493  if (debug)
494  {
495  Pout<< "masterUncollatedFileOperation::readAndSend :"
496  << " compressed:" << bool(ifs.compression()) << " "
497  << filePath << endl;
498  }
499 
500  if (ifs.compression() == IOstreamOption::COMPRESSED)
501  {
502  // Could use Foam::fileSize, estimate uncompressed size (eg, 2x)
503  // and then string reserve followed by string assign...
504 
505  // Uncompress and read file contents into a character buffer
506  const std::string buf
507  (
508  std::istreambuf_iterator<char>(ifs.stdStream()),
509  std::istreambuf_iterator<char>()
510  );
511 
512  for (const label proci : procs)
513  {
514  UOPstream os(proci, pBufs);
515  os.write(buf.data(), buf.length());
516  }
517 
518  if (debug)
519  {
520  Pout<< "masterUncollatedFileOperation::readStream :"
521  << " From " << filePath << " sent " << buf.size()
522  << " bytes" << endl;
523  }
524  }
525  else
526  {
527  const off_t count(Foam::fileSize(filePath));
528 
529  // Read file contents into a character buffer
530  List<char> buf(static_cast<label>(count));
531  ifs.stdStream().read(buf.data(), count);
532 
533  for (const label proci : procs)
534  {
535  UOPstream os(proci, pBufs);
536  os.write(buf.cdata(), count);
537  }
538 
539  if (debug)
540  {
541  Pout<< "masterUncollatedFileOperation::readStream :"
542  << " From " << filePath << " sent " << buf.size()
543  << " bytes" << endl;
544  }
545  }
546 }
547 
548 
551 (
552  IOobject& io,
553  const label comm,
554  const bool uniform, // on comms master only
555  const fileNameList& filePaths, // on comms master only
556  const boolList& procValid // on comms master and sub-ranks
557 )
558 {
559  autoPtr<ISstream> isPtr;
560 
561  // const bool uniform = uniformFile(filePaths);
562 
563  PstreamBuffers pBufs(comm, UPstream::commsTypes::nonBlocking);
564 
565  if (Pstream::master(comm))
566  {
567  if (uniform)
568  {
569  if (procValid[0])
570  {
571  if (filePaths[0].empty())
572  {
573  FatalIOErrorInFunction(filePaths[0])
574  << "cannot find file " << io.objectPath()
575  << exit(FatalIOError);
576  }
577 
578  DynamicList<label> validProcs(Pstream::nProcs(comm));
579  for (const int proci : Pstream::allProcs(comm))
580  {
581  if (procValid[proci])
582  {
583  validProcs.append(proci);
584  }
585  }
586 
587  // Read on master and send to all processors
588  // (including master for simplicity)
589  if (debug)
590  {
591  Pout<< "masterUncollatedFileOperation::readStream :"
592  << " For uniform file " << filePaths[0]
593  << " sending to " << validProcs
594  << " in comm:" << comm << endl;
595  }
596  readAndSend(filePaths[0], validProcs, pBufs);
597  }
598  }
599  else
600  {
601  if (procValid[0])
602  {
603  if (filePaths[0].empty())
604  {
605  FatalIOErrorInFunction(filePaths[0])
606  << "cannot find file " << io.objectPath()
607  << exit(FatalIOError);
608  }
609 
610  // Open master
611  isPtr.reset(new IFstream(filePaths[0]));
612 
613  // Read header
614  if (!io.readHeader(*isPtr))
615  {
616  FatalIOErrorInFunction(*isPtr)
617  << "problem while reading header for object "
618  << io.name() << exit(FatalIOError);
619  }
620  }
621 
622  // Read sub-rank files
623  for (const int proci : Pstream::subProcs(comm))
624  {
625  if (debug)
626  {
627  Pout<< "masterUncollatedFileOperation::readStream :"
628  << " For processor " << proci
629  << " opening " << filePaths[proci] << endl;
630  }
631 
632  const fileName& fPath = filePaths[proci];
633 
634  if (procValid[proci] && !fPath.empty())
635  {
636  // Note: handle compression ourselves since size cannot
637  // be determined without actually uncompressing
638  readAndSend(fPath, labelList(one{}, proci), pBufs);
639  }
640  }
641  }
642  }
643 
644  labelList recvSizes;
645  pBufs.finishedSends(recvSizes);
646 
647  // isPtr will be valid on master and will be the unbuffered
648  // IFstream. Else the information is in the PstreamBuffers (and
649  // the special case of a uniform file)
650 
651  if (!isPtr)
652  {
653  if (procValid[Pstream::myProcNo(comm)])
654  {
655  // This processor needs to return something
656 
657  UIPstream is(Pstream::masterNo(), pBufs);
658 
659  List<char> buf(recvSizes[Pstream::masterNo()]);
660  if (!buf.empty())
661  {
662  is.read(buf.data(), buf.size());
663  }
664 
665  if (debug)
666  {
667  Pout<< "masterUncollatedFileOperation::readStream :"
668  << " Done reading " << buf.size() << " bytes" << endl;
669  }
670 
671  // A local character buffer copy of the Pstream contents.
672  // Construct with same parameters (ASCII, current version)
673  // as the IFstream so that it has the same characteristics.
674 
675  isPtr.reset(new IListStream(std::move(buf)));
676 
677  // With the proper file name
678  isPtr->name() = filePaths[Pstream::myProcNo(comm)];
679 
680  if (!io.readHeader(*isPtr))
681  {
682  FatalIOErrorInFunction(*isPtr)
683  << "problem while reading header for object "
684  << io.name() << exit(FatalIOError);
685  }
686  }
687  else
688  {
689  isPtr.reset(new dummyISstream());
690  }
691  }
692 
693 
694  return isPtr;
695 }
696 
697 
698 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
699 
700 void Foam::fileOperations::masterUncollatedFileOperation::init(bool verbose)
701 {
702  verbose = (verbose && Foam::infoDetailLevel > 0);
703 
704  if (verbose)
705  {
706  DetailInfo
707  << "I/O : " << typeName
708  << " (maxMasterFileBufferSize " << maxMasterFileBufferSize << ')'
709  << endl;
710  }
711 
713  {
714  if (verbose)
715  {
717  << "Resetting fileModificationChecking to timeStamp" << endl;
718  }
720  }
722  {
723  if (verbose)
724  {
726  << "Resetting fileModificationChecking to inotify"
727  << endl;
728  }
730  }
731 }
732 
733 
736 (
737  bool verbose
738 )
739 :
741  (
742  UPstream::allocateCommunicator
743  (
744  UPstream::worldComm,
745  subRanks(Pstream::nProcs())
746  )
747  ),
748  managedComm_(comm_)
749 {
750  init(verbose);
751 }
752 
753 
756 (
757  const label comm,
758  bool verbose
759 )
760 :
761  fileOperation(comm),
762  managedComm_(-1) // Externally managed
763 {
764  init(verbose);
765 }
766 
767 
768 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
769 
772 {
773  if (UPstream::isUserComm(managedComm_))
774  {
775  UPstream::freeCommunicator(managedComm_);
776  }
777 }
778 
779 
780 // * * * * * * * * * * * * * Filesystem Operations * * * * * * * * * * * * * //
781 
783 (
784  const fileName& dir,
785  mode_t mode
786 ) const
787 {
788  return masterOp<mode_t>
789  (
790  dir,
791  mkDirOp(mode),
793  comm_
794  );
795 }
796 
797 
799 (
800  const fileName& fName,
801  mode_t mode
802 ) const
803 {
804  return masterOp<mode_t>
805  (
806  fName,
807  chModOp(mode),
809  comm_
810  );
811 }
812 
813 
815 (
816  const fileName& fName,
817  const bool followLink
818 ) const
819 {
820  return masterOp<mode_t>
821  (
822  fName,
823  modeOp(followLink),
825  comm_
826  );
827 }
828 
829 
831 (
832  const fileName& fName,
833  const bool followLink
834 ) const
835 {
836  return fileName::Type
837  (
838  masterOp<label>
839  (
840  fName,
841  typeOp(followLink),
843  comm_
844  )
845  );
846 }
847 
848 
850 (
851  const fileName& fName,
852  const bool checkGzip,
853  const bool followLink
854 ) const
855 {
856  return masterOp<bool>
857  (
858  fName,
859  existsOp(checkGzip, followLink),
861  comm_
862  );
863 }
864 
865 
867 (
868  const fileName& fName,
869  const bool followLink
870 ) const
871 {
872  return masterOp<bool>
873  (
874  fName,
875  isDirOp(followLink),
877  comm_
878  );
879 }
880 
881 
883 (
884  const fileName& fName,
885  const bool checkGzip,
886  const bool followLink
887 ) const
888 {
889  return masterOp<bool>
890  (
891  fName,
892  isFileOp(checkGzip, followLink),
894  comm_
895  );
896 }
897 
898 
900 (
901  const fileName& fName,
902  const bool followLink
903 ) const
904 {
905  return masterOp<off_t>
906  (
907  fName,
908  fileSizeOp(followLink),
910  comm_
911  );
912 }
913 
914 
916 (
917  const fileName& fName,
918  const bool followLink
919 ) const
920 {
921  return masterOp<time_t>
922  (
923  fName,
924  lastModifiedOp(followLink),
926  comm_
927  );
928 }
929 
930 
932 (
933  const fileName& fName,
934  const bool followLink
935 ) const
936 {
937  return masterOp<double>
938  (
939  fName,
940  highResLastModifiedOp(followLink),
942  comm_
943  );
944 }
945 
946 
948 (
949  const fileName& fName,
950  const std::string& ext
951 ) const
952 {
953  return masterOp<bool>
954  (
955  fName,
956  mvBakOp(ext),
958  comm_
959  );
960 }
961 
962 
964 (
965  const fileName& fName
966 ) const
967 {
968  return masterOp<bool>
969  (
970  fName,
971  rmOp(),
973  comm_
974  );
975 }
976 
977 
979 (
980  const fileName& dir,
981  const bool silent,
982  const bool emptyOnly
983 ) const
984 {
985  return masterOp<bool>
986  (
987  dir,
988  rmDirOp(silent, emptyOnly),
990  comm_
991  );
992 }
993 
994 
996 (
997  const fileName& dir,
998  const fileName::Type type,
999  const bool filtergz,
1000  const bool followLink
1001 ) const
1002 {
1003  return masterOp<fileNameList>
1004  (
1005  dir,
1006  readDirOp(type, filtergz, followLink),
1008  comm_
1009  );
1010 }
1011 
1012 
1014 (
1015  const fileName& src,
1016  const fileName& dst,
1017  const bool followLink
1018 ) const
1019 {
1020  return masterOp<bool>
1021  (
1022  src,
1023  dst,
1024  cpOp(followLink),
1026  comm_
1027  );
1028 }
1029 
1030 
1032 (
1033  const fileName& src,
1034  const fileName& dst
1035 ) const
1036 {
1037  return masterOp<bool>
1038  (
1039  src,
1040  dst,
1041  lnOp(),
1043  comm_
1044  );
1045 }
1046 
1047 
1049 (
1050  const fileName& src,
1051  const fileName& dst,
1052  const bool followLink
1053 ) const
1054 {
1055  return masterOp<bool>
1056  (
1057  src,
1058  dst,
1059  mvOp(followLink),
1060  Pstream::msgType(),
1061  comm_
1062  );
1063 }
1064 
1065 
1066 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
1067 
1069 (
1070  const bool checkGlobal,
1071  const IOobject& io,
1072  const word& typeName,
1073  const bool search
1074 ) const
1075 {
1076  if (debug)
1077  {
1078  Pout<< "masterUncollatedFileOperation::filePath :"
1079  << " objectPath:" << io.objectPath()
1080  << " checkGlobal:" << checkGlobal << endl;
1081  }
1082 
1083  // Now that we have an IOobject path use it to detect & cache
1084  // processor directory naming
1085  (void)lookupProcessorsPath(io.objectPath());
1086 
1087  // Trigger caching of times
1088  (void)findTimes(io.time().path(), io.time().constant());
1089 
1090 
1091  // Determine master filePath and scatter
1092 
1093  fileName objPath;
1094  pathType searchType = NOTFOUND;
1095  word procsDir;
1096  word newInstancePath;
1097 
1098  if (Pstream::master(comm_))
1099  {
1100  const bool oldParRun(Pstream::parRun(false));
1101 
1102  // All masters search locally. Note that global objects might
1103  // fail (except on master). This gets handled later on (in PARENTOBJECT)
1104  objPath =
1105  filePathInfo
1106  (
1107  checkGlobal,
1108  true,
1109  io,
1110  search,
1111  searchType,
1112  procsDir,
1113  newInstancePath
1114  );
1115 
1116  Pstream::parRun(oldParRun);
1117 
1118  if (debug)
1119  {
1120  Pout<< "masterUncollatedFileOperation::filePath :"
1121  << " master objPath:" << objPath
1122  << " searchType:" << fileOperation::pathTypeNames_[searchType]
1123  << " procsDir:" << procsDir << " instance:" << newInstancePath
1124  << endl;
1125  }
1126  }
1127 
1128  // Scatter the information about where the master found the object
1129  // Note: use the worldComm to make sure all processors decide
1130  // the same type. Only procsDir is allowed to differ; searchType
1131  // and instance have to be same
1132  {
1133  int masterType(searchType);
1134  Pstream::broadcasts(UPstream::worldComm, masterType, newInstancePath);
1135  searchType = pathType(masterType);
1136  }
1137 
1138  if
1139  (
1140  checkGlobal
1141  || searchType == fileOperation::PARENTOBJECT
1142  || searchType == fileOperation::PROCBASEOBJECT
1143  || searchType == fileOperation::PROCBASEINSTANCE
1144  || io.local() == "uniform"
1145  )
1146  {
1147  // Distribute master path. This makes sure it is seen as uniform
1148  // and only gets read from the master.
1149  Pstream::broadcasts(UPstream::worldComm, objPath, procsDir);
1150  }
1151  else
1152  {
1153  Pstream::broadcast(procsDir, comm_);
1154 
1155  // Use the master type to determine if additional information is
1156  // needed to construct the local equivalent
1157  switch (searchType)
1158  {
1162  {
1163  // Already handled above
1164  }
1165  break;
1166 
1174  {
1175  // Construct equivalent local path
1176  objPath = localObjectPath
1177  (
1178  io,
1179  searchType,
1180  procsDir,
1181  newInstancePath
1182  );
1183  }
1184  break;
1185 
1186  case fileOperation::OBJECT:
1188  {
1189  // Retest all processors separately since some processors might
1190  // have the file and some not (e.g. lagrangian data)
1191 
1192  objPath = masterOp<fileName>
1193  (
1194  io.objectPath(),
1195  fileOrNullOp(true), // isFile=true
1196  Pstream::msgType(),
1197  comm_
1198  );
1199  }
1200  break;
1201  }
1202  }
1203 
1204  if (debug)
1205  {
1206  Pout<< "masterUncollatedFileOperation::filePath :"
1207  << " Returning from file searching:" << endl
1208  << " objectPath:" << io.objectPath() << endl
1209  << " filePath :" << objPath << endl << endl;
1210  }
1211  return objPath;
1212 }
1213 
1214 
1216 (
1217  const bool checkGlobal,
1218  const IOobject& io,
1219  const bool search
1220 ) const
1221 {
1222  if (debug)
1223  {
1224  Pout<< "masterUncollatedFileOperation::dirPath :"
1225  << " objectPath:" << io.objectPath()
1226  << " checkGlobal:" << checkGlobal << endl;
1227  }
1228 
1229  // Now that we have an IOobject path use it to detect & cache
1230  // processor directory naming
1231  (void)lookupProcessorsPath(io.objectPath());
1232 
1233  // Determine master dirPath and broadcast
1234 
1235  fileName objPath;
1236  pathType searchType = NOTFOUND;
1237  word procsDir;
1238  word newInstancePath;
1239 
1240  if (Pstream::master(comm_))
1241  {
1242  const bool oldParRun(Pstream::parRun(false));
1243 
1244  objPath = filePathInfo
1245  (
1246  checkGlobal,
1247  false,
1248  io,
1249  search,
1250  searchType,
1251  procsDir,
1252  newInstancePath
1253  );
1254 
1255  Pstream::parRun(oldParRun);
1256  }
1257 
1258  {
1259  int masterType(searchType);
1260  // Future?: comm_,
1261  Pstream::broadcasts(UPstream::worldComm, masterType, newInstancePath);
1262  searchType = pathType(masterType);
1263  }
1264 
1265  if
1266  (
1267  checkGlobal
1268  || searchType == fileOperation::PARENTOBJECT
1269  || searchType == fileOperation::PROCBASEOBJECT
1270  || searchType == fileOperation::PROCBASEINSTANCE
1271  || io.local() == "uniform"
1272  )
1273  {
1274  // Distribute master path. This makes sure it is seen as uniform
1275  // and only gets read from the master.
1276  Pstream::broadcasts(UPstream::worldComm, objPath, procsDir);
1277  }
1278  else
1279  {
1280  Pstream::broadcast(procsDir, comm_);
1281 
1282  // Use the master type to determine if additional information is
1283  // needed to construct the local equivalent
1284  switch (searchType)
1285  {
1289  {
1290  // Already handled above
1291  }
1292  break;
1293 
1301  {
1302  // Construct equivalent local path
1303  objPath = localObjectPath
1304  (
1305  io,
1306  searchType,
1307  procsDir,
1308  newInstancePath
1309  );
1310  }
1311  break;
1312 
1313  case fileOperation::OBJECT:
1315  {
1316  // Retest all processors separately since some processors might
1317  // have the file and some not (e.g. lagrangian data)
1318 
1319  objPath = masterOp<fileName>
1320  (
1321  io.objectPath(),
1322  fileOrNullOp(false), // isFile=false
1323  Pstream::msgType(),
1324  comm_
1325  );
1326  }
1327  break;
1328  }
1329  }
1330 
1331  if (debug)
1332  {
1333  Pout<< "masterUncollatedFileOperation::dirPath :"
1334  << " Returning from file searching:" << endl
1335  << " objectPath:" << io.objectPath() << endl
1336  << " filePath :" << objPath << endl << endl;
1337  }
1338  return objPath;
1339 }
1340 
1341 
1343 (
1344  const dirIndexList& pDirs,
1345  IOobject& io
1346 ) const
1347 {
1348  // Cut-down version of filePathInfo that does not look for
1349  // different instance or parent directory
1350 
1351  const bool isFile = !io.name().empty();
1352 
1353  // Generate output filename for object
1354  const fileName writePath(objectPath(io, word::null));
1355 
1356  // 1. Test writing name for either directory or a (valid) file
1357  if (isFileOrDir(isFile, writePath))
1358  {
1359  return true;
1360  }
1361 
1362  // 2. Check processors/
1363  if (io.time().processorCase())
1364  {
1365  for (const dirIndex& dirIdx : pDirs)
1366  {
1367  const fileName& pDir = dirIdx.first();
1368  fileName procPath =
1369  processorsPath(io, io.instance(), pDir)
1370  /io.name();
1371  if (procPath != writePath && isFileOrDir(isFile, procPath))
1372  {
1373  return true;
1374  }
1375  }
1376  }
1377 
1378  // 3. Check local
1379  fileName localPath = io.objectPath();
1380 
1381  if (localPath != writePath && isFileOrDir(isFile, localPath))
1382  {
1383  return true;
1384  }
1386  return false;
1387 }
1388 
1389 
1392 (
1393  const IOobject& startIO,
1394  const scalar startValue,
1395  const word& stopInstance
1396 ) const
1397 {
1398  if (debug)
1399  {
1400  Pout<< "masterUncollatedFileOperation::findInstance :"
1401  << " Starting searching for name:" << startIO.name()
1402  << " local:" << startIO.local()
1403  << " from instance:" << startIO.instance()
1404  << endl;
1405  }
1406 
1407  const Time& time = startIO.time();
1408  IOobject io(startIO);
1409 
1410  // Note: - if name is empty, just check the directory itself
1411  // - check both for isFile and headerOk since the latter does a
1412  // filePath so searches for the file.
1413  // - check for an object with local file scope (so no looking up in
1414  // parent directory in case of parallel)
1415 
1416 
1417  refPtr<dirIndexList> pDirs(lookupProcessorsPath(io.objectPath()));
1418 
1419  word foundInstance;
1420 
1421  // if (Pstream::master(comm_))
1423  {
1424  const bool oldParRun(Pstream::parRun(false));
1425  if (exists(pDirs, io))
1426  {
1427  foundInstance = io.instance();
1428  }
1429  Pstream::parRun(oldParRun);
1430  }
1431 
1432  // Do parallel early exit to avoid calling time.times()
1433  // Pstream::broadcast(foundInstance, comm_);
1434  Pstream::broadcast(foundInstance, UPstream::worldComm);
1435  if (!foundInstance.empty())
1436  {
1437  io.instance() = foundInstance;
1438  if (debug)
1439  {
1440  Pout<< "masterUncollatedFileOperation::findInstance :"
1441  << " for name:" << io.name() << " local:" << io.local()
1442  << " found starting instance:" << io.instance() << endl;
1443  }
1444  return io;
1445  }
1446 
1447 
1448  // Handling failures afterwards
1449  const bool exitIfMissing = startIO.isReadRequired();
1450 
1451  enum failureCodes { FAILED_STOPINST = 1, FAILED_CONSTINST = 2 };
1452  int failed(0);
1453 
1454  instantList ts = time.times();
1455 
1456  // if (Pstream::master(comm_))
1458  {
1459  const bool oldParRun(Pstream::parRun(false));
1460 
1461  label instIndex = ts.size()-1;
1462 
1463  // Backward search for first time that is <= startValue
1464  for (; instIndex >= 0; --instIndex)
1465  {
1466  if (ts[instIndex].value() <= startValue)
1467  {
1468  break;
1469  }
1470  }
1471 
1472  // Continue (forward) searching from here
1473  for (; instIndex >= 0; --instIndex)
1474  {
1475  // Shortcut: if actual directory is the timeName we've
1476  // already tested it
1477  if (ts[instIndex].name() == time.timeName())
1478  {
1479  continue;
1480  }
1481 
1482  io.instance() = ts[instIndex].name();
1483  if (exists(pDirs, io))
1484  {
1485  foundInstance = io.instance();
1486  if (debug)
1487  {
1488  Pout<< "masterUncollatedFileOperation::findInstance :"
1489  << " for name:" << io.name() << " local:" << io.local()
1490  << " found at:" << io.instance()
1491  << endl;
1492  }
1493  break;
1494  }
1495 
1496  // Check if hit minimum instance
1497  if (io.instance() == stopInstance)
1498  {
1499  if (debug)
1500  {
1501  Pout<< "masterUncollatedFileOperation::findInstance :"
1502  << " name:" << io.name()
1503  << " local:" << io.local()
1504  << " at stop-instance:" << io.instance() << endl;
1505  }
1506 
1507  if (exitIfMissing)
1508  {
1509  failed = failureCodes::FAILED_STOPINST;
1510  }
1511  else
1512  {
1513  foundInstance = io.instance();
1514  }
1515  break;
1516  }
1517  }
1518 
1519 
1520  // times() usually already includes the constant() so would
1521  // have been checked above. However, re-test under these conditions:
1522  // - times() is empty. Sometimes this can happen (e.g. decomposePar
1523  // with collated)
1524  // - times()[0] is not constant
1525  // - Times is empty.
1526  // Sometimes this can happen (eg, decomposePar with collated)
1527  // - Times[0] is not constant
1528  // - The startValue is negative (eg, kivaTest).
1529  // This plays havoc with the reverse search, causing it to miss
1530  // 'constant'
1531 
1532  if
1533  (
1534  !failed && foundInstance.empty()
1535  && (ts.empty() || ts[0].name() != time.constant() || startValue < 0)
1536  )
1537  {
1538  // Note. This needs to be a hard-coded "constant" (not constant
1539  // function of Time), because the latter points to
1540  // the case constant directory in parallel cases.
1541  // However, parRun is disabled so they are actually the same.
1542 
1543  io.instance() = time.constant();
1544 
1545  if (exists(pDirs, io))
1546  {
1547  if (debug)
1548  {
1549  Pout<< "masterUncollatedFileOperation::findInstance :"
1550  << " name:" << io.name()
1551  << " local:" << io.local()
1552  << " at:" << io.instance() << endl;
1553  }
1554  foundInstance = io.instance();
1555  }
1556  }
1557 
1558  if (!failed && foundInstance.empty())
1559  {
1560  if (exitIfMissing)
1561  {
1562  failed = failureCodes::FAILED_CONSTINST;
1563  }
1564  else
1565  {
1566  foundInstance = time.constant();
1567  }
1568  }
1569 
1570  UPstream::parRun(oldParRun); // Restore parallel state
1571  }
1572 
1573  // Pstream::broadcast(foundInstance, comm_);
1574  Pstream::broadcast(foundInstance, UPstream::worldComm);
1575  io.instance() = foundInstance;
1576 
1577 
1578  // Handle failures
1579  // ~~~~~~~~~~~~~~~
1580  if (failed)
1581  {
1582  FatalErrorInFunction << "Cannot find";
1583 
1584  if (!io.name().empty())
1585  {
1586  FatalError
1587  << " file \"" << io.name() << "\" in";
1588  }
1589 
1590  FatalError
1591  << " directory "
1592  << io.local() << " in times "
1593  << startIO.instance() << " down to ";
1594 
1595  if (failed == failureCodes::FAILED_STOPINST)
1596  {
1597  FatalError << stopInstance;
1598  }
1599  else
1600  {
1601  FatalError << "constant";
1602  }
1604  }
1605 
1606  if (debug)
1607  {
1608  Pout<< "masterUncollatedFileOperation::findInstance :"
1609  << " name:" << io.name() << " local:" << io.local()
1610  << " returning instance:" << io.instance() << endl;
1611  }
1612  return io;
1613 }
1614 
1615 
1618 (
1619  const objectRegistry& db,
1620  const fileName& instance,
1621  const fileName& local,
1622  word& newInstance
1623 ) const
1624 {
1625  if (debug)
1626  {
1627  Pout<< "masterUncollatedFileOperation::readObjects :"
1628  << " db:" << db.objectPath()
1629  << " local:" << local << " instance:" << instance << endl;
1630  }
1631 
1632  fileNameList objectNames;
1633  newInstance = word::null;
1634 
1635  // Note: readObjects uses WORLD to make sure order of objects is the
1636  // same everywhere
1637 
1638  if (Pstream::master()) // comm_))
1639  {
1640  // Avoid fileOperation::readObjects from triggering parallel ops
1641  // (through call to filePath which triggers parallel )
1642  const bool oldParRun = UPstream::parRun(false);
1643 
1644  //- Use non-time searching version
1645  objectNames = fileOperation::readObjects
1646  (
1647  db,
1648  instance,
1649  local,
1650  newInstance
1651  );
1652 
1653  if (newInstance.empty())
1654  {
1655  // Find similar time
1656 
1657  // Copy of Time::findInstancePath. We want to avoid the
1658  // parallel call to findTimes. Alternative is to have
1659  // version of findInstancePath that takes instantList ...
1660  const instantList timeDirs
1661  (
1663  (
1664  db.time().path(),
1665  db.time().constant()
1666  )
1667  );
1668 
1669  const instant t(instance);
1670  forAllReverse(timeDirs, i)
1671  {
1672  if (t.equal(timeDirs[i].value()))
1673  {
1674  objectNames = fileOperation::readObjects
1675  (
1676  db,
1677  timeDirs[i].name(), // newly found time
1678  local,
1679  newInstance
1680  );
1681  break;
1682  }
1683  }
1684  }
1685 
1686  UPstream::parRun(oldParRun); // Restore parallel state
1687  }
1688 
1689  // Future? comm_
1690  Pstream::broadcasts(UPstream::worldComm, newInstance, objectNames);
1691 
1692  if (debug)
1693  {
1694  Pout<< "masterUncollatedFileOperation::readObjects :"
1695  << " newInstance:" << newInstance
1696  << " objectNames:" << objectNames << endl;
1697  }
1698 
1699  return objectNames;
1700 }
1701 
1702 
1704 (
1705  IOobject& io,
1706  const fileName& fName,
1707  const word& typeName
1708 ) const
1709 {
1710  bool ok = false;
1711 
1712  if (debug)
1713  {
1714  Pout<< "masterUncollatedFileOperation::readHeader :" << endl
1715  << " objectPath:" << io.objectPath() << endl
1716  << " filePath :" << fName << endl;
1717  }
1718 
1719  // Get filePaths on world master
1721  filePaths[Pstream::myProcNo(Pstream::worldComm)] = fName;
1723  bool uniform = uniformFile(filePaths);
1725 
1726  if (uniform)
1727  {
1729  {
1730  if (!fName.empty())
1731  {
1732  IFstream is(fName);
1733 
1734  if (is.good())
1735  {
1736  // Regular header or from decomposed data
1738  }
1739  }
1740  }
1741 
1743  (
1745  ok,
1746  io.headerClassName(),
1747  io.note()
1748  );
1749  }
1750  else
1751  {
1753  {
1754  // Re-gather file paths on local master
1755  filePaths.resize(Pstream::nProcs(comm_));
1756  filePaths[Pstream::myProcNo(comm_)] = fName;
1757  Pstream::gatherList(filePaths, Pstream::msgType(), comm_);
1758  }
1759 
1760  // Intermediate storage arrays (master only)
1761  boolList result;
1762  wordList headerClassName;
1763  stringList note;
1764 
1765  if (Pstream::master(comm_))
1766  {
1767  const label np = Pstream::nProcs(comm_);
1768 
1769  result.resize(np, false);
1770  headerClassName.resize(np);
1771  note.resize(np);
1772 
1773  forAll(filePaths, proci)
1774  {
1775  if (!filePaths[proci].empty())
1776  {
1777  if (proci > 0 && filePaths[proci] == filePaths[proci-1])
1778  {
1779  result[proci] = result[proci-1];
1780  headerClassName[proci] = headerClassName[proci-1];
1781  note[proci] = note[proci-1];
1782  }
1783  else
1784  {
1785  IFstream is(filePaths[proci]);
1786 
1787  if (is.good())
1788  {
1789  result[proci] =
1791  headerClassName[proci] = io.headerClassName();
1792  note[proci] = io.note();
1793  }
1794  }
1795  }
1796  }
1797  }
1798 
1799  // Is a more efficient scatter possible?
1800  PstreamBuffers pBufs(comm_, UPstream::commsTypes::nonBlocking);
1801 
1802  if (Pstream::master(comm_))
1803  {
1804  ok = result[0];
1805  io.headerClassName() = headerClassName[0];
1806  io.note() = note[0];
1807 
1808  // Scatter to each proc
1809  for (const int proci : pBufs.subProcs())
1810  {
1811  UOPstream os(proci, pBufs);
1812  os << result[proci] << headerClassName[proci] << note[proci];
1813  }
1814  }
1815 
1816  pBufs.finishedScatters();
1817 
1818  if (!Pstream::master(comm_))
1819  {
1820  UIPstream is(Pstream::masterNo(), pBufs);
1821  is >> ok >> io.headerClassName() >> io.note();
1822  }
1823  }
1824 
1825  if (debug)
1826  {
1827  Pout<< "masterUncollatedFileOperation::readHeader :" << " ok:" << ok
1828  << " class:" << io.headerClassName() << endl;
1829  }
1830  return ok;
1832 
1833 
1836 (
1837  regIOobject& io,
1838  const fileName& fName,
1839  const word& typeName,
1840  const bool valid
1841 ) const
1842 {
1843  if (debug)
1844  {
1845  Pout<< "masterUncollatedFileOperation::readStream :"
1846  << " object : " << io.name()
1847  << " global : " << io.global()
1848  << " fName : " << fName << " valid:" << valid << endl;
1849  }
1850 
1851 
1852  autoPtr<ISstream> isPtr;
1853  bool isCollated = false;
1854  IOobject headerIO(io);
1855 
1856  // Detect collated format. This could be done on the local communicator
1857  // but we do it on the master node only for now.
1858  if (UPstream::master()) // comm_))
1859  {
1860  if (!fName.empty())
1861  {
1862  // This can happen in lagrangian field reading some processors
1863  // have no file to read from. This will only happen when using
1864  // normal writing since then the fName for the valid processors is
1865  // processorDDD/<instance>/.. . In case of collocated writing
1866  // the fName is already rewritten to processorsNN/.
1867 
1868  isPtr.reset(new IFstream(fName));
1869 
1870  if (isPtr->good())
1871  {
1872  // Read header data (on copy)
1873  headerIO.readHeader(*isPtr);
1874 
1875  isCollated = decomposedBlockData::isCollatedType(headerIO);
1876 
1877  if (!isCollated && !Pstream::parRun())
1878  {
1879  // Short circuit: non-collated format. No parallel bits.
1880  // Copy header and return.
1881  if (debug)
1882  {
1883  Pout<< "masterUncollatedFileOperation::readStream :"
1884  << " For object : " << io.name()
1885  << " doing straight IFstream input from "
1886  << fName << endl;
1887  }
1888  io = headerIO;
1889  return isPtr;
1890  }
1891  }
1892 
1893  if (!isCollated)
1894  {
1895  // Close file. Reopened below.
1896  isPtr.clear();
1897  }
1898  }
1899  }
1900 
1901  Pstream::broadcast(isCollated); //, comm_);
1902 
1903  if (isCollated)
1904  {
1905  if (debug)
1906  {
1907  Pout<< "masterUncollatedFileOperation::readStream :"
1908  << " For object : " << io.name()
1909  << " starting collating input from " << fName << endl;
1910  }
1911 
1912 
1913  // Analyse the file path (on (co)master) to see the processors type
1914  // Note: this should really be part of filePath() which should return
1915  // both file and index in file.
1916 
1917  fileName path, procDir, local;
1918  procRangeType group;
1919  label nProcs;
1920  splitProcessorPath(fName, path, procDir, local, group, nProcs);
1921 
1922 
1923  if (!Pstream::parRun())
1924  {
1925  // Analyse the objectpath to find out the processor we're trying
1926  // to access
1927  label proci = detectProcessorPath(io.objectPath());
1928 
1929  if (proci == -1)
1930  {
1931  FatalIOErrorInFunction(*isPtr)
1932  << "Could not detect processor number"
1933  << " from objectPath:" << io.objectPath()
1934  << exit(FatalIOError);
1935  }
1936 
1937  // The local rank (offset)
1938  if (!group.empty())
1939  {
1940  proci = proci - group.start();
1941  }
1942 
1943  if (debug)
1944  {
1945  Pout<< "masterUncollatedFileOperation::readStream :"
1946  << " For object : " << io.name()
1947  << " starting input from block " << proci
1948  << " of " << isPtr->name() << endl;
1949  }
1950 
1951  return decomposedBlockData::readBlock(proci, *isPtr, io);
1952  }
1953  else
1954  {
1955  // Are we reading from single-master file ('processors256') or
1956  // from multi-master files ('processors256_0-9')
1957  label readComm = -1;
1958  if (!group.empty())
1959  {
1960  readComm = comm_;
1961  if (UPstream::master(comm_) && !isPtr && !fName.empty())
1962  {
1963  // In multi-master mode also open the file on the other
1964  // masters
1965  isPtr.reset(new IFstream(fName));
1966 
1967  if (isPtr->good())
1968  {
1969  // Read header data (on copy)
1970  IOobject headerIO(io);
1971  headerIO.readHeader(*isPtr);
1972  }
1973  }
1974  }
1975  else
1976  {
1977  // Single master so read on world
1978  readComm = UPstream::worldComm;
1979  }
1980 
1981  // Get size of file to determine communications type
1982  bool bigSize = false;
1983 
1984  if (Pstream::master()) //, comm_))
1985  {
1986  // TBD: handle multiple masters?
1987  bigSize =
1988  (
1989  off_t(Foam::fileSize(fName))
1990  > off_t(maxMasterFileBufferSize)
1991  );
1992  }
1993  // Reduce (not broadcast)
1994  // - if we have multiple master files (FUTURE)
1995  Pstream::reduceOr(bigSize); //, comm_);
1996 
1997  const UPstream::commsTypes myCommsType
1998  (
1999  bigSize
2002  );
2003 
2004  // Read my data
2006  (
2007  readComm,
2008  fName,
2009  isPtr,
2010  io,
2011  myCommsType
2012  );
2013  }
2014  }
2015  else
2016  {
2017  if (debug)
2018  {
2019  Pout<< "masterUncollatedFileOperation::readStream :"
2020  << " For object : " << io.name()
2021  << " starting separated input from " << fName << endl;
2022  }
2023 
2024  if (io.global())
2025  {
2026  // Use worldComm. Note: should not really need to gather filePaths
2027  // since we enforce sending from master anyway ...
2028  fileNameList filePaths(Pstream::nProcs());
2029  filePaths[Pstream::myProcNo()] = fName;
2030  Pstream::gatherList(filePaths);
2031 
2032  boolList procValid(UPstream::listGatherValues<bool>(valid));
2033  // NB: local proc validity information required on sub-ranks too!
2034  procValid.resize(Pstream::nProcs());
2035  procValid[Pstream::myProcNo()] = valid;
2036 
2037  return read(io, Pstream::worldComm, true, filePaths, procValid);
2038  }
2039  else
2040  {
2041  // Use local communicator
2042  fileNameList filePaths(Pstream::nProcs(comm_));
2043  filePaths[Pstream::myProcNo(comm_)] = fName;
2044  Pstream::gatherList(filePaths, Pstream::msgType(), comm_);
2045 
2046  boolList procValid(UPstream::listGatherValues<bool>(valid, comm_));
2047  // NB: local proc validity information required on sub-ranks too!
2048  procValid.resize(Pstream::nProcs(comm_));
2049  procValid[Pstream::myProcNo(comm_)] = valid;
2050 
2051  // Uniform in local comm
2052  const bool uniform = uniformFile(filePaths);
2053 
2054  return read(io, comm_, uniform, filePaths, procValid);
2055  }
2056  }
2057 }
2058 
2059 
2061 (
2062  regIOobject& io,
2063  const bool masterOnly,
2065  const word& typeName
2066 ) const
2067 {
2068  bool ok = true;
2069 
2070  if (io.globalObject())
2071  {
2072  if (debug)
2073  {
2074  Pout<< "masterUncollatedFileOperation::read :"
2075  << " Reading global object " << io.name() << endl;
2076  }
2077 
2078  bool ok = false;
2080  {
2081  // Do master-only reading always.
2082  const bool oldParRun = UPstream::parRun(false);
2083 
2084  ok = io.readData(io.readStream(typeName));
2085  io.close();
2086 
2087  UPstream::parRun(oldParRun); // Restore parallel state
2088  }
2089 
2090  // Broadcast regIOobjects content
2091  if (Pstream::parRun())
2092  {
2094  (
2096  ok,
2097  io.headerClassName(),
2098  io.note()
2099  );
2100 
2102  {
2103  OPBstream toAll
2104  (
2107  format
2108  );
2109  bool okWrite = io.writeData(toAll);
2110  ok = ok && okWrite;
2111  }
2112  else
2113  {
2114  IPBstream fromMaster
2115  (
2118  format
2119  );
2120  ok = io.readData(fromMaster);
2121  }
2122  }
2123  }
2124  else
2125  {
2126  if (debug)
2127  {
2128  Pout<< "masterUncollatedFileOperation::read :"
2129  << " Reading local object " << io.name() << endl;
2130  }
2131 
2132  ok = io.readData(io.readStream(typeName));
2133  io.close();
2134  }
2135 
2136  return ok;
2137 }
2138 
2139 
2141 (
2142  const regIOobject& io,
2143  IOstreamOption streamOpt,
2144  const bool valid
2145 ) const
2146 {
2147  fileName pathName(io.objectPath());
2148 
2149  if (debug)
2150  {
2151  Pout<< "masterUncollatedFileOperation::writeObject :"
2152  << " io:" << pathName << " valid:" << valid << endl;
2153  }
2154 
2155  // Make sure to pick up any new times
2156  setTime(io.time());
2157 
2158  // Update meta-data for current state
2159  const_cast<regIOobject&>(io).updateMetaData();
2160 
2161  autoPtr<OSstream> osPtr(NewOFstream(pathName, streamOpt, valid));
2162  OSstream& os = *osPtr;
2163 
2164  // If any of these fail, return (leave error handling to Ostream class)
2165 
2166  const bool ok =
2167  (
2168  os.good()
2169  && io.writeHeader(os)
2170  && io.writeData(os)
2171  );
2172 
2173  if (ok)
2174  {
2176  }
2177 
2178  return ok;
2179 }
2180 
2181 
2183 (
2184  const fileName& directory,
2185  const word& constantName
2186 ) const
2187 {
2188  const auto iter = times_.cfind(directory);
2189  if (iter.found())
2190  {
2191  if (debug)
2192  {
2193  Pout<< "masterUncollatedFileOperation::findTimes :"
2194  << " Found " << iter.val()->size() << " cached times" << endl;
2195  }
2196  return *(iter.val());
2197  }
2198  else
2199  {
2200  instantList times;
2201  if (Pstream::master()) // comm_))
2202  {
2203  // Do master-only reading always.
2204  const bool oldParRun = UPstream::parRun(false);
2205 
2206  times = fileOperation::findTimes(directory, constantName);
2207 
2208  UPstream::parRun(oldParRun); // Restore parallel state
2209  }
2210  Pstream::broadcast(times); //, comm_);
2211 
2212  if (debug)
2213  {
2214  Pout<< "masterUncollatedFileOperation::findTimes :"
2215  << " Caching times:" << times << nl
2216  << " for directory:" << directory << endl;
2217  }
2218 
2219  // Note: do we also cache if no times have been found since it might
2220  // indicate a directory that is being filled later on ...
2221 
2222  auto* tPtr = new DynamicList<instant>(std::move(times));
2223 
2224  times_.set(directory, tPtr);
2225 
2226  return *tPtr;
2227  }
2228 }
2229 
2230 
2232 (
2233  const Time& tm
2234 ) const
2235 {
2236  if (tm.subCycling())
2237  {
2238  return;
2239  }
2240 
2241  // Mutable access to instant list for modification and sorting
2242  // - cannot use auto type deduction here
2243 
2244  HashPtrTable<DynamicList<instant>>::iterator iter = times_.find(tm.path());
2245 
2246  if (iter.found())
2247  {
2248  DynamicList<instant>& times = *(iter.val());
2249 
2250  const instant timeNow(tm.value(), tm.timeName());
2251 
2252  // The start index for checking and sorting (excluding "constant")
2253  const label startIdx =
2254  (
2255  (times.empty() || times[0].name() != tm.constant())
2256  ? 0
2257  : 1
2258  );
2259 
2260  // This routine always results in a sorted list of times, so first
2261  // check if the new time is greater than the latest existing time.
2262  // Can then simply append without extra searching or sorting
2263 
2264  if (times.size() <= startIdx || times.last() < timeNow)
2265  {
2266  times.append(timeNow);
2267  }
2268  else if
2269  (
2271  (
2272  SubList<instant>(times, times.size()-startIdx, startIdx),
2273  timeNow
2274  ) < 0
2275  )
2276  {
2277  if (debug)
2278  {
2279  Pout<< "masterUncollatedFileOperation::setTime :"
2280  << " Caching time " << tm.timeName()
2281  << " for case:" << tm.path() << endl;
2282  }
2283 
2284  times.append(timeNow);
2285 
2286  SubList<instant> realTimes
2287  (
2288  times, times.size()-startIdx, startIdx
2289  );
2290  Foam::stableSort(realTimes);
2291  }
2292  }
2293 
2296 
2297 
2300 (
2301  const fileName& filePath
2302 ) const
2303 {
2304  autoPtr<ISstream> isPtr;
2305 
2306  if (Pstream::parRun())
2307  {
2308  // Insert logic of filePath. We assume that if a file is absolute
2309  // on the master it is absolute also on the sub-ranks etc.
2310 
2312  filePaths[Pstream::myProcNo(Pstream::worldComm)] = filePath;
2314 
2315  PstreamBuffers pBufs
2316  (
2318  Pstream::msgType(),
2320  );
2321 
2323  {
2324  const bool uniform = uniformFile(filePaths);
2325 
2326  if (uniform)
2327  {
2328  if (debug)
2329  {
2330  Pout<< "masterUncollatedFileOperation::NewIFstream :"
2331  << " Opening global file " << filePath << endl;
2332  }
2333 
2334  readAndSend
2335  (
2336  filePath,
2338  pBufs
2339  );
2340  }
2341  else
2342  {
2343  for (const int proci : Pstream::subProcs(Pstream::worldComm))
2344  {
2345  readAndSend
2346  (
2347  filePaths[proci],
2348  labelList(one{}, proci),
2349  pBufs
2350  );
2351  }
2352  }
2353  }
2354 
2355 
2356  labelList recvSizes;
2357  pBufs.finishedSends(recvSizes);
2358 
2360  {
2361  // Read myself
2362  isPtr.reset(new IFstream(filePaths[Pstream::masterNo()]));
2363  }
2364  else
2365  {
2366  if (debug)
2367  {
2368  Pout<< "masterUncollatedFileOperation::NewIFstream :"
2369  << " Reading " << filePath
2370  << " from processor " << Pstream::masterNo() << endl;
2371  }
2372 
2373  UIPstream is(Pstream::masterNo(), pBufs);
2374 
2375  List<char> buf(recvSizes[Pstream::masterNo()]);
2376  is.read(buf.data(), buf.size());
2377 
2378  if (debug)
2379  {
2380  Pout<< "masterUncollatedFileOperation::NewIFstream :"
2381  << " Done reading " << buf.size() << " bytes" << endl;
2382  }
2383 
2384  // A local character buffer copy of the Pstream contents.
2385  // Construct with same parameters (ASCII, current version)
2386  // as the IFstream so that it has the same characteristics.
2387 
2388  isPtr.reset(new IListStream(std::move(buf)));
2389 
2390  // With the proper file name
2391  isPtr->name() = filePath;
2392  }
2393  }
2394  else
2395  {
2396  // Read myself
2397  isPtr.reset(new IFstream(filePath));
2398  }
2399 
2400  return isPtr;
2402 
2403 
2406 (
2407  const fileName& pathName,
2408  IOstreamOption streamOpt,
2409  const bool valid
2410 ) const
2411 {
2412  return autoPtr<OSstream>
2413  (
2414  new masterOFstream
2415  (
2416  pathName,
2417  streamOpt,
2419  valid
2420  )
2421  );
2423 
2424 
2427 (
2429  const fileName& pathName,
2430  IOstreamOption streamOpt,
2431  const bool valid
2432 ) const
2433 {
2434  return autoPtr<OSstream>
2435  (
2436  new masterOFstream
2437  (
2438  atomic,
2439  pathName,
2440  streamOpt,
2442  valid
2443  )
2444  );
2445 }
2446 
2447 
2449 {
2451  times_.clear();
2452 }
2453 
2454 
2456 (
2457  const fileName& fName
2458 ) const
2459 {
2460  label watchFd = -1;
2461  if (Pstream::master()) // comm_))
2462  {
2463  watchFd = monitor().addWatch(fName);
2464  }
2465  Pstream::broadcast(watchFd); //, comm_);
2466  return watchFd;
2467 }
2468 
2469 
2471 (
2472  const label watchIndex
2473 ) const
2474 {
2475  bool ok = false;
2476  if (Pstream::master()) // comm_))
2477  {
2478  ok = monitor().removeWatch(watchIndex);
2479  }
2480  Pstream::broadcast(ok); //, comm_);
2481  return ok;
2482 }
2483 
2484 
2486 (
2487  const labelList& watchIndices,
2488  const fileName& fName
2489 ) const
2490 {
2491  label index = -1;
2492 
2493  if (Pstream::master()) // comm_))
2494  {
2495  forAll(watchIndices, i)
2496  {
2497  if (monitor().getFile(watchIndices[i]) == fName)
2498  {
2499  index = i;
2500  break;
2501  }
2502  }
2503  }
2504  Pstream::broadcast(index); //, comm_);
2505  return index;
2506 }
2507 
2508 
2510 (
2511  regIOobject& rio,
2512  const fileNameList& files
2513 ) const
2514 {
2515  const labelList& watchIndices = rio.watchIndices();
2516 
2517  DynamicList<label> newWatchIndices;
2518  labelHashSet removedWatches(watchIndices);
2519 
2520  for (const fileName& f : files)
2521  {
2522  const label index = findWatch(watchIndices, f);
2523 
2524  if (index == -1)
2525  {
2526  newWatchIndices.append(addWatch(f));
2527  }
2528  else
2529  {
2530  // Existing watch
2531  newWatchIndices.append(watchIndices[index]);
2532  removedWatches.erase(index);
2533  }
2534  }
2535 
2536  // Remove any unused watches
2537  for (const label index : removedWatches)
2538  {
2539  removeWatch(watchIndices[index]);
2540  }
2541 
2542  rio.watchIndices() = newWatchIndices;
2543 }
2544 
2545 
2547 (
2548  const label watchIndex
2549 ) const
2550 {
2551  fileName fName;
2552  if (Pstream::master()) // comm_))
2553  {
2554  fName = monitor().getFile(watchIndex);
2555  }
2556  Pstream::broadcast(fName); //, comm_);
2557  return fName;
2558 }
2559 
2560 
2562 (
2563  const bool masterOnly,
2564  const bool syncPar
2565 ) const
2566 {
2567  if (Pstream::master()) // comm_))
2568  {
2569  monitor().updateStates(true, false);
2570  }
2572 
2573 
2576 (
2577  const label watchFd
2578 ) const
2579 {
2580  unsigned int state = fileMonitor::UNMODIFIED;
2581  if (Pstream::master()) // comm_))
2582  {
2583  state = monitor().getState(watchFd);
2584  }
2585  Pstream::broadcast(state); //, comm_);
2586  return fileMonitor::fileState(state);
2587 }
2588 
2589 
2591 (
2592  const label watchFd
2593 ) const
2594 {
2595  if (Pstream::master()) // comm_))
2596  {
2597  monitor().setUnmodified(watchFd);
2598  }
2599 }
2600 
2601 
2602 // ************************************************************************* //
virtual mode_t mode(const fileName &, const bool followLink=true) const
Return the file mode.
static word findInstancePath(const instantList &timeDirs, const instant &t)
Equivalent of Time::findInstance.
fileName localObjectPath(const IOobject &, const pathType &searchType, const word &processorsDir, const word &instancePath) const
Construct filePath.
virtual bool isFile(const fileName &, const bool checkGzip=true, const bool followLink=true) const
Does the name exist as a FILE in the file system?
virtual fileMonitor::fileState getState(const label) const
Get current state of file (using handle)
static const Enum< pathType > pathTypeNames_
Definition: fileOperation.H:94
List< instant > instantList
List of instants.
Definition: instantList.H:41
Generic output stream using a standard (STL) stream.
Definition: OSstream.H:50
virtual bool cp(const fileName &src, const fileName &dst, const bool followLink=true) const
Copy, recursively if necessary, the source to the destination.
const Type & value() const noexcept
Return const reference to value.
virtual bool chMod(const fileName &, const mode_t) const
Set the file mode.
virtual bool mv(const fileName &src, const fileName &dst, const bool followLink=false) const
Rename src to dst.
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:118
fileName path() const
Return path.
Definition: Time.H:449
virtual fileNameList readDir(const fileName &, const fileName::Type=fileName::FILE, const bool filtergz=true, const bool followLink=true) const
Read a directory and return the entries as a string list.
A class for handling file names.
Definition: fileName.H:71
virtual const fileName & name() const
The name of the stream.
Definition: IOstream.C:33
off_t fileSize(const fileName &name, const bool followLink=true)
Return size of file or -1 on failure (normally follows symbolic links).
Definition: POSIX.C:858
virtual time_t lastModified(const fileName &, const bool followLink=true) const
Return time of last file modification.
io.objectPath() exists
Definition: fileOperation.H:76
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
virtual label addWatch(const fileName &) const
Add watching of a file. Returns handle.
as PROCUNCOLLATED but with instance
Definition: fileOperation.H:90
commsTypes
Types of communications.
Definition: UPstream.H:66
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:578
void append(const T &val)
Append an element at the end of the list.
Definition: List.H:491
const word & name() const noexcept
Return the object name.
Definition: IOobjectI.H:150
virtual autoPtr< ISstream > NewIFstream(const fileName &) const
Generate an ISstream that reads a file.
static autoPtr< ISstream > readBlock(const label blocki, ISstream &is, IOobject &headerIO)
Read selected block (non-seeking) + header information.
fileState
Enumeration defining the file state.
Definition: fileMonitor.H:71
static rangeType allProcs(const label communicator=worldComm)
Range of process indices for all processes.
Definition: UPstream.H:748
int infoDetailLevel
Global for selective suppression of Info output.
virtual double highResLastModified(const fileName &, const bool followLink=true) const
Return time of last file modification.
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:49
bool empty() const noexcept
True if the UList is empty (ie, size() is zero)
Definition: UListI.H:420
static const fileName null
An empty fileName.
Definition: fileName.H:110
T * data() noexcept
Return pointer to the underlying array serving as data storage.
Definition: UListI.H:230
virtual autoPtr< ISstream > readStream(regIOobject &, const fileName &, const word &typeName, const bool valid=true) const
Reads header for regIOobject and returns an ISstream.
virtual bool readHeader(IOobject &, const fileName &, const word &typeName) const
Read object header from supplied file.
virtual bool isDir(const fileName &, const bool followLink=true) const
Does the name exist as a DIRECTORY in the file system?
label findSortedIndex(const ListType &input, typename ListType::const_reference val, const label start=0)
Binary search to find the index of the last element in a sorted list that is less than value...
virtual fileNameList readObjects(const objectRegistry &db, const fileName &instance, const fileName &local, word &newInstance) const
Search directory for objects. Used in IOobjectList.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:487
bool found(const T &val, label pos=0) const
True if the value if found in the list.
Definition: UListI.H:258
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:639
virtual bool rmDir(const fileName &dir, const bool silent=false, const bool emptyOnly=false) const
Remove a directory and its contents.
void clear() noexcept
Same as reset(nullptr)
Definition: autoPtr.H:255
runTimeSource setTime(sourceTimes[sourceTimeIndex], sourceTimeIndex)
static void reduceOr(bool &value, const label communicator=worldComm)
Logical (or) reduction (cf. MPI AllReduce)
file found in time directory
Definition: fileOperation.H:89
void stableSort(UList< T > &list)
Stable sort the list.
Definition: UList.C:348
static bool readBlocks(const label comm, autoPtr< ISstream > &isPtr, List< char > &contentChars, const UPstream::commsTypes commsType)
Read data into *this. ISstream is only valid on master.
static int & msgType() noexcept
Message tag of standard messages.
Definition: UPstream.H:806
label subCycling() const noexcept
Zero (tests as false) if time is not being sub-cycled, otherwise the current sub-cycle index or the t...
Definition: Time.H:683
A simple container for options an IOstream can normally have.
virtual bool ln(const fileName &src, const fileName &dst) const
Create a softlink. dst should not exist. Returns true if.
virtual autoPtr< OSstream > NewOFstream(const fileName &pathname, IOstreamOption streamOpt=IOstreamOption(), const bool valid=true) const
Generate an OSstream that writes a file.
static int myProcNo(const label communicator=worldComm)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:688
static label worldComm
Default world communicator (all processors). May differ from globalComm if local worlds are in use...
Definition: UPstream.H:361
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:69
A class for managing references or pointers (no reference counting)
Definition: HashPtrTable.H:49
bool exists(const dirIndexList &, IOobject &io) const
Helper: check IO for local existence. Like filePathInfo but.
An encapsulation of filesystem-related operations.
Definition: fileOperation.H:63
fileName objectPath() const
The complete path + object name.
Definition: IOobjectI.H:239
Macros for easy insertion into run-time selection tables.
as PROCOBJECT but with instance
Definition: fileOperation.H:92
static bool isReadRequired(readOption opt) noexcept
True if (MUST_READ | MUST_READ_IF_MODIFIED) bits are set.
UList< label > labelUList
A UList of labels.
Definition: UList.H:80
addNamedToRunTimeSelectionTable(fileOperationInitialise, collatedFileOperationInitialise, word, collated)
static void broadcast(Type &value, const label comm=UPstream::worldComm)
Broadcast content (contiguous or non-contiguous) to all processes in communicator.
bool read(const char *buf, int32_t &val)
Same as readInt32.
Definition: int32.H:125
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:413
constexpr const char *const group
Group name for atomic constants.
virtual fileName filePath(const bool checkGlobal, const IOobject &io, const word &typeName, const bool search) const
Search for an object. checkGlobal : also check undecomposed case.
void reset(T *p=nullptr) noexcept
Delete managed object and set to new given pointer.
Definition: autoPtrI.H:37
addToRunTimeSelectionTable(fileOperation, collatedFileOperation, word)
Input inter-processor communications stream using MPI send/recv etc. - operating on external buffer...
Definition: UIPstream.H:251
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: POSIX.C:752
atomicType
Atomic operations (output)
unsigned int count(const UList< bool > &bools, const bool val=true)
Count number of &#39;true&#39; entries.
Definition: BitOps.H:73
virtual fileName filePathInfo(const bool checkGlobal, const bool isFile, const IOobject &io, const bool search, pathType &searchType, word &processorsDir, word &instance) const
Search (locally!) for object; return info on how it was found.
static label nProcs(const label communicator=worldComm)
Number of ranks in parallel run (for given communicator) is 1 for serial run.
Definition: UPstream.H:656
static void gatherList(const List< commsStruct > &comms, List< T > &values, const int tag, const label comm)
Gather data, but keep individual values separate. Uses the specified communication schedule...
IOobject io("surfaceFilmProperties", mesh.time().constant(), mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE, false)
virtual bool writeObject(const regIOobject &io, IOstreamOption streamOpt=IOstreamOption(), const bool valid=true) const
Writes a regIOobject (so header, contents and divider).
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:52
instance is absolute directory
Definition: fileOperation.H:75
"scheduled" : (MPI_Send, MPI_Recv)
bool good() const noexcept
True if the managed pointer is non-null.
Definition: autoPtr.H:206
objectPath exists in &#39;processorsNN&#39;
Definition: fileOperation.H:83
labelList identity(const label len, label start=0)
Return an identity map of the given length with (map[i] == i)
Definition: labelList.C:31
static float maxMasterFileBufferSize
Max size of parallel communications. Switches from non-blocking.
A class for handling words, derived from Foam::string.
Definition: word.H:63
const Time & time() const noexcept
Return time registry.
Master-only drop-in replacement for OFstream.
objectPath exists in &#39;processorN&#39;
Definition: fileOperation.H:81
virtual fileName dirPath(const bool checkGlobal, const IOobject &io, const bool search) const
Search for a directory. checkGlobal : also check undecomposed.
virtual instantList findTimes(const fileName &, const word &) const
Get sorted list of times.
Inter-processor communications stream.
Definition: Pstream.H:56
static constexpr int masterNo() noexcept
Process index of the master (always 0)
Definition: UPstream.H:664
void finishedSends(const bool wait=true)
Mark sends as done.
virtual void addWatches(regIOobject &, const fileNameList &) const
Helper: add watches for list of regIOobjects.
static const word null
An empty word.
Definition: word.H:84
bool exists(const fileName &name, const bool checkGzip=true, const bool followLink=true)
Does the name exist (as DIRECTORY or FILE) in the file system?
Definition: POSIX.C:788
bool local
Definition: EEqn.H:20
as PROCBASEOBJECT but with instance
Definition: fileOperation.H:91
void append(const T &val)
Copy append an element to the end of this list.
Definition: DynamicList.H:558
objectPath exists in &#39;processorsNN_first-last&#39;
Definition: fileOperation.H:85
static bool isCollatedType(const word &objectType)
True if object type is a known collated type.
virtual bool removeWatch(const label) const
Remove watch on a file (using handle)
#define DetailInfo
Definition: evalEntry.C:30
virtual void updateStates(const bool masterOnly, const bool syncPar) const
Update state of all files.
static bool readHeader(IOobject &io, Istream &is)
Read header as per IOobject with additional handling of decomposedBlockData.
static bool isUserComm(label communicator) noexcept
True if communicator appears to be user-allocated.
Definition: UPstream.H:386
static Ostream & writeEndDivider(Ostream &os)
Write the standard end file divider.
An ISstream with internal List storage. Always UNCOMPRESSED.
Definition: IListStream.H:144
const labelList & watchIndices() const noexcept
Read access to file-monitoring handles.
Definition: regIOobjectI.H:195
virtual bool mvBak(const fileName &, const std::string &ext="bak") const
Rename to a corresponding backup file.
parent of object path
Definition: fileOperation.H:88
static word timeName(const scalar t, const int precision=precision_)
Return time name of given scalar time formatted with the given precision.
Definition: Time.C:760
const word & constant() const noexcept
Return constant name.
Definition: TimePathsI.H:89
int debug
Static debugging option.
OBJstream os(runTime.globalPath()/outputName)
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
static fileCheckTypes fileModificationChecking
Type of file modification checking.
Definition: IOobject.H:313
Input from file stream, using an ISstream.
Definition: IFstream.H:49
labelList f(nPoints)
Buffers for inter-processor communications streams (UOPstream, UIPstream).
const fileName & instance() const noexcept
Read access to instance path component.
Definition: IOobjectI.H:221
virtual void flush() const
Forcibly wait until all output done. Flush any cached data.
static void broadcasts(const label comm, Type &arg1, Args &&... args)
Broadcast multiple items to all processes in communicator.
virtual bool mkDir(const fileName &, mode_t=0777) const
Make directory.
bool erase(const iterator &iter)
Erase an entry specified by given iterator.
Definition: HashTable.C:433
word format(conversionProperties.get< word >("format"))
bool isFile(const fileName &name, const bool checkGzip=true, const bool followLink=true)
Does the name exist as a FILE in the file system?
Definition: POSIX.C:830
List< word > wordList
A List of words.
Definition: fileName.H:58
virtual instantList findTimes(const fileName &, const word &) const
Get sorted list of times.
An instant of time. Contains the time value and name. Uses Foam::Time when formatting the name...
Definition: instant.H:53
List< string > stringList
A List of strings.
Definition: stringList.H:54
virtual bool rm(const fileName &) const
Remove a file, returning true if successful otherwise false.
virtual void flush() const
Forcibly wait until all output done. Flush any cached data.
instantList times() const
Search the case for valid time directories.
Definition: TimePaths.C:142
float floatOptimisationSwitch(const char *name, const float deflt=0)
Lookup optimisation switch or add default value.
Definition: debug.C:240
virtual void setTime(const Time &) const
Callback for time change.
#define WarningInFunction
Report a warning using Foam::Warning.
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:607
const Time & time() const
Return Time associated with the objectRegistry.
Definition: IOobject.C:447
virtual void setUnmodified(const label) const
Set current state of file (using handle) to unmodified.
static bool master(const label communicator=worldComm)
Am I the master rank.
Definition: UPstream.H:672
registerOptSwitch("maxThreadFileBufferSize", float, collatedFileOperation::maxThreadFileBufferSize)
streamFormat
Data format (ascii | binary)
regIOobject is an abstract class derived from IOobject to handle automatic object registration with t...
Definition: regIOobject.H:69
"nonBlocking" : (MPI_Isend, MPI_Irecv)
label n
static void readAndSend(const fileName &filePath, const labelUList &procs, PstreamBuffers &pBufs)
Read file contents and send to processors.
static autoPtr< ISstream > read(IOobject &io, const label comm, const bool uniform, const fileNameList &filePaths, const boolList &procValid)
Read files on comms master.
virtual fileName::Type type(const fileName &, const bool followLink=true) const
Return the file type: DIRECTORY, FILE or SYMLINK.
virtual fileName getFile(const label) const
Get name of file being watched (using handle)
fileName search(const word &file, const fileName &directory)
Recursively search the given directory for the file.
Definition: fileName.C:640
virtual off_t fileSize(const fileName &, const bool followLink=true) const
Return size of file.
virtual label findWatch(const labelList &watchIndices, const fileName &) const
Find index (or -1) of file in list of handles.
#define forAllReverse(list, i)
Reverse loop across all elements in list.
Definition: stdFoam.H:429
defineTypeNameAndDebug(collatedFileOperation, 0)
List< label > labelList
A List of labels.
Definition: List.H:62
static rangeType subProcs(const label communicator=worldComm)
Range of process indices for sub-processes.
Definition: UPstream.H:757
virtual fileNameList readObjects(const objectRegistry &db, const fileName &instance, const fileName &local, word &newInstance) const
Search directory for objects. Used in IOobjectList.
Registry of regIOobjects.
bool equal(scalar val) const noexcept
True if values are equal (includes SMALL for rounding)
Definition: Instant.H:155
static labelList ioRanks()
Retrieve list of IO ranks from FOAM_IORANKS env variable.
virtual void setTime(const Time &) const
Callback for time change.
const fileName & local() const noexcept
Read access to local path component.
Definition: IOobjectI.H:233
static label read(const commsTypes commsType, const int fromProcNo, char *buf, const std::streamsize bufSize, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Read buffer contents from given processor.
Definition: UIPstreamRead.C:35
List< fileName > fileNameList
A List of fileNames.
Definition: fileNameList.H:54
#define NotImplemented
Issue a FatalErrorIn for a function not currently implemented.
Definition: error.H:666
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:166
mode_t mode(const fileName &name, const bool followLink=true)
Return the file mode, normally following symbolic links.
Definition: POSIX.C:726
List< bool > boolList
A List of bools.
Definition: List.H:60
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
Inter-processor communications stream.
Definition: UPstream.H:54
virtual IOobject findInstance(const IOobject &io, const scalar startValue, const word &stopInstance) const
Find instance where IOobject is.
static void freeCommunicator(const label communicator, const bool doPstream=true)
Free a previously allocated communicator.
Definition: UPstream.C:239
Type
Enumerations to handle directory entry types.
Definition: fileName.H:80
Extract type (as a word) from an object, typically using its type() method.
Definition: word.H:361
static labelList subRanks(const label n)
Get the list of processors that are part of this communicator.
Namespace for OpenFOAM.
A class representing the concept of 1 (one) that can be used to avoid manipulating objects known to b...
Definition: one.H:57
IOerror FatalIOError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL IO ERROR&#39; header text and ...