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-2025 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 
32 #include "Pstream.H"
33 #include "Time.H"
34 #include "instant.H"
35 #include "IFstream.H"
36 #include "SpanStream.H"
37 #include "masterOFstream.H"
38 #include "decomposedBlockData.H"
39 #include "registerSwitch.H"
40 #include "dummyISstream.H"
41 #include "SubList.H"
42 
43 /* * * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * */
44 
45 namespace Foam
46 {
47 namespace fileOperations
48 {
51  (
54  word
55  );
57  (
60  comm
61  );
62 
64  (
65  Foam::debug::floatOptimisationSwitch("maxMasterFileBufferSize", 1e9)
66  );
68  (
69  "maxMasterFileBufferSize",
70  float,
72  );
73 
74  // Threaded MPI: not required
76  (
79  word,
80  masterUncollated
81  );
82 }
83 }
84 
85 
86 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
87 
90 (
91  const bool checkGlobal,
92  const bool isFile,
93  const IOobject& io,
94  const dirIndexList& pDirs,
95  const bool search,
96  pathType& searchType,
97  word& procsDir,
98  word& newInstancePath
99 ) const
100 {
101  procsDir.clear();
102  newInstancePath.clear();
103 
104  if (io.instance().isAbsolute())
105  {
106  fileName objPath = io.instance()/io.name();
107 
108  if (isFileOrDir(isFile, objPath))
109  {
110  searchType = fileOperation::ABSOLUTE;
111  return objPath;
112  }
113  else
114  {
115  searchType = fileOperation::NOTFOUND;
116  return fileName();
117  }
118  }
119  else
120  {
121  // 1. Check the writing fileName
122  fileName writePath(objectPath(io, io.headerClassName()));
123 
124  if (isFileOrDir(isFile, writePath))
125  {
126  searchType = fileOperation::WRITEOBJECT;
127  return writePath;
128  }
129 
130  // 2. Check processors/
131  if (io.time().processorCase())
132  {
133  for (const dirIndex& dirIdx : pDirs)
134  {
135  const fileName& pDir = dirIdx.first();
136  fileName objPath =
137  processorsPath(io, io.instance(), pDir)
138  /io.name();
139  if (objPath != writePath && isFileOrDir(isFile, objPath))
140  {
141  searchType = dirIdx.second().first();
142  procsDir = pDir;
143  return objPath;
144  }
145  }
146  }
147  {
148  // 3. Check local
149  fileName localPath = io.objectPath();
150 
151  if
152  (
153  localPath != writePath
154  && isFileOrDir(isFile, localPath)
155  )
156  {
157  searchType = fileOperation::OBJECT;
158  return localPath;
159  }
160  }
161 
162 
163 
164  // Any global checks
165  if
166  (
167  checkGlobal
168  && io.time().processorCase()
169  && (
170  io.instance() == io.time().system()
171  || io.instance() == io.time().constant()
172  )
173  )
174  {
175  fileName parentPath =
176  (
177  io.rootPath()/io.globalCaseName()
178  /io.instance()/io.db().dbDir()/io.local()/io.name()
179  );
180 
181  if (isFileOrDir(isFile, parentPath))
182  {
183  searchType = fileOperation::PARENTOBJECT;
184  return parentPath;
185  }
186  }
187 
188  // Check for approximately same time. E.g. if time = 1e-2 and
189  // directory is 0.01 (due to different time formats)
190  const auto pathFnd = times_.cfind(io.time().path());
191 
192  if (search && pathFnd.good())
193  {
194  newInstancePath =
196  (
197  *pathFnd(),
198  instant(io.instance())
199  );
200 
201  if (newInstancePath.size() && newInstancePath != io.instance())
202  {
203  // 1. Try processors equivalent
204  for (const dirIndex& dirIdx : pDirs)
205  {
206  const fileName& pDir = dirIdx.first();
207 
208  fileName fName
209  (
210  processorsPath(io, newInstancePath, pDir)
211  /io.name()
212  );
213  if (isFileOrDir(isFile, fName))
214  {
215  switch (dirIdx.second().first())
216  {
218  {
219  searchType =
221  }
222  break;
224  {
225  searchType = fileOperation::PROCBASEINSTANCE;
226  }
227  break;
229  {
230  searchType = fileOperation::PROCINSTANCE;
231  }
232  break;
233  default:
234  break;
235  }
236  procsDir = pDir;
237  return fName;
238  }
239  }
240 
241 
242  // 2. Check local
243  fileName fName
244  (
245  io.rootPath()/io.caseName()
246  /newInstancePath/io.db().dbDir()/io.local()/io.name()
247  );
248  if (isFileOrDir(isFile, fName))
249  {
250  searchType = fileOperation::FINDINSTANCE;
251  return fName;
252  }
253  }
254  }
255  }
256 
257  // Nothing found
258  searchType = fileOperation::NOTFOUND;
259  return fileName();
260 }
261 
262 
265 (
266  const IOobject& io,
267  const pathType& searchType,
268  const word& procDir,
269  const word& instancePath
270 ) const
271 {
272  // Replacement for IOobject::objectPath()
273 
274  switch (searchType)
275  {
277  {
278  return io.instance()/io.name();
279  }
280  break;
281 
283  {
284  return io.path()/io.name();
285  }
286  break;
287 
289  {
290  return objectPath(io, io.headerClassName());
291  }
292  break;
293 
295  {
296  // Uncollated type, e.g. processor1
297  const word procName
298  (
300  );
301  return
302  processorsPath
303  (
304  io,
305  io.instance(),
306  (
308  ? procName
309  : procDir
310  )
311  )
312  /io.name();
313  }
314  break;
315 
317  {
318  // Collated, e.g. processors4
319  return
320  processorsPath(io, io.instance(), procDir)
321  /io.name();
322  }
323  break;
324 
326  {
327  // Processors directory locally provided by the fileHandler itself
328  return
329  processorsPath(io, io.instance(), processorsDir(io))
330  /io.name();
331  }
332  break;
333 
335  {
336  return
337  io.rootPath()/io.globalCaseName()
338  /io.instance()/io.db().dbDir()/io.local()/io.name();
339  }
340  break;
341 
343  {
344  return
345  io.rootPath()/io.caseName()
346  /instancePath/io.db().dbDir()/io.local()/io.name();
347  }
348  break;
349 
351  {
352  // Uncollated type, e.g. processor1
353  const word procName
354  (
355  "processor"
357  );
358  return
359  processorsPath
360  (
361  io,
362  instancePath,
363  (
365  ? procName
366  : procDir
367  )
368  )
369  /io.name();
370  }
371  break;
372 
374  {
375  // Collated, e.g. processors4
376  return
377  processorsPath(io, instancePath, procDir)
378  /io.name();
379  }
380  break;
381 
383  {
384  // Processors directory locally provided by the fileHandler itself
385  return
386  processorsPath(io, instancePath, processorsDir(io))
387  /io.name();
388  }
389  break;
390 
392  {
393  return fileName();
394  }
395  break;
396 
397  default:
398  {
400  return fileName();
401  }
402  }
403 }
404 
405 
407 (
408  const fileName& filePath,
409  const labelUList& recvProcs,
410  PstreamBuffers& pBufs
411 )
412 {
413  if (recvProcs.empty()) return;
414 
415  IFstream ifs(filePath, IOstreamOption::BINARY);
416 
417  if (!ifs.good())
418  {
419  FatalIOErrorInFunction(filePath)
420  << "Cannot open file " << filePath
421  << exit(FatalIOError);
422  }
423 
424  // Read file contents (compressed or uncompressed) into a character buffer
425  DynamicList<char> buf(IFstream::readContents(ifs));
426 
427  if (debug)
428  {
429  Info<< "masterUncollatedFileOperation::readAndSend :"
430  << filePath
431  << " (compressed:" << bool(ifs.compression())
432  << ") : " << " bytes" << endl;
433  }
434 
435  for (const label proci : recvProcs)
436  {
437  UOPstream os(proci, pBufs);
438  os.write(buf.cdata_bytes(), buf.size_bytes());
439  }
440 }
441 
442 
445 (
446  IOobject& io,
447  const label comm,
448  const bool uniform, // on comms master only
449  const fileNameList& filePaths, // on comms master and sub-ranks
450  const boolUList& readOnProcs // on comms master and sub-ranks
451 )
452 {
453  autoPtr<ISstream> isPtr;
454 
455  PstreamBuffers pBufs(comm);
456 
457  if (UPstream::master(comm))
458  {
459  if (uniform)
460  {
461  if (readOnProcs[0])
462  {
463  if (filePaths[0].empty())
464  {
465  FatalIOErrorInFunction(filePaths[0])
466  << "Cannot find file " << io.objectPath()
467  << " fileHandler : comm:" << comm
468  << " ioRanks:" << UPstream::procID(comm)
469  << exit(FatalIOError);
470  }
471 
472  DynamicList<label> recvProcs(UPstream::nProcs(comm));
473  for (const int proci : UPstream::allProcs(comm))
474  {
475  if (readOnProcs[proci])
476  {
477  recvProcs.push_back(proci);
478  }
479  }
480 
481  // Read on master and send to all processors
482  // (including master for simplicity)
483  if (debug)
484  {
485  Pout<< "masterUncollatedFileOperation::readStream :"
486  << " For uniform file " << filePaths[0]
487  << " sending to " << recvProcs
488  << " in comm:" << comm << endl;
489  }
490  readAndSend(filePaths[0], recvProcs, pBufs);
491  }
492  }
493  else
494  {
495  if (readOnProcs[0])
496  {
497  if (filePaths[0].empty())
498  {
499  FatalIOErrorInFunction(filePaths[0])
500  << "Cannot find file " << io.objectPath()
501  << " fileHandler : comm:" << comm
502  << " ioRanks:" << UPstream::procID(comm)
503  << exit(FatalIOError);
504  }
505 
506  // Open master
507  isPtr.reset(new IFstream(filePaths[0]));
508 
509  // Read header
510  if (!io.readHeader(*isPtr))
511  {
512  FatalIOErrorInFunction(*isPtr)
513  << "problem while reading header for object "
514  << io.name()
515  << " fileHandler : comm:" << comm
516  << " ioRanks:" << UPstream::procID(comm)
517  << exit(FatalIOError);
518  }
519  }
520 
521  // Read sub-rank files
522  for (const int proci : UPstream::subProcs(comm))
523  {
524  if (debug)
525  {
526  Pout<< "masterUncollatedFileOperation::readStream :"
527  << " For processor " << proci
528  << " opening " << filePaths[proci] << endl;
529  }
530 
531  const fileName& fPath = filePaths[proci];
532 
533  if (readOnProcs[proci] && !fPath.empty())
534  {
535  // Note: handle compression ourselves since size cannot
536  // be determined without actually uncompressing
537  readAndSend(fPath, labelList(one{}, proci), pBufs);
538  }
539  }
540  }
541  }
542 
543  pBufs.finishedScatters();
544 
545  // isPtr will be valid on master and will be the unbuffered
546  // IFstream. Else the information is in the PstreamBuffers (and
547  // the special case of a uniform file)
548 
549  if (!isPtr)
550  {
551  if (readOnProcs[UPstream::myProcNo(comm)])
552  {
553  // This processor needs to return something
554  List<char> buf(pBufs.recvDataCount(UPstream::masterNo()));
555 
556  if (!buf.empty())
557  {
558  UIPstream is(UPstream::masterNo(), pBufs);
559  is.read(buf.data(), buf.size());
560  }
561 
562  if (debug)
563  {
564  Pout<< "masterUncollatedFileOperation::readStream :"
565  << " Done reading " << buf.size() << " bytes" << endl;
566  }
567 
568  // A local character buffer copy of the Pstream contents.
569  // Construct with same parameters (ASCII, current version)
570  // as the IFstream so that it has the same characteristics.
571 
572  isPtr.reset(new ICharStream(std::move(buf)));
573 
574  // With the proper file name
575  isPtr->name() = filePaths[UPstream::myProcNo(comm)];
576 
577  if (!io.readHeader(*isPtr))
578  {
579  FatalIOErrorInFunction(*isPtr)
580  << "problem while reading header for object "
581  << io.name()
582  << " fileHandler : comm:" << comm
583  << " ioRanks:" << UPstream::procID(comm)
584  << exit(FatalIOError);
585  }
586  }
587  else
588  {
589  isPtr.reset(new dummyISstream());
590  }
591  }
592 
593  return isPtr;
594 }
595 
596 
597 // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
598 
599 namespace Foam
600 {
601 
602 // Construction helper: self/world/local communicator and IO ranks
604 {
605  // Default is COMM_WORLD (single master)
606  Tuple2<label, labelList> commAndIORanks
607  (
610  );
611 
612  if (UPstream::parRun() && commAndIORanks.second().size() > 1)
613  {
614  // Multiple masters: ranks for my IO range
615  commAndIORanks.first() = UPstream::newCommunicator
616  (
618  fileOperation::subRanks(commAndIORanks.second())
619  );
620  }
621 
622  return commAndIORanks;
623 }
624 
625 } // End namespace Foam
626 
627 
628 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
629 
630 void Foam::fileOperations::masterUncollatedFileOperation::init(bool verbose)
631 {
632  verbose = (verbose && Foam::infoDetailLevel > 0);
633 
634  if (verbose)
635  {
636  DetailInfo
637  << "I/O : " << typeName
638  << " (maxMasterFileBufferSize " << maxMasterFileBufferSize << ')'
639  << endl;
640  }
641 
643  {
644  if (verbose)
645  {
647  << "Resetting fileModificationChecking to timeStamp" << endl;
648  }
650  }
652  {
653  if (verbose)
654  {
656  << "Resetting fileModificationChecking to inotify"
657  << endl;
658  }
660  }
661 }
662 
663 
666 (
667  bool verbose
668 )
669 :
670  fileOperation
671  (
673  ),
674  managedComm_(getManagedComm(comm_)) // Possibly locally allocated
675 {
676  init(verbose);
677 
678  if (comm_ == -1)
679  {
680  FatalErrorInFunction<< "Problem comm_:" << comm_ << exit(FatalError);
681  }
682  if (UPstream::nProcs(comm_) == -1)
683  {
684  FatalErrorInFunction<< "Problem comm_:" << comm_
685  << " nProcs:" << UPstream::nProcs(comm_)
686  << exit(FatalError);
687  }
688  if (UPstream::myProcNo(comm_) == -1)
689  {
690  FatalErrorInFunction<< "Problem comm_:" << comm_
691  << " myProcNo:" << UPstream::myProcNo(comm_)
692  << exit(FatalError);
693  }
694 }
695 
696 
699 (
700  const Tuple2<label, labelList>& commAndIORanks,
701  const bool distributedRoots,
702  bool verbose
703 )
704 :
705  fileOperation(commAndIORanks, distributedRoots),
706  managedComm_(-1) // Externally managed
707 {
708  init(verbose);
709 
710  if (comm_ == -1)
711  {
712  FatalErrorInFunction<< "Problem comm_:" << comm_ << exit(FatalError);
713  }
714  if (UPstream::nProcs(comm_) == -1)
715  {
716  FatalErrorInFunction<< "Problem comm_:" << comm_
717  << " nProcs:" << UPstream::nProcs(comm_)
718  << exit(FatalError);
719  }
720  if (UPstream::myProcNo(comm_) == -1)
721  {
722  FatalErrorInFunction<< "Problem comm_:" << comm_
723  << " myProcNo:" << UPstream::myProcNo(comm_)
724  << exit(FatalError);
725  }
726 }
727 
728 
730 {
731  // From externally -> locally managed
732  managedComm_ = getManagedComm(comm_);
733 }
734 
735 
736 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
737 
740 {
741  UPstream::freeCommunicator(managedComm_);
742 }
743 
744 
745 // * * * * * * * * * * * * * Filesystem Operations * * * * * * * * * * * * * //
746 
748 (
749  const fileName& dir,
750  mode_t mode
751 ) const
752 {
753  return masterOp<bool>
754  (
755  dir,
758  comm_
759  );
760 }
761 
762 
764 (
765  const fileName& fName,
766  mode_t mode
767 ) const
768 {
769  return masterOp<bool>
770  (
771  fName,
774  comm_
775  );
776 }
777 
778 
780 (
781  const fileName& fName,
782  const bool followLink
783 ) const
784 {
785  return masterOp<mode_t>
786  (
787  fName,
788  modeOp(followLink),
790  comm_
791  );
792 }
793 
794 
796 (
797  const fileName& fName,
798  const bool followLink
799 ) const
800 {
801  return fileName::Type
802  (
803  masterOp<int>
804  (
805  fName,
806  typeOp(followLink),
808  comm_
809  )
810  );
811 }
812 
813 
815 (
816  const fileName& fName,
817  const bool checkGzip,
818  const bool followLink
819 ) const
820 {
821  return masterOp<bool>
822  (
823  fName,
824  existsOp(checkGzip, followLink),
826  comm_
827  );
828 }
829 
830 
832 (
833  const fileName& fName,
834  const bool followLink
835 ) const
836 {
837  return masterOp<bool>
838  (
839  fName,
840  isDirOp(followLink),
842  comm_
843  );
844 }
845 
846 
848 (
849  const fileName& fName,
850  const bool checkGzip,
851  const bool followLink
852 ) const
853 {
854  return masterOp<bool>
855  (
856  fName,
857  isFileOp(checkGzip, followLink),
859  comm_
860  );
861 }
862 
863 
865 (
866  const fileName& fName,
867  const bool followLink
868 ) const
869 {
870  // Reduce as int64_t instead of off_t to avoid missing
871  // pTraits<long int> (or other ambiguities) on Mingw and Linux i586
872 
873  return off_t
874  (
875  masterOp<int64_t>
876  (
877  fName,
878  fileSizeOp(followLink),
880  comm_
881  )
882  );
883 }
884 
885 
887 (
888  const fileName& fName,
889  const bool followLink
890 ) const
891 {
892  // time_t is invariably an integer type, but verify that anyhow
893  // before doing the following:
894 
895  if constexpr (std::is_integral_v<time_t>)
896  {
897  // Reduce as int64_t instead of time_t to avoid missing
898  // pTraits<long int> (or other ambiguities) on Linux i586
899  return time_t
900  (
901  masterOp<int64_t>
902  (
903  fName,
904  lastModifiedOp(followLink),
907  )
908  );
909  }
910  else
911  {
912  return masterOp<time_t>
913  (
914  fName,
915  lastModifiedOp(followLink),
918  );
919  }
920 }
921 
922 
924 (
925  const fileName& fName,
926  const bool followLink
927 ) const
928 {
929  return masterOp<double>
930  (
931  fName,
935  );
936 }
937 
938 
940 (
941  const fileName& fName,
942  const std::string& ext
943 ) const
944 {
945  return masterOp<bool>
946  (
947  fName,
948  mvBakOp(ext),
950  comm_
951  );
952 }
953 
954 
956 (
957  const fileName& fName
958 ) const
959 {
960  return masterOp<bool>
961  (
962  fName,
963  rmOp(),
965  comm_
966  );
967 }
968 
969 
971 (
972  const fileName& dir,
973  const bool silent,
974  const bool emptyOnly
975 ) const
976 {
977  return masterOp<bool>
978  (
979  dir,
980  rmDirOp(silent, emptyOnly),
982  comm_
983  );
984 }
985 
986 
988 (
989  const fileName& dir,
990  const fileName::Type type,
991  const bool filtergz,
992  const bool followLink
993 ) const
994 {
995  return masterOp<fileNameList>
996  (
997  dir,
998  readDirOp(type, filtergz, followLink),
1000  comm_
1001  );
1002 }
1003 
1004 
1006 (
1007  const fileName& src,
1008  const fileName& dst,
1009  const bool followLink
1010 ) const
1011 {
1012  return masterOp<bool>
1013  (
1014  src,
1015  dst,
1016  cpOp(followLink),
1018  comm_
1019  );
1020 }
1021 
1022 
1024 (
1025  const fileName& src,
1026  const fileName& dst
1027 ) const
1028 {
1029  return masterOp<bool>
1030  (
1031  src,
1032  dst,
1033  lnOp(),
1035  comm_
1036  );
1037 }
1038 
1039 
1041 (
1042  const fileName& src,
1043  const fileName& dst,
1044  const bool followLink
1045 ) const
1046 {
1047  return masterOp<bool>
1048  (
1049  src,
1050  dst,
1051  mvOp(followLink),
1053  comm_
1054  );
1055 }
1056 
1057 
1058 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
1059 
1061 (
1062  const bool checkGlobal,
1063  const IOobject& io,
1064  const word& typeName,
1065  const bool search
1066 ) const
1067 {
1068  if (debug)
1069  {
1070  Pout<< "masterUncollatedFileOperation::filePath :"
1071  << " objectPath:" << io.objectPath()
1072  << " checkGlobal:" << checkGlobal
1073  << " parRun:" << Pstream::parRun()
1074  << " localmaster:" << Pstream::master(comm_) << endl;
1075  }
1076 
1077  // Now that we have an IOobject path use it to detect & cache
1078  // processor directory naming
1079  const refPtr<dirIndexList> pDirs(lookupProcessorsPath(io.objectPath()));
1080 
1081  // Trigger caching of times
1082  if (cacheLevel() > 0)
1083  {
1084  (void)findTimes(io.time().path(), io.time().constant());
1085  }
1086 
1087  // Determine master filePath and scatter
1088 
1089  fileName objPath;
1090  pathType searchType = NOTFOUND;
1091  word procsDir;
1092  word newInstancePath;
1093 
1094  if (Pstream::master(comm_))
1095  {
1096  const bool oldParRun = UPstream::parRun(false);
1097  const int oldCache = fileOperation::cacheLevel(0);
1098  const label oldNProcs = fileOperation::nProcs();
1099 
1100  // All masters search locally. Note that global objects might
1101  // fail (except on master). This gets handled later on (in PARENTOBJECT)
1102  objPath =
1103  filePathInfo
1104  (
1105  checkGlobal,
1106  true,
1107  io,
1108  pDirs,
1109  search,
1110  searchType,
1111  procsDir,
1112  newInstancePath
1113  );
1114 
1115  const_cast<masterUncollatedFileOperation&>(*this).nProcs(oldNProcs);
1116  fileOperation::cacheLevel(oldCache);
1117  UPstream::parRun(oldParRun);
1118 
1119  if (debug)
1120  {
1121  Pout<< "masterUncollatedFileOperation::filePath :"
1122  << " master objPath:" << objPath
1123  << " searchType:" << fileOperation::pathTypeNames_[searchType]
1124  << " procsDir:" << procsDir << " instance:" << newInstancePath
1125  << endl;
1126  }
1127  }
1128 
1129  // Broadcast information about where the master found the object
1130  // Note: use the worldComm to make sure all processors decide
1131  // the same type. Only procsDir is allowed to differ; searchType
1132  // and instance have to be same
1133  if (UPstream::parRun())
1134  {
1135  int masterType(searchType);
1136  Pstream::broadcasts(UPstream::worldComm, masterType, newInstancePath);
1137  searchType = pathType(masterType);
1138  }
1139 
1140  if
1141  (
1142  checkGlobal
1143  || searchType == fileOperation::PARENTOBJECT
1144  || searchType == fileOperation::PROCBASEOBJECT
1145  || searchType == fileOperation::PROCBASEINSTANCE
1146  || io.local() == "uniform"
1147  )
1148  {
1149  // Distribute master path. This makes sure it is seen as uniform
1150  // and only gets read from the master.
1151  Pstream::broadcasts(UPstream::worldComm, objPath, procsDir);
1152  }
1153  else
1154  {
1155  Pstream::broadcast(procsDir, comm_);
1156 
1157  // Use the master type to determine if additional information is
1158  // needed to construct the local equivalent
1159  switch (searchType)
1160  {
1164  {
1165  // Already handled above
1166  }
1167  break;
1168 
1176  {
1177  // Construct equivalent local path
1178  objPath = localObjectPath
1179  (
1180  io,
1181  searchType,
1182  procsDir,
1183  newInstancePath
1184  );
1185  }
1186  break;
1187 
1188  case fileOperation::OBJECT:
1190  {
1191  // Retest all processors separately since some processors might
1192  // have the file and some not (e.g. lagrangian data)
1193 
1194  objPath = masterOp<fileName>
1195  (
1196  io.objectPath(),
1197  fileOrNullOp(true), // isFile=true
1199  comm_
1200  );
1201  }
1202  break;
1203  }
1204  }
1205 
1206  if (debug)
1207  {
1208  Pout<< "masterUncollatedFileOperation::filePath :"
1209  << " Returning from file searching using type "
1210  << fileOperation::pathTypeNames_[searchType] << endl
1211  << " objectPath:" << io.objectPath() << endl
1212  << " filePath :" << objPath << endl << endl;
1213  }
1214  return objPath;
1215 }
1216 
1217 
1219 (
1220  const bool checkGlobal,
1221  const IOobject& io,
1222  const bool search
1223 ) const
1224 {
1225  if (debug)
1226  {
1227  Pout<< "masterUncollatedFileOperation::dirPath :"
1228  << " objectPath:" << io.objectPath()
1229  << " checkGlobal:" << checkGlobal
1230  << " parRun:" << Pstream::parRun()
1231  << " localmaster:" << Pstream::master(comm_) << endl;
1232  }
1233 
1234  // Now that we have an IOobject path use it to detect & cache
1235  // processor directory naming
1236  const refPtr<dirIndexList> pDirs(lookupProcessorsPath(io.objectPath()));
1237 
1238  // Trigger caching of times
1239  if (cacheLevel() > 0)
1240  {
1241  (void)findTimes(io.time().path(), io.time().constant());
1242  }
1243 
1244  // Determine master dirPath and broadcast
1245 
1246  fileName objPath;
1247  pathType searchType = NOTFOUND;
1248  word procsDir;
1249  word newInstancePath;
1250 
1251  // Local IO node searches for file
1252  if (Pstream::master(comm_))
1253  {
1254  const bool oldParRun = UPstream::parRun(false);
1255  const int oldCache = fileOperation::cacheLevel(0);
1256  const label oldNProcs = fileOperation::nProcs();
1257 
1258  objPath = filePathInfo
1259  (
1260  checkGlobal,
1261  false,
1262  io,
1263  pDirs,
1264  search,
1265  searchType,
1266  procsDir,
1267  newInstancePath
1268  );
1269 
1270  const_cast<masterUncollatedFileOperation&>(*this).nProcs(oldNProcs);
1271  fileOperation::cacheLevel(oldCache);
1272  UPstream::parRun(oldParRun);
1273 
1274  if (debug)
1275  {
1276  Pout<< "masterUncollatedFileOperation::dirPath :"
1277  << " master objPath:" << objPath
1278  << " searchType:" << fileOperation::pathTypeNames_[searchType]
1279  << " procsDir:" << procsDir << " instance:" << newInstancePath
1280  << endl;
1281  }
1282  }
1283 
1284 
1285  // Broadcast information about where the master found the object
1286  // Note: use the worldComm to make sure all processors decide
1287  // the same type. Only procsDir is allowed to differ; searchType
1288  // and instance have to be same
1289  if (UPstream::parRun())
1290  {
1291  int masterType(searchType);
1292  Pstream::broadcasts(UPstream::worldComm, masterType, newInstancePath);
1293  searchType = pathType(masterType);
1294  }
1295 
1296 
1297  if
1298  (
1299  checkGlobal
1300  || searchType == fileOperation::PARENTOBJECT
1301  || searchType == fileOperation::PROCBASEOBJECT
1302  || searchType == fileOperation::PROCBASEINSTANCE
1303  || io.local() == "uniform"
1304  )
1305  {
1306  // Distribute master path. This makes sure it is seen as uniform
1307  // and only gets read from the master.
1308  Pstream::broadcasts(UPstream::worldComm, objPath, procsDir);
1309  }
1310  else
1311  {
1312  // Broadcast local processors dir amongst all local nodes
1313  Pstream::broadcast(procsDir, comm_);
1314 
1315  // Use the master type to determine if additional information is
1316  // needed to construct the local equivalent
1317  switch (searchType)
1318  {
1322  {
1323  // Already handled above
1324  }
1325  break;
1326 
1334  {
1335  // Construct equivalent local path
1336  objPath = localObjectPath
1337  (
1338  io,
1339  searchType,
1340  procsDir,
1341  newInstancePath
1342  );
1343  }
1344  break;
1345 
1346  case fileOperation::OBJECT:
1348  {
1349  // Retest all processors separately since some processors might
1350  // have the file and some not (e.g. lagrangian data)
1351 
1352  objPath = masterOp<fileName>
1353  (
1354  io.objectPath(),
1355  fileOrNullOp(false), // isFile=false
1357  comm_
1358  );
1359  }
1360  break;
1361  }
1362  }
1363 
1364  if (debug)
1365  {
1366  Pout<< "masterUncollatedFileOperation::dirPath :"
1367  << " Returning from directory searching using type "
1368  << fileOperation::pathTypeNames_[searchType] << endl
1369  << " objectPath:" << io.objectPath() << endl
1370  << " filePath :" << objPath << endl << endl;
1371  }
1372  return objPath;
1373 }
1374 
1375 
1377 (
1378  const dirIndexList& pDirs,
1379  IOobject& io
1380 ) const
1381 {
1382  // Cut-down version of filePathInfo that does not look for
1383  // different instance or parent directory
1384 
1385  const bool isFile = !io.name().empty();
1386 
1387  // Generate output filename for object
1388  const fileName writePath(objectPath(io, word::null));
1389 
1390  // 1. Test writing name for either directory or a (valid) file
1391  if (isFileOrDir(isFile, writePath))
1392  {
1393  return true;
1394  }
1395 
1396  // 2. Check processors/
1397  if (io.time().processorCase())
1398  {
1399  for (const dirIndex& dirIdx : pDirs)
1400  {
1401  const fileName& pDir = dirIdx.first();
1402  fileName procPath =
1403  processorsPath(io, io.instance(), pDir)
1404  /io.name();
1405  if (procPath != writePath && isFileOrDir(isFile, procPath))
1406  {
1407  return true;
1408  }
1409  }
1410  }
1411 
1412  // 3. Check local
1413  fileName localPath = io.objectPath();
1414 
1415  if (localPath != writePath && isFileOrDir(isFile, localPath))
1416  {
1417  return true;
1418  }
1419 
1420  return false;
1421 }
1422 
1423 
1426 (
1427  const IOobject& startIO,
1428  const scalar startValue,
1429  const word& stopInstance,
1430  const bool constant_fallback
1431 ) const
1432 {
1433  if (debug)
1434  {
1435  Pout<< "masterUncollatedFileOperation::findInstance :"
1436  << " Starting searching for name:" << startIO.name()
1437  << " local:" << startIO.local()
1438  << " from instance:" << startIO.instance()
1439  << endl;
1440  }
1441 
1442  const Time& time = startIO.time();
1443  IOobject io(startIO);
1444 
1445  // Note: - if name is empty, just check the directory itself
1446  // - check both for isFile and headerOk since the latter does a
1447  // filePath so searches for the file.
1448  // - check for an object with local file scope (so no looking up in
1449  // parent directory in case of parallel)
1450 
1451 
1452  const refPtr<dirIndexList> pDirs(lookupProcessorsPath(io.objectPath()));
1453 
1454  word foundInstance;
1455 
1456  // if (Pstream::master(comm_))
1458  {
1459  const bool oldParRun = UPstream::parRun(false);
1460  const int oldCache = fileOperation::cacheLevel(0);
1461  const label oldNProcs = fileOperation::nProcs();
1462 
1463  if (exists(pDirs, io))
1464  {
1465  foundInstance = io.instance();
1466  }
1467  const_cast<masterUncollatedFileOperation&>(*this).nProcs(oldNProcs);
1468  fileOperation::cacheLevel(oldCache);
1469  UPstream::parRun(oldParRun);
1470  }
1471 
1472 
1473  // Do parallel early exit to avoid calling time.times()
1474  Pstream::broadcast(foundInstance, UPstream::worldComm);
1475 
1476  if (!foundInstance.empty())
1477  {
1478  io.instance() = foundInstance;
1479  if (debug)
1480  {
1481  Pout<< "masterUncollatedFileOperation::findInstance :"
1482  << " for name:" << io.name() << " local:" << io.local()
1483  << " found starting instance:" << io.instance() << endl;
1484  }
1485  return io;
1486  }
1487 
1488 
1489  // Handling failures afterwards
1490  const bool exitIfMissing = startIO.isReadRequired();
1491 
1492  enum failureCodes { FAILED_STOPINST = 1, FAILED_CONSTINST = 2 };
1493  int failed(0);
1494 
1495  instantList ts = time.times();
1496 
1497  // if (Pstream::master(comm_))
1499  {
1500  const bool oldParRun = UPstream::parRun(false);
1501  const int oldCache = fileOperation::cacheLevel(0);
1502  const label oldNProcs = fileOperation::nProcs();
1503 
1504  label instIndex = ts.size()-1;
1505 
1506  // Backward search for first time that is <= startValue
1507  for (; instIndex >= 0; --instIndex)
1508  {
1509  if (ts[instIndex].value() <= startValue)
1510  {
1511  break;
1512  }
1513  }
1514 
1515  // Continue (forward) searching from here
1516  for (; instIndex >= 0; --instIndex)
1517  {
1518  // Shortcut: if actual directory is the timeName we've
1519  // already tested it
1520  if (ts[instIndex].name() == time.timeName())
1521  {
1522  continue;
1523  }
1524 
1525  io.instance() = ts[instIndex].name();
1526  if (exists(pDirs, io))
1527  {
1528  foundInstance = io.instance();
1529  if (debug)
1530  {
1531  Pout<< "masterUncollatedFileOperation::findInstance :"
1532  << " for name:" << io.name() << " local:" << io.local()
1533  << " found at:" << io.instance()
1534  << endl;
1535  }
1536  break;
1537  }
1538 
1539  // Check if hit minimum instance
1540  if (io.instance() == stopInstance)
1541  {
1542  if (debug)
1543  {
1544  Pout<< "masterUncollatedFileOperation::findInstance :"
1545  << " name:" << io.name()
1546  << " local:" << io.local()
1547  << " at stop-instance:" << io.instance() << endl;
1548  }
1549 
1550  if (exitIfMissing)
1551  {
1552  failed = failureCodes::FAILED_STOPINST;
1553  }
1554  else
1555  {
1556  // At the stopInstance
1557  foundInstance = io.instance();
1558  }
1559  break;
1560  }
1561  }
1562 
1563 
1564  // times() usually already includes the constant() so would
1565  // have been checked above. However, re-test under these conditions:
1566  // - times() is empty. Sometimes this can happen (e.g. decomposePar
1567  // with collated)
1568  // - times()[0] is not constant
1569  // - Times is empty.
1570  // Sometimes this can happen (eg, decomposePar with collated)
1571  // - Times[0] is not constant
1572  // - The startValue is negative (eg, kivaTest).
1573  // This plays havoc with the reverse search, causing it to miss
1574  // 'constant'
1575 
1576  if
1577  (
1578  !failed && foundInstance.empty()
1579  && (ts.empty() || ts[0].name() != time.constant() || startValue < 0)
1580  )
1581  {
1582  // Note. This needs to be a hard-coded "constant" (not constant
1583  // function of Time), because the latter points to
1584  // the case constant directory in parallel cases.
1585  // However, parRun is disabled so they are actually the same.
1586 
1587  io.instance() = time.constant();
1588 
1589  if (exists(pDirs, io))
1590  {
1591  if (debug)
1592  {
1593  Pout<< "masterUncollatedFileOperation::findInstance :"
1594  << " name:" << io.name()
1595  << " local:" << io.local()
1596  << " at:" << io.instance() << endl;
1597  }
1598  foundInstance = io.instance();
1599  }
1600  }
1601 
1602  if (!failed && foundInstance.empty())
1603  {
1604  if (exitIfMissing)
1605  {
1606  failed = failureCodes::FAILED_CONSTINST;
1607  }
1608  else if (constant_fallback)
1609  {
1610  foundInstance = time.constant();
1611  }
1612  else
1613  {
1614  foundInstance.clear();
1615  }
1616  }
1617 
1618  const_cast<masterUncollatedFileOperation&>(*this).nProcs(oldNProcs);
1619  fileOperation::cacheLevel(oldCache);
1620  UPstream::parRun(oldParRun); // Restore parallel state
1621  }
1622 
1623  Pstream::broadcast(foundInstance, UPstream::worldComm);
1624 
1625  io.instance() = foundInstance;
1626 
1627 
1628  // Handle failures
1629  // ~~~~~~~~~~~~~~~
1630  if (failed)
1631  {
1632  FatalErrorInFunction << "Cannot find";
1633 
1634  if (!io.name().empty())
1635  {
1636  FatalError
1637  << " file \"" << io.name() << "\" in";
1638  }
1639 
1640  FatalError
1641  << " directory "
1642  << io.local() << " in times "
1643  << startIO.instance() << " down to ";
1644 
1645  if (failed == failureCodes::FAILED_STOPINST)
1646  {
1647  FatalError << stopInstance;
1648  }
1649  else // FAILED_CONSTINST
1650  {
1651  FatalError << "constant";
1652  }
1654  }
1655 
1656  if (debug)
1657  {
1658  Pout<< "masterUncollatedFileOperation::findInstance :"
1659  << " name:" << io.name() << " local:" << io.local()
1660  << " returning instance:" << io.instance() << endl;
1661  }
1662  return io;
1663 }
1664 
1665 
1668 (
1669  const objectRegistry& db,
1670  const fileName& instance,
1671  const fileName& local,
1672  word& newInstance
1673 ) const
1674 {
1675  if (debug)
1676  {
1677  Pout<< "masterUncollatedFileOperation::readObjects :"
1678  << " db:" << db.objectPath()
1679  << " local:" << local << " instance:" << instance << endl;
1680  }
1681 
1682  fileNameList objectNames;
1683  newInstance.clear();
1684 
1685  // Note: readObjects uses WORLD to make sure order of objects is the
1686  // same everywhere
1687 
1689  {
1690  // Avoid fileOperation::readObjects from triggering parallel ops
1691  // (through call to filePath which triggers parallel )
1692  const bool oldParRun = UPstream::parRun(false);
1693  const int oldCache = fileOperation::cacheLevel(0);
1694  const label oldNProcs = fileOperation::nProcs();
1695 
1696  //- Use non-time searching version
1697  objectNames = fileOperation::readObjects
1698  (
1699  db,
1700  instance,
1701  local,
1702  newInstance
1703  );
1704 
1705  if (newInstance.empty())
1706  {
1707  // Find similar time
1708 
1709  // Copy of Time::findInstancePath. We want to avoid the
1710  // parallel call to findTimes.
1711  const instantList timeDirs
1712  (
1714  (
1715  db.time().path(),
1716  db.time().constant()
1717  )
1718  );
1719 
1720  fileName foundInst
1721  (
1722  Time::findInstancePath(timeDirs, instant(instance))
1723  );
1724 
1725  if (!foundInst.empty())
1726  {
1727  objectNames = fileOperation::readObjects
1728  (
1729  db,
1730  foundInst, // newly found time
1731  local,
1732  newInstance
1733  );
1734  }
1735  }
1736 
1737  const_cast<masterUncollatedFileOperation&>(*this).nProcs(oldNProcs);
1738  fileOperation::cacheLevel(oldCache);
1739  UPstream::parRun(oldParRun); // Restore parallel state
1740  }
1741 
1742  Pstream::broadcasts(UPstream::worldComm, newInstance, objectNames);
1743 
1744  if (debug)
1745  {
1746  Pout<< "masterUncollatedFileOperation::readObjects :"
1747  << " newInstance:" << newInstance
1748  << " objectNames:" << objectNames << endl;
1749  }
1751  return objectNames;
1752 }
1753 
1754 
1756 (
1757  IOobject& io,
1758  const fileName& fName,
1759  const word& typeName
1760 ) const
1761 {
1762  bool ok = false;
1763 
1764  if (debug)
1765  {
1766  Pout<< "masterUncollatedFileOperation::readHeader :" << endl
1767  << " objectPath:" << io.objectPath() << endl
1768  << " filePath :" << fName << endl;
1769  }
1770 
1771  // We assume if filePath is the same
1772  // - headerClassName
1773  // - note
1774  // are also the same, independent of where the file came from.
1775 
1776  // Get filePaths on world master
1778  filePaths[UPstream::myProcNo(UPstream::worldComm)] = fName;
1780 
1781  bool uniform
1782  (
1784  && fileOperation::uniformFile(filePaths)
1785  );
1786 
1788 
1789  if (uniform)
1790  {
1792  {
1793  if (!fName.empty())
1794  {
1795  IFstream is(fName);
1796 
1797  if (is.good())
1798  {
1799  // Regular header or from decomposed data
1801  }
1802  }
1803  }
1804 
1806  (
1808  ok,
1809  io.headerClassName(),
1810  io.note()
1811  );
1812  }
1813  else
1814  {
1816  {
1817  // Assume if different nprocs the communicators are also
1818  // different. Re-gather file paths on local master
1819  filePaths.resize(UPstream::nProcs(comm_));
1820  filePaths[UPstream::myProcNo(comm_)] = fName;
1821  Pstream::gatherList(filePaths, UPstream::msgType(), comm_);
1822  }
1823 
1824  // Intermediate storage arrays (master only)
1825  boolList result;
1826  wordList headerClassName;
1827  stringList note;
1828 
1829  if (Pstream::master(comm_))
1830  {
1831  const label np = Pstream::nProcs(comm_);
1832 
1833  result.resize(np, false);
1834  headerClassName.resize(np);
1835  note.resize(np);
1836 
1837  forAll(filePaths, proci)
1838  {
1839  if (!filePaths[proci].empty())
1840  {
1841  if (proci > 0 && filePaths[proci] == filePaths[proci-1])
1842  {
1843  result[proci] = result[proci-1];
1844  headerClassName[proci] = headerClassName[proci-1];
1845  note[proci] = note[proci-1];
1846  }
1847  else
1848  {
1849  IFstream is(filePaths[proci]);
1850 
1851  if (is.good())
1852  {
1853  result[proci] =
1855  headerClassName[proci] = io.headerClassName();
1856  note[proci] = io.note();
1857  }
1858  }
1859  }
1860  }
1861  }
1862 
1863  // Is a more efficient scatter possible?
1864  PstreamBuffers pBufs(comm_);
1865 
1866  if (Pstream::master(comm_))
1867  {
1868  ok = result[0];
1869  io.headerClassName() = headerClassName[0];
1870  io.note() = note[0];
1871 
1872  // Scatter to each proc
1873  for (const int proci : pBufs.subProcs())
1874  {
1875  UOPstream os(proci, pBufs);
1876  os << result[proci] << headerClassName[proci] << note[proci];
1877  }
1878  }
1879 
1880  pBufs.finishedScatters();
1881 
1882  if (!Pstream::master(comm_))
1883  {
1884  UIPstream is(Pstream::masterNo(), pBufs);
1885  is >> ok >> io.headerClassName() >> io.note();
1886  }
1887  }
1888 
1889  if (debug)
1890  {
1891  Pout<< "masterUncollatedFileOperation::readHeader :" << " ok:" << ok
1892  << " class:" << io.headerClassName()
1893  << " for file:" << fName << endl;
1894  }
1895  return ok;
1896 }
1897 
1898 
1901 (
1902  regIOobject& io,
1903  const fileName& fName,
1904  const word& typeName,
1905  const bool readOnProc
1906 ) const
1907 {
1908  if (debug)
1909  {
1910  Pout<< "masterUncollatedFileOperation::readStream :"
1911  << " object : " << io.name()
1912  << " global : " << io.global()
1913  << " globalObject : " << io.globalObject()
1914  << " fName : " << fName << " readOnProc:" << readOnProc << endl;
1915  }
1916 
1917  // Close old stream
1918  io.close();
1919 
1920  autoPtr<ISstream> isPtr;
1921  bool isCollated = false;
1922  IOobject headerIO(io);
1923 
1924  // Detect collated format. This could be done on the local communicator
1925  // but we do it on the master node only for now.
1927  {
1928  if (!fName.empty())
1929  {
1930  // This can happen in lagrangian field reading some processors
1931  // have no file to read from. This will only happen when using
1932  // normal writing since then the fName for the valid processors is
1933  // processorDDD/<instance>/.. . In case of collocated writing
1934  // the fName is already rewritten to processorsNN/.
1935 
1936  isPtr.reset(new IFstream(fName));
1937 
1938  if (isPtr->good())
1939  {
1940  // Read header data (on copy)
1941  headerIO.readHeader(*isPtr);
1942 
1943  isCollated = decomposedBlockData::isCollatedType(headerIO);
1944 
1945  if (!isCollated && !Pstream::parRun())
1946  {
1947  // Short circuit: non-collated format. No parallel bits.
1948  // Copy header and return.
1949  if (debug)
1950  {
1951  Pout<< "masterUncollatedFileOperation::readStream :"
1952  << " For object : " << io.name()
1953  << " doing straight IFstream input from "
1954  << fName << endl;
1955  }
1956 
1957  // Copy IOobject header information
1958  io.IOobject::operator=(headerIO);
1959  return isPtr;
1960  }
1961  }
1962 
1963  if (!isCollated)
1964  {
1965  // Close file. Reopened below.
1966  isPtr.clear();
1967  }
1968  }
1969  }
1970 
1972 
1973  if (isCollated)
1974  {
1975  if (debug)
1976  {
1977  Pout<< "masterUncollatedFileOperation::readStream :"
1978  << " For object : " << io.name()
1979  << " starting collating input from " << fName << endl;
1980  }
1981 
1982 
1983  // Analyse the file path (on (co)master) to see the processors type
1984  // Note: this should really be part of filePath() which should return
1985  // both file and index in file.
1986 
1987  fileName path, procDir, local;
1988  procRangeType group;
1989  label nProcs;
1990  splitProcessorPath(fName, path, procDir, local, group, nProcs);
1991 
1992 
1993  if (!UPstream::parRun())
1994  {
1995  // Analyse the objectpath to find out the processor we're trying
1996  // to access
1997  label proci = detectProcessorPath(io.objectPath());
1998 
1999  if (proci == -1)
2000  {
2001  FatalIOErrorInFunction(*isPtr)
2002  << "Could not detect processor number"
2003  << " from objectPath:" << io.objectPath()
2004  << " fileHandler : comm:" << comm_
2005  << " ioRanks:" << flatOutput(ioRanks_)
2006  << exit(FatalIOError);
2007  }
2008 
2009  // The local rank (offset)
2010  if (!group.empty())
2011  {
2012  proci = proci - group.start();
2013  }
2014 
2015  if (debug)
2016  {
2017  Pout<< "masterUncollatedFileOperation::readStream :"
2018  << " For object : " << io.name()
2019  << " starting input from block " << proci
2020  << " of " << isPtr->name() << endl;
2021  }
2022 
2023  return decomposedBlockData::readBlock(proci, *isPtr, io);
2024  }
2025  else
2026  {
2027  // Are we reading from single-master file ('processors256') or
2028  // from multi-master files ('processors256_0-9')
2029  label readComm = -1;
2030  if (!group.empty())
2031  {
2032  readComm = comm_;
2033  if (UPstream::master(comm_) && !isPtr && !fName.empty())
2034  {
2035  // In multi-master mode also open the file on the other
2036  // masters
2037  isPtr.reset(new IFstream(fName));
2038 
2039  if (isPtr->good())
2040  {
2041  // Read header data (on copy)
2042  IOobject headerIO(io);
2043  headerIO.readHeader(*isPtr);
2044  }
2045  }
2046  }
2047  else
2048  {
2049  // Single master so read on world
2050  readComm = UPstream::worldComm;
2051  }
2052 
2053  // Get size of file to determine communications type
2054  bool bigSize = false;
2055 
2057  {
2058  // TBD: handle multiple masters?
2059  bigSize =
2060  (
2061  off_t(Foam::fileSize(fName))
2062  > off_t(maxMasterFileBufferSize)
2063  );
2064  }
2065  // Reduce (not broadcast)
2066  // - if we have multiple master files (FUTURE)
2068 
2069  const UPstream::commsTypes myCommsType
2070  (
2071  bigSize
2074  );
2075 
2076  // Read my data
2078  (
2079  readComm,
2080  fName,
2081  isPtr,
2082  io,
2083  myCommsType
2084  );
2085  }
2086  }
2087  else
2088  {
2089  if (debug)
2090  {
2091  Pout<< "masterUncollatedFileOperation::readStream :"
2092  << " For object : " << io.name()
2093  << " starting separated input from " << fName << endl;
2094  }
2095 
2096  if (io.global() || io.globalObject())
2097  {
2098  // Use worldComm. Note: should not really need to gather filePaths
2099  // since we enforce sending from master anyway ...
2101  filePaths[UPstream::myProcNo(UPstream::worldComm)] = fName;
2103  (
2104  filePaths,
2107  );
2108 
2109  boolList readOnProcs
2110  (
2111  UPstream::listGatherValues<bool>
2112  (
2113  readOnProc,
2115  )
2116  );
2117  // NB: local proc validity information required on sub-ranks too!
2118  readOnProcs.resize(UPstream::nProcs(UPstream::worldComm));
2119  readOnProcs[UPstream::myProcNo(UPstream::worldComm)] = readOnProc;
2120 
2121  // Uniform in local comm
2122  return read(io, UPstream::worldComm, true, filePaths, readOnProcs);
2123  }
2124  else
2125  {
2126  // Use local communicator
2127  fileNameList filePaths(UPstream::nProcs(comm_));
2128  filePaths[UPstream::myProcNo(comm_)] = fName;
2130  (
2131  filePaths,
2133  comm_
2134  );
2135 
2136  boolList readOnProcs
2137  (
2138  UPstream::listGatherValues<bool>
2139  (
2140  readOnProc,
2141  comm_
2142  )
2143  );
2144  // NB: local proc validity information required on sub-ranks too!
2145  readOnProcs.resize(UPstream::nProcs(comm_));
2146  readOnProcs[UPstream::myProcNo(comm_)] = readOnProc;
2147 
2148  // Uniform in local comm
2149  const bool uniform = fileOperation::uniformFile(filePaths);
2150 
2151  return read(io, comm_, uniform, filePaths, readOnProcs);
2152  }
2153  }
2154 }
2155 
2156 
2158 (
2159  regIOobject& io,
2160  const bool masterOnly,
2162  const word& typeName
2163 ) const
2164 {
2165  bool ok = true;
2166 
2167  if (io.global() || io.globalObject())
2168  {
2169  if (debug)
2170  {
2171  Pout<< "masterUncollatedFileOperation::read :"
2172  << " Reading global object " << io.name()
2173  << " worldComm:" << UPstream::worldComm
2174  << " Pstream::myProcNo:"
2176  << " amMaster:" << Pstream::master(UPstream::worldComm)
2177  << endl;
2178  }
2179 
2181  {
2182  // Do master-only reading always.
2183  const bool oldParRun = UPstream::parRun(false);
2184  const int oldCache = fileOperation::cacheLevel(0);
2185  const label oldNProcs = fileOperation::nProcs();
2186 
2187  auto& is = io.readStream(typeName);
2188  ok = io.readData(is);
2189  io.close();
2190 
2191  const_cast<masterUncollatedFileOperation&>(*this).nProcs(oldNProcs);
2192  fileOperation::cacheLevel(oldCache);
2193  UPstream::parRun(oldParRun); // Restore parallel state
2194  }
2195 
2196  // Broadcast regIOobject content, with writeData/readData handling
2197  if (UPstream::parRun())
2198  {
2200  {
2201  OPBstream os(UPstream::worldComm, format);
2202 
2203  os << io.headerClassName() << io.note();
2204  bool okWrite = io.writeData(os);
2205  ok = ok && okWrite;
2206  }
2207  else
2208  {
2209  IPBstream is(UPstream::worldComm, format);
2210 
2211  is >> io.headerClassName() >> io.note();
2212  ok = io.readData(is);
2213  }
2214  }
2215  }
2216  else
2217  {
2218  if (debug)
2219  {
2220  Pout<< "masterUncollatedFileOperation::read :"
2221  << " Reading local object " << io.name() << endl;
2222  }
2223 
2224  ok = io.readData(io.readStream(typeName));
2225  io.close();
2226  }
2227 
2228  if (debug)
2229  {
2230  Pout<< "masterUncollatedFileOperation::read :"
2231  << " Read object:" << io.name()
2232  << " isGlobal:" << (io.global() || io.globalObject())
2233  << " status:" << ok << endl;
2234  }
2236  return ok;
2237 }
2238 
2239 
2241 (
2242  const regIOobject& io,
2243  IOstreamOption streamOpt,
2244  const bool writeOnProc
2245 ) const
2246 {
2247  fileName pathName(io.objectPath());
2248 
2249  if (debug)
2250  {
2251  Pout<< "masterUncollatedFileOperation::writeObject :"
2252  << " io:" << pathName << " writeOnProc:" << writeOnProc << endl;
2253  }
2254 
2255  // Make sure to pick up any new times
2256  setTime(io.time());
2257 
2258  // Update meta-data for current state
2259  const_cast<regIOobject&>(io).updateMetaData();
2260 
2261  autoPtr<OSstream> osPtr(NewOFstream(pathName, streamOpt, writeOnProc));
2262  OSstream& os = *osPtr;
2263 
2264  // If any of these fail, return (leave error handling to Ostream class)
2265 
2266  const bool ok =
2267  (
2268  os.good()
2269  && io.writeHeader(os)
2270  && io.writeData(os)
2271  );
2272 
2273  if (ok)
2274  {
2276  }
2278  return ok;
2279 }
2280 
2281 
2283 (
2284  const fileName& directory,
2285  const word& constantName
2286 ) const
2287 {
2288  const auto iter = times_.cfind(directory);
2289  if (iter.good())
2290  {
2291  if (debug)
2292  {
2293  Pout<< "masterUncollatedFileOperation::findTimes :"
2294  << " Found " << iter.val()->size() << " cached times" << nl
2295  << " for directory:" << directory << endl;
2296  }
2297  return *(iter.val());
2298  }
2299  else
2300  {
2301  instantList times;
2303  {
2304  // Do master-only reading always.
2305  const bool oldParRun = UPstream::parRun(false);
2306  const int oldCache = fileOperation::cacheLevel(0);
2307  const label oldNProcs = fileOperation::nProcs();
2308 
2309  times = fileOperation::findTimes(directory, constantName);
2310 
2311  const_cast<masterUncollatedFileOperation&>(*this).nProcs(oldNProcs);
2312  fileOperation::cacheLevel(oldCache);
2313  UPstream::parRun(oldParRun); // Restore parallel state
2314  }
2315 
2317 
2318  if (debug)
2319  {
2320  Pout<< "masterUncollatedFileOperation::findTimes :"
2321  << " Found times:" << flatOutput(times) << nl
2322  << " for directory:" << directory << endl;
2323  }
2324 
2325  // Caching
2326  // - cache values even if no times were found since it might
2327  // indicate a directory that is being filled later on ...
2328  if (cacheLevel() > 0)
2329  {
2330  auto* tPtr = new DynamicList<instant>(std::move(times));
2331  times_.set(directory, tPtr);
2332 
2333  return *tPtr;
2334  }
2335 
2336  // Times found (not cached)
2337  return times;
2338  }
2339 }
2340 
2341 
2343 (
2344  const Time& tm
2345 ) const
2346 {
2347  if (tm.subCycling())
2348  {
2349  return;
2350  }
2351 
2352  // Mutable access to instant list for modification and sorting
2353  // - cannot use auto type deduction here
2354 
2355  auto iter = times_.find(tm.path());
2356 
2357  if (iter.good())
2358  {
2359  DynamicList<instant>& times = *(iter.val());
2360 
2361  const instant timeNow(tm.value(), tm.timeName());
2362 
2363  // The start index for checking and sorting (excluding "constant")
2364  const label startIdx =
2365  (
2366  (times.empty() || times[0].name() != tm.constant())
2367  ? 0
2368  : 1
2369  );
2370 
2371  // This routine always results in a sorted list of times, so first
2372  // check if the new time is greater than the latest existing time.
2373  // Can then simply append without extra searching or sorting
2374 
2375  if (times.size() <= startIdx || times.last() < timeNow)
2376  {
2377  times.append(timeNow);
2378  }
2379  else if
2380  (
2382  (
2383  SubList<instant>(times, times.size()-startIdx, startIdx),
2384  timeNow
2385  ) < 0
2386  )
2387  {
2388  if (debug)
2389  {
2390  Pout<< "masterUncollatedFileOperation::setTime :"
2391  << " Caching time " << tm.timeName()
2392  << " for case:" << tm.path() << endl;
2393  }
2394 
2395  times.append(timeNow);
2396 
2397  SubList<instant> realTimes
2398  (
2399  times, times.size()-startIdx, startIdx
2400  );
2401  Foam::stableSort(realTimes);
2402  }
2403  }
2404 
2406 }
2407 
2408 
2411 (
2412  const fileName& filePath
2413 ) const
2414 {
2415  autoPtr<ISstream> isPtr;
2416 
2417  if (Pstream::parRun())
2418  {
2419  // Insert logic of filePath. We assume that if a file is absolute
2420  // on the master it is absolute also on the sub-ranks etc.
2421 
2422  fileNameList filePaths(Pstream::nProcs(comm_));
2423  filePaths[Pstream::myProcNo(comm_)] = filePath;
2424  Pstream::gatherList(filePaths, Pstream::msgType(), comm_);
2425 
2426  PstreamBuffers pBufs(comm_);
2427 
2428  if (Pstream::master(comm_))
2429  {
2430  // Same filename on the IO node -> same file
2431  const bool uniform = fileOperation::uniformFile(filePaths);
2432 
2433  if (uniform)
2434  {
2435  if (debug)
2436  {
2437  Pout<< "masterUncollatedFileOperation::NewIFstream :"
2438  << " Opening global file " << filePath << endl;
2439  }
2440 
2441  readAndSend
2442  (
2443  filePath,
2444  identity(Pstream::nProcs(comm_)-1, 1),
2445  pBufs
2446  );
2447  }
2448  else
2449  {
2450  for (const int proci : Pstream::subProcs(comm_))
2451  {
2452  if (debug)
2453  {
2454  Pout<< "masterUncollatedFileOperation::NewIFstream :"
2455  << " Opening local file " << filePath
2456  << " for rank " << proci << endl;
2457  }
2458 
2459  readAndSend
2460  (
2461  filePaths[proci],
2462  labelList(one{}, proci),
2463  pBufs
2464  );
2465  }
2466  }
2467  }
2468 
2469 
2470  pBufs.finishedSends();
2471 
2472  if (Pstream::master(comm_))
2473  {
2474  // Read myself
2475  isPtr.reset(new IFstream(filePaths[Pstream::masterNo()]));
2476  }
2477  else
2478  {
2479  if (debug)
2480  {
2481  Pout<< "masterUncollatedFileOperation::NewIFstream :"
2482  << " Reading " << filePath
2483  << " from processor " << Pstream::masterNo() << endl;
2484  }
2485 
2486  List<char> buf(pBufs.recvDataCount(Pstream::masterNo()));
2487 
2488  if (!buf.empty())
2489  {
2490  UIPstream is(Pstream::masterNo(), pBufs);
2491  is.read(buf.data(), buf.size());
2492  }
2493 
2494  if (debug)
2495  {
2496  Pout<< "masterUncollatedFileOperation::NewIFstream :"
2497  << " Done reading " << buf.size() << " bytes" << endl;
2498  }
2499 
2500  // A local character buffer copy of the Pstream contents.
2501  // Construct with same parameters (ASCII, current version)
2502  // as the IFstream so that it has the same characteristics.
2503 
2504  isPtr.reset(new ICharStream(std::move(buf)));
2505 
2506  // With the proper file name
2507  isPtr->name() = filePath;
2508  }
2509  }
2510  else
2511  {
2512  // Read myself
2513  isPtr.reset(new IFstream(filePath));
2514  }
2515 
2516  return isPtr;
2517 }
2518 
2519 
2522 (
2523  const fileName& pathName,
2524  IOstreamOption streamOpt,
2525  const bool writeOnProc
2526 ) const
2527 {
2528  return autoPtr<OSstream>
2529  (
2530  new masterOFstream
2531  (
2532  comm_,
2533  pathName,
2534  streamOpt,
2536  writeOnProc
2537  )
2538  );
2539 }
2540 
2541 
2544 (
2546  const fileName& pathName,
2547  IOstreamOption streamOpt,
2548  const bool writeOnProc
2549 ) const
2550 {
2551  return autoPtr<OSstream>
2552  (
2553  new masterOFstream
2554  (
2555  atomic,
2556  comm_,
2557  pathName,
2558  streamOpt,
2560  writeOnProc
2561  )
2562  );
2563 }
2564 
2565 
2567 {
2569  times_.clear();
2570 }
2571 
2572 
2574 {
2575  if (debug)
2576  {
2577  Pout<< "masterUncollatedFileOperation::sync :"
2578  << " syncing information across processors" << endl;
2579  }
2580 
2582 
2583 
2584  wordList timeNames;
2585  List<DynamicList<instant>> instants;
2586 
2588  {
2589  timeNames.resize(times_.size());
2590  instants.resize(times_.size());
2591 
2592  // Flatten into two lists to preserve key/val pairing
2593  label i = 0;
2594  forAllConstIters(times_, iter)
2595  {
2596  timeNames[i] = iter.key();
2597  instants[i] = std::move(*(iter.val()));
2598  ++i;
2599  }
2600  }
2601 
2602  Pstream::broadcasts(UPstream::worldComm, timeNames, instants);
2603 
2604  times_.clear();
2605  forAll(timeNames, i)
2606  {
2607  fileName dir(timeNames[i]);
2608  auto ptr = autoPtr<DynamicList<instant>>::New(std::move(instants[i]));
2609 
2611  {
2612  // Replace processor0 ending with processorDDD
2613  fileName path;
2614  fileName pDir;
2615  fileName local;
2616  procRangeType group;
2617  label numProcs;
2618  const label proci = splitProcessorPath
2619  (
2620  dir,
2621  path,
2622  pDir,
2623  local,
2624  group,
2625  numProcs
2626  );
2627 
2628  //Pout<< "**sync : From dir : " << dir << nl
2629  // << " path : " << path << nl
2630  // << " pDir : " << pDir << nl
2631  // << " local: " << local << nl
2632  // << " proci: " << proci << nl
2633  // << endl;
2634 
2635  const label myProci = Pstream::myProcNo(UPstream::worldComm);
2636 
2637  if (proci != -1 && proci != myProci)
2638  {
2639  dir = path/"processor" + Foam::name(myProci);
2640  }
2641  }
2642 
2643  times_.insert(dir, ptr);
2644  }
2645 }
2646 
2647 
2649 (
2650  const fileName& fName
2651 ) const
2652 {
2653  label watchFd = -1;
2655  {
2656  watchFd = monitor().addWatch(fName);
2657  }
2658 
2660  return watchFd;
2661 }
2662 
2663 
2665 (
2666  const label watchIndex
2667 ) const
2668 {
2669  bool ok = false;
2671  {
2672  ok = monitor().removeWatch(watchIndex);
2673  }
2674 
2676  return ok;
2677 }
2678 
2679 
2681 (
2682  const labelList& watchIndices,
2683  const fileName& fName
2684 ) const
2685 {
2686  label index = -1;
2687 
2689  {
2690  forAll(watchIndices, i)
2691  {
2692  if (monitor().getFile(watchIndices[i]) == fName)
2693  {
2694  index = i;
2695  break;
2696  }
2697  }
2698  }
2699 
2701  return index;
2702 }
2703 
2704 
2706 (
2707  regIOobject& rio,
2708  const fileNameList& files
2709 ) const
2710 {
2711  const labelList& watchIndices = rio.watchIndices();
2712 
2713  // Do on master and distribute effect to subprocs such that after
2714  // all have consistent numbering & files
2715 
2716  DynamicList<label> newWatchIndices;
2717  if (UPstream::master())
2718  {
2719  // Switch off comms inside findWatch/addWatch etc.
2720  const bool oldParRun = UPstream::parRun(false);
2721  const int oldCache = fileOperation::cacheLevel(0);
2722  const label oldNProcs = fileOperation::nProcs();
2723 
2724  labelHashSet removedWatches(watchIndices);
2725 
2726  for (const fileName& f : files)
2727  {
2728  const label index = findWatch(watchIndices, f);
2729 
2730  if (index == -1)
2731  {
2732  newWatchIndices.push_back(addWatch(f));
2733  }
2734  else
2735  {
2736  // Existing watch
2737  newWatchIndices.push_back(watchIndices[index]);
2738  removedWatches.erase(index);
2739  }
2740  }
2741 
2742  // Remove any unused watches
2743  for (const label index : removedWatches)
2744  {
2745  removeWatch(watchIndices[index]);
2746  }
2747 
2748  const_cast<masterUncollatedFileOperation&>(*this).nProcs(oldNProcs);
2749  fileOperation::cacheLevel(oldCache);
2750  UPstream::parRun(oldParRun);
2751  }
2752  Pstream::broadcast(newWatchIndices);
2754  rio.watchIndices() = newWatchIndices;
2755 }
2756 
2757 
2759 (
2760  const label watchIndex
2761 ) const
2762 {
2763  fileName fName;
2765  {
2766  fName = monitor().getFile(watchIndex);
2767  }
2768 
2770  return fName;
2771 }
2772 
2773 
2775 (
2776  const bool masterOnly,
2777  const bool syncPar
2778 ) const
2779 {
2781  {
2782  monitor().updateStates(true, false);
2783  }
2784 }
2785 
2786 
2789 (
2790  const label watchFd
2791 ) const
2792 {
2793  unsigned int state = fileMonitor::UNMODIFIED;
2795  {
2796  state = monitor().getState(watchFd);
2797  }
2798 
2800  return fileMonitor::fileState(state);
2801 }
2802 
2803 
2805 (
2806  const label watchFd
2807 ) const
2808 {
2810  {
2811  monitor().setUnmodified(watchFd);
2812  }
2813 }
2814 
2815 
2816 // ************************************************************************* //
Input/output streams with (internal or external) character storage.
Macros for easy insertion into run-time selection tables.
void push_back(const T &val)
Copy append an element to the end of this list.
Definition: DynamicListI.H:558
Input from file stream as an ISstream, normally using std::ifstream for the actual input.
Definition: IFstream.H:55
static DynamicList< char > readContents(const fileName &pathname)
Get file contents from specified file (compressed/uncompressed). Returns an empty list if the file ca...
Definition: IFstream.C:130
static bool isReadRequired(readOption opt) noexcept
True if (MUST_READ | READ_MODIFIED) bits are set.
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:183
const Time & time() const noexcept
Return Time associated with the objectRegistry.
Definition: IOobject.C:456
const word & name() const noexcept
Return the object name.
Definition: IOobjectI.H:195
static Ostream & writeEndDivider(Ostream &os)
Write the standard end file divider.
const fileName & local() const noexcept
Read access to local path component.
Definition: IOobjectI.H:278
const fileName & instance() const noexcept
Read access to instance path component.
Definition: IOobjectI.H:266
static fileCheckTypes fileModificationChecking
Type of file modification checking.
Definition: IOobject.H:351
fileName objectPath() const
The complete path + object name.
Definition: IOobjectI.H:284
A simple container for options an IOstream can normally have.
streamFormat
Data format (ascii | binary)
atomicType
Atomic operations (output)
@ NO_APPEND
no append (truncates existing)
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:150
Generic output stream using a standard (STL) stream.
Definition: OSstream.H:53
Buffers for inter-processor communications streams (UOPstream, UIPstream).
static void gatherList(UList< T > &values, const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm)
Gather data, but keep individual values separate.
static void broadcast(Type &value, const int communicator=UPstream::worldComm)
Broadcast content (contiguous or non-contiguous) to all communicator ranks. Does nothing in non-paral...
static void broadcasts(const int communicator, Type &value, Args &&... values)
Broadcast multiple items to all communicator ranks. Does nothing in non-parallel.
const word & constant() const noexcept
Return constant name.
Definition: TimePathsI.H:112
static word findInstancePath(const UList< instant > &timeDirs, const instant &t)
Search instantList for matching time value, return the instance name or word::null if nothing is equa...
Definition: TimePaths.C:125
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:76
fileName path() const
Return path = rootPath/caseName. Same as TimePaths::path()
Definition: Time.H:503
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:735
static word timeName(const scalar t, const int precision=precision_)
Return a time name for the given scalar time value formatted with the given precision.
Definition: Time.C:714
A 2-tuple for storing two objects of dissimilar types. The container is similar in purpose to std::pa...
Definition: Tuple2.H:51
const T2 & second() const noexcept
Access the second element.
Definition: Tuple2.H:142
const T1 & first() const noexcept
Access the first element.
Definition: Tuple2.H:132
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: UList.H:85
Output inter-processor communications stream using MPI send/recv etc. - operating on external buffer.
Definition: UOPstream.H:398
static int myProcNo(const label communicator=worldComm)
Rank of this process in the communicator (starting from masterNo()). Negative if the process is not a...
Definition: UPstream.H:1611
commsTypes
Communications types.
Definition: UPstream.H:78
@ scheduled
"scheduled" (MPI standard) : (MPI_Send, MPI_Recv)
@ nonBlocking
"nonBlocking" (immediate) : (MPI_Isend, MPI_Irecv)
static constexpr int masterNo() noexcept
Relative rank for the master process - is always 0.
Definition: UPstream.H:1596
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition: UPstream.H:1619
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:1586
static void reduceOr(bool &value, const int communicator=worldComm)
Logical (or) reduction (MPI_AllReduce)
static label nProcs(const label communicator=worldComm)
Number of ranks in parallel run (for given communicator). It is 1 for serial run.
Definition: UPstream.H:1602
static label worldComm
Communicator for all ranks. May differ from commGlobal() if local worlds are in use.
Definition: UPstream.H:987
static List< int > & procID(int communicator)
The list of ranks within a given communicator.
Definition: UPstream.H:1672
static rangeType allProcs(const label communicator=worldComm)
Range of process indices for all processes.
Definition: UPstream.H:1718
static rangeType subProcs(const label communicator=worldComm)
Range of process indices for sub-processes.
Definition: UPstream.H:1727
static int & msgType() noexcept
Message tag of standard messages.
Definition: UPstream.H:1787
static label newCommunicator(const label parent, const labelRange &subRanks, const bool withComponents=true)
Create new communicator with sub-ranks on the parent communicator.
Definition: UPstream.C:272
static void freeCommunicator(const label communicator, const bool withComponents=true)
Free a previously allocated communicator.
Definition: UPstream.C:622
void clear() noexcept
Same as reset(nullptr)
Definition: autoPtr.H:255
bool good() const noexcept
True if the managed pointer is non-null.
Definition: autoPtr.H:206
void reset(T *p=nullptr) noexcept
Delete managed object and set to new given pointer.
Definition: autoPtrI.H:37
static autoPtr< ISstream > readBlock(const label blocki, ISstream &is, IOobject &headerIO)
Read selected block (non-seeking) + header information.
static bool isCollatedType(const word &objectType)
True if object type is a known collated type.
static bool readHeader(IOobject &io, Istream &is)
Read header as per IOobject with additional handling of decomposedBlockData.
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.
const Type & value() const noexcept
Return const reference to value.
fileState
Enumeration defining the file state.
Definition: fileMonitor.H:71
A class for handling file names.
Definition: fileName.H:75
Type
Enumerations to handle directory entry types.
Definition: fileName.H:82
An encapsulation of filesystem-related operations.
static bool isFileOrDir(const bool isFile, const fileName &)
Helper: check for file (isFile) or directory (!isFile)
static labelRange subRanks(const labelUList &mainIOranks)
Get (contiguous) range/bounds of ranks addressed within the given main io-ranks.
Tuple2< fileName, Tuple2< pathType, int > > dirIndex
Augment fileName with pathType and local offset.
virtual void flush() const
Forcibly wait until all output done. Flush any cached data.
virtual fileNameList readObjects(const objectRegistry &db, const fileName &instance, const fileName &local, word &newInstance) const
Search directory for objects. Used in IOobjectList.
label nProcs() const noexcept
Overall number of processors, from UPstream::nProcs() or detected from directories/results.
fileName processorsPath(const IOobject &io, const word &instance, const word &procDir) const
Generate path (like io.path) with provided instance and any.
virtual void setTime(const Time &) const
Callback for time change.
@ PROCUNCOLLATEDINSTANCE
as PROCUNCOLLATED but with instance
@ WRITEOBJECT
write path exists
@ NOTFOUND
Not found.
@ OBJECT
io.objectPath() exists
@ PROCINSTANCE
as PROCOBJECT but with instance
@ FINDINSTANCE
file found in time directory
@ PROCUNCOLLATED
objectPath exists in 'processorN'
@ ABSOLUTE
instance is absolute directory
@ PROCBASEINSTANCE
as PROCBASEOBJECT but with instance
@ PARENTOBJECT
parent of object path
@ PROCOBJECT
objectPath exists in 'processorsNN_first-last'
@ PROCBASEOBJECT
objectPath exists in 'processorsNN'
label comm_
Communicator to use.
static labelList getGlobalIORanks()
Get list of global IO ranks from FOAM_IORANKS env variable. If set, these correspond to the IO master...
static bool uniformFile(const fileNameList &names)
True if the file names are identical. False on an empty list.
static int cacheLevel() noexcept
Return cache level.
static const Enum< pathType > pathTypeNames_
virtual void sync()
Forcibly parallel sync.
virtual instantList findTimes(const fileName &, const word &) const
Get sorted list of times.
virtual fileName objectPath(const IOobject &io, const word &typeName) const
Generate disk file name for object. Opposite of filePath.
A fileOperation initialiser for unthreaded file handlers.
fileOperations that performs all file operations on the master processor. Requires the calls to be pa...
virtual void addWatches(regIOobject &, const fileNameList &) const
Helper: add watches for list of regIOobjects.
virtual double highResLastModified(const fileName &, const bool followLink=true) const
Return time of last file modification.
virtual fileName filePathInfo(const bool checkGlobal, const bool isFile, const IOobject &io, const dirIndexList &pDirs, const bool search, pathType &searchType, word &processorsDir, word &instance) const
Search (locally!) for object; return info on how it was found.
virtual autoPtr< OSstream > NewOFstream(const fileName &pathname, IOstreamOption streamOpt=IOstreamOption(), const bool writeOnProc=true) const
Generate an OSstream that writes a file.
virtual label addWatch(const fileName &) const
Add watching of a file. Returns handle.
static void readAndSend(const fileName &filePath, const labelUList &recvProcs, PstreamBuffers &pBufs)
Read file contents and send to processors.
virtual bool rmDir(const fileName &dir, const bool silent=false, const bool emptyOnly=false) const
Remove a directory and its contents.
virtual mode_t mode(const fileName &, const bool followLink=true) const
Return the file mode.
virtual void setTime(const Time &) const
Callback for time change.
virtual autoPtr< ISstream > readStream(regIOobject &, const fileName &, const word &typeName, const bool readOnProc=true) const
Reads header for regIOobject and returns an ISstream to read the contents.
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.
virtual void flush() const
Forcibly wait until all output done. Flush any cached data.
static float maxMasterFileBufferSize
Max size of parallel communications. Switches from non-blocking.
virtual bool removeWatch(const label) const
Remove watch on a file (using handle)
virtual bool readHeader(IOobject &, const fileName &, const word &typeName) const
Read object header from supplied file.
virtual bool mvBak(const fileName &, const std::string &ext="bak") const
Rename to a corresponding backup file.
virtual fileNameList readObjects(const objectRegistry &db, const fileName &instance, const fileName &local, word &newInstance) const
Search directory for objects. Used in IOobjectList.
virtual label findWatch(const labelList &watchIndices, const fileName &) const
Find index (or -1) of file in list of handles.
virtual time_t lastModified(const fileName &, const bool followLink=true) const
Return time of last file modification.
virtual fileName dirPath(const bool checkGlobal, const IOobject &io, const bool search) const
Search for a directory. checkGlobal : also check undecomposed.
virtual bool cp(const fileName &src, const fileName &dst, const bool followLink=true) const
Copy, recursively if necessary, the source to the destination.
virtual bool chMod(const fileName &, const mode_t) const
Set the file mode.
bool exists(const dirIndexList &, IOobject &io) const
Helper: check IO for local existence. Like filePathInfo but.
virtual off_t fileSize(const fileName &, const bool followLink=true) const
Return size of file.
masterUncollatedFileOperation(bool verbose=false)
Default construct.
virtual bool rm(const fileName &) const
Remove a file, returning true if successful otherwise false.
virtual autoPtr< ISstream > NewIFstream(const fileName &) const
Generate an ISstream that reads a file.
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 bool isDir(const fileName &, const bool followLink=true) const
Does the name exist as a DIRECTORY in the file system?
virtual fileMonitor::fileState getState(const label) const
Get current state of file (using handle)
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.
virtual void setUnmodified(const label) const
Set current state of file (using handle) to unmodified.
HashPtrTable< DynamicList< instant > > times_
Cached times for a given directory.
virtual void updateStates(const bool masterOnly, const bool syncPar) const
Update state of all files.
virtual void storeComm() const
Transfer ownership of communicator to this fileOperation. Use with caution.
virtual bool mkDir(const fileName &, mode_t=0777) const
Make directory.
virtual fileName::Type type(const fileName &, const bool followLink=true) const
Return the file type: DIRECTORY, FILE or SYMLINK.
virtual IOobject findInstance(const IOobject &io, const scalar startValue, const word &stopInstance, const bool constant_fallback=true) const
Find time instance where IOobject is located. The name of the IOobject can be empty,...
virtual bool writeObject(const regIOobject &io, IOstreamOption streamOpt=IOstreamOption(), const bool writeOnProc=true) const
Writes a regIOobject (so header, contents and divider).
virtual instantList findTimes(const fileName &, const word &) const
Get sorted list of times.
static autoPtr< ISstream > read(IOobject &io, const label comm, const bool uniform, const fileNameList &filePaths, const boolUList &readOnProcs)
Read files on comms master.
virtual bool mv(const fileName &src, const fileName &dst, const bool followLink=false) const
Rename src to dst.
virtual bool ln(const fileName &src, const fileName &dst) const
Create a softlink. dst should not exist. Returns true if.
fileName localObjectPath(const IOobject &, const pathType &searchType, const word &processorsDir, const word &instancePath) const
Construct filePath.
virtual fileName getFile(const label) const
Get name of file being watched (using handle)
Master-only drop-in replacement for OFstream.
Registry of regIOobjects.
const Time & time() const noexcept
Return time registry.
A class for managing references or pointers (no reference counting)
Definition: refPtr.H:54
regIOobject is an abstract class derived from IOobject to handle automatic object registration with t...
Definition: regIOobject.H:71
const labelList & watchIndices() const noexcept
Read access to file-monitoring handles.
Definition: regIOobjectI.H:206
A class for handling words, derived from Foam::string.
Definition: word.H:66
static const word null
An empty word.
Definition: word.H:84
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
bool
Definition: EEqn.H:20
#define NotImplemented
Issue a FatalErrorIn for a function not currently implemented.
Definition: error.H:688
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:629
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:600
#define DetailInfo
Definition: evalEntry.C:30
OBJstream os(runTime.globalPath()/outputName)
IOobject io("surfaceFilmProperties", mesh.time().constant(), mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE, IOobject::NO_REGISTER)
runTimeSource setTime(sourceTimes[sourceTimeIndex], sourceTimeIndex)
#define WarningInFunction
Report a warning using Foam::Warning.
forAllConstIters(mixture.phases(), phase)
Definition: pEqn.H:28
constexpr const char *const group
Group name for atomic constants.
float floatOptimisationSwitch(const char *name, const float deflt=0)
Lookup optimisation switch or add default value.
Definition: debug.C:240
int debug
Static debugging option.
addToRunTimeSelectionTable(fileOperation, collatedFileOperation, word)
defineTypeNameAndDebug(collatedFileOperation, 0)
registerOptSwitch("maxThreadFileBufferSize", float, collatedFileOperation::maxThreadFileBufferSize)
addNamedToRunTimeSelectionTable(fileOperationInitialise, fileOperationInitialise_collated, word, collated)
Namespace for OpenFOAM.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
List< word > wordList
List of word.
Definition: fileName.H:59
labelList identity(const label len, label start=0)
Return an identity map of the given length with (map[i] == i), works like std::iota() but returning a...
Definition: labelLists.C:44
static Tuple2< label, labelList > getCommPattern()
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:837
List< label > labelList
A List of labels.
Definition: List.H:61
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:529
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.
List< fileName > fileNameList
List of fileName.
Definition: fileNameList.H:32
messageStream Info
Information stream (stdout output on master, null elsewhere)
mode_t mode(const fileName &name, const bool followLink=true)
Return the file mode, normally following symbolic links.
Definition: POSIX.C:775
List< instant > instantList
List of instants.
Definition: instantList.H:41
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
Definition: FlatOutput.H:225
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
List< string > stringList
List of string.
Definition: stringList.H:32
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:907
IOerror FatalIOError
Error stream (stdout output on all processes), with additional 'FOAM FATAL IO ERROR' header text and ...
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh >> &tf1, const word &name, const dimensionSet &dimensions, const bool initCopy=false)
Global function forwards to reuseTmpDimensionedField::New.
List< bool > boolList
A List of bools.
Definition: List.H:59
int infoDetailLevel
Global for selective suppression of Info output.
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:879
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition: exprTraits.C:127
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
UList< label > labelUList
A UList of labels.
Definition: UList.H:76
bool read(const char *buf, int32_t &val)
Same as readInt32.
Definition: int32.H:127
void stableSort(UList< T > &list)
Stable sort the list.
Definition: UList.C:311
fileName search(const word &file, const fileName &directory)
Recursively search the given directory for the file.
Definition: fileName.C:642
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:50
word format(conversionProperties.get< word >("format"))
labelList f(nPoints)
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:286
Extract type (as a word) from an object, typically using its type() method.
Definition: word.H:362