fileOperation.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 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "fileOperation.H"
31 #include "regIOobject.H"
32 #include "argList.H"
33 #include "HashSet.H"
34 #include "objectRegistry.H"
35 #include "decomposedBlockData.H"
36 #include "polyMesh.H"
37 #include "registerSwitch.H"
38 #include "Time.H"
39 
40 /* * * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * */
41 
42 namespace Foam
43 {
44  autoPtr<fileOperation> fileOperation::fileHandlerPtr_;
45 
46  defineTypeNameAndDebug(fileOperation, 0);
47  defineRunTimeSelectionTable(fileOperation, word);
48 
50  (
51  debug::optimisationSwitches().lookupOrAddDefault<word>
52  (
53  "fileHandler",
54  //Foam::fileOperations::uncollatedFileOperation::typeName,
55  "uncollated",
57  )
58  );
59 }
60 
61 
63 
66 ({
67  { fileOperation::NOTFOUND, "notFound" },
68  { fileOperation::ABSOLUTE, "absolute" },
69  { fileOperation::OBJECT, "objectPath" },
70  { fileOperation::WRITEOBJECT, "writeObject" },
71  { fileOperation::PROCUNCOLLATED, "uncollatedProc" },
72  { fileOperation::PROCBASEOBJECT, "globalProc" },
73  { fileOperation::PROCOBJECT, "localProc" },
74  { fileOperation::PARENTOBJECT, "parentObjectPath" },
75  { fileOperation::FINDINSTANCE, "findInstance" },
76  { fileOperation::PROCUNCOLLATEDINSTANCE, "uncollatedProcInstance" },
77  { fileOperation::PROCBASEINSTANCE, "globalProcInstance" },
78  { fileOperation::PROCINSTANCE, "localProcInstance" }
79 });
80 
81 
82 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
83 
85 {
86  if (!monitorPtr_.valid())
87  {
88  monitorPtr_.reset
89  (
90  new fileMonitor
91  (
94  )
95  );
96  }
97  return *monitorPtr_;
98 }
99 
100 
102 (
103  const fileNameList& dirEntries,
104  const word& constantName
105 )
106 {
107  // Initialise instant list
108  instantList times(dirEntries.size() + 1);
109  label nTimes = 0;
110 
111  // Check for "constant"
112  bool haveConstant = false;
113  for (const fileName& dirName : dirEntries)
114  {
115  if (dirName == constantName)
116  {
117  haveConstant = true;
118  times[nTimes].value() = 0;
119  times[nTimes].name() = constantName;
120  ++nTimes;
121  break;
122  }
123  }
124 
125  // Read and parse all the entries in the directory
126  for (const fileName& dirName : dirEntries)
127  {
128  scalar timeValue;
129  if (readScalar(dirName, timeValue))
130  {
131  times[nTimes].value() = timeValue;
132  times[nTimes].name() = dirName;
133  ++nTimes;
134  }
135  }
136 
137  // Reset the length of the times list
138  times.setSize(nTimes);
139 
140  if (haveConstant)
141  {
142  if (nTimes > 2)
143  {
144  std::sort(&times[1], times.end(), instant::less());
145  }
146  }
147  else if (nTimes > 1)
148  {
149  std::sort(&times[0], times.end(), instant::less());
150  }
151 
152  return times;
153 }
154 
155 
157 (
158  const instantList& extraTimes,
159  const word& constantName,
160  instantList& times
161 )
162 {
163  if (extraTimes.size())
164  {
165  const bool haveConstant =
166  (
167  times.size()
168  && times[0].name() == constantName
169  );
170 
171  const bool haveExtraConstant =
172  (
173  extraTimes.size()
174  && extraTimes[0].name() == constantName
175  );
176 
177  // Combine times
178  instantList combinedTimes(times.size()+extraTimes.size());
179  label sz = 0;
180  label extrai = 0;
181  if (haveExtraConstant)
182  {
183  extrai = 1;
184  if (!haveConstant)
185  {
186  combinedTimes[sz++] = extraTimes[0]; // constant
187  }
188  }
189  forAll(times, i)
190  {
191  combinedTimes[sz++] = times[i];
192  }
193  for (; extrai < extraTimes.size(); extrai++)
194  {
195  combinedTimes[sz++] = extraTimes[extrai];
196  }
197  combinedTimes.setSize(sz);
198  times.transfer(combinedTimes);
199 
200  // Sort
201  if (times.size() > 1)
202  {
203  label starti = 0;
204  if (times[0].name() == constantName)
205  {
206  starti = 1;
207  }
208  std::sort(&times[starti], times.end(), instant::less());
209 
210  // Filter out duplicates
211  label newi = starti+1;
212  for (label i = newi; i < times.size(); i++)
213  {
214  if (times[i].value() != times[i-1].value())
215  {
216  if (newi != i)
217  {
218  times[newi] = times[i];
219  }
220  newi++;
221  }
222  }
223 
224  times.setSize(newi);
225  }
226  }
227 }
228 
229 
231 {
232  return (isFile ? Foam::isFile(f) : Foam::isDir(f));
233 }
234 
235 
238 (
239  const fileName& fName,
240  const bool syncPar
241 ) const
242 {
243  // If path is local to a processor (e.g. contains 'processor2')
244  // find the corresponding actual processor directory (e.g. 'processors4')
245  // and index (2)
246 
247  fileName path;
248  fileName pDir;
249  fileName local;
250  label gStart;
251  label gSz;
252  label numProcs;
253  label proci =
254  splitProcessorPath(fName, path, pDir, local, gStart, gSz, numProcs);
255 
256  if (proci != -1)
257  {
258  const fileName procPath(path/pDir);
259 
260  const auto iter = procsDirs_.cfind(procPath);
261 
262  if (iter.found())
263  {
264  return iter.val();
265  }
266 
267  // Read all directories to see any beginning with processor
268  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
269 
270  DynamicList<dirIndex> procDirs;
271 
272  // Note: use parallel synchronised reading so cache will be same
273  // order on all processors
274  fileNameList dirNames(readDir(path, fileName::Type::DIRECTORY));
275 
276  // Extract info from processorsDDD or processorDDD:
277  // - highest processor number
278  // - directory+offset containing data for proci
279  label maxProc = -1;
280 
281  forAll(dirNames, i)
282  {
283  const fileName& dirN = dirNames[i];
284 
285  // Analyse directory name
286  fileName rp, rd, rl;
287  label rStart, rSize, rNum;
288  label readProci =
289  splitProcessorPath(dirN, rp, rd, rl, rStart, rSize, rNum);
290  maxProc = max(maxProc, readProci);
291 
292  if (proci == readProci)
293  {
294  // Found "processorDDD". No need for index.
295  procDirs.append
296  (
297  dirIndex
298  (
299  dirN,
300  Tuple2<pathType, label>(PROCUNCOLLATED, -1)
301  )
302  );
303  }
304  else if (proci >= rStart && proci < rStart+rSize)
305  {
306  // "processorsDDD_start-end"
307  // Found the file that contains the data for proci
308  procDirs.append
309  (
310  dirIndex
311  (
312  dirN,
313  Tuple2<pathType, label>(PROCOBJECT, proci-rStart)
314  )
315  );
316  }
317  if (rNum != -1)
318  {
319  // Direct detection of processorsDDD
320  maxProc = rNum-1;
321 
322  if (rStart == -1)
323  {
324  // "processorsDDD"
325  procDirs.append
326  (
327  dirIndex
328  (
329  dirN,
330  Tuple2<pathType, label>(PROCBASEOBJECT, proci)
331  )
332  );
333  }
334  }
335  }
336  if (!Pstream::parRun())
337  {
338  // If (as a side effect) we found the number of decompositions
339  // use it
340  if (maxProc != -1)
341  {
342  const_cast<fileOperation&>(*this).setNProcs(maxProc+1);
343  }
344  }
345 
346  if
347  (
348  (syncPar && returnReduce(procDirs.size(), sumOp<label>()))
349  || (!syncPar && procDirs.size())
350  )
351  {
352  procsDirs_.insert(procPath, procDirs);
353 
354  if (debug)
355  {
356  Pout<< "fileOperation::lookupProcessorsPath : For:" << procPath
357  << " detected:" << procDirs << endl;
358  }
359 
360  // Make sure to return a reference
361  return procsDirs_[procPath];
362  }
363  }
364  return tmpNrc<dirIndexList>(new dirIndexList(0, dirIndex()));
365 }
366 
367 
370 {
371  // Use parallel synchronisation
372  return lookupAndCacheProcessorsPath(fName, true);
373 }
374 
375 
377 {
378  // Generate output filename for object
379  fileName objPath(objectPath(io, word::null));
380 
381  // Test for either directory or a (valid) file & IOobject
382  bool ok;
383  if (io.name().empty())
384  {
385  ok = isDir(objPath);
386  }
387  else
388  {
389  ok =
390  isFile(objPath)
391  && io.typeHeaderOk<IOList<label>>(false);// object with local scope
392  }
393 
394  if (!ok)
395  {
396  // Re-test with searched for objectPath. This is for backwards
397  // compatibility
398  fileName originalPath(filePath(io.objectPath()));
399  if (originalPath != objPath)
400  {
401  // Test for either directory or a (valid) file & IOobject
402  if (io.name().empty())
403  {
404  ok = isDir(originalPath);
405  }
406  else
407  {
408  ok =
409  isFile(originalPath)
410  && io.typeHeaderOk<IOList<label>>(false);
411  }
412  }
413  }
414 
415  return ok;
416 }
417 
418 
419 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
420 
422 :
423  comm_(comm)
424 {}
425 
426 
428 (
429  const word& handlerType,
430  bool verbose
431 )
432 {
434  << "Constructing fileHandler" << endl;
435 
436  auto cstrIter = wordConstructorTablePtr_->cfind(handlerType);
437 
438  if (!cstrIter.found())
439  {
441  (
442  "fileHandler",
443  handlerType,
444  *wordConstructorTablePtr_
445  ) << abort(FatalError);
446  }
447 
448  return autoPtr<fileOperation>(cstrIter()(verbose));
449 }
450 
451 
452 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
453 
455 (
456  const IOobject& io,
457  const word& typeName
458 ) const
459 {
460  return io.objectPath();
461 }
462 
463 
465 (
466  const regIOobject& io,
470  const bool valid
471 ) const
472 {
473  if (valid)
474  {
475  fileName pathName(io.objectPath());
476 
477  mkDir(pathName.path());
478 
479  autoPtr<Ostream> osPtr
480  (
481  NewOFstream
482  (
483  pathName,
484  fmt,
485  ver,
486  cmp
487  )
488  );
489 
490  if (!osPtr.valid())
491  {
492  return false;
493  }
494 
495  Ostream& os = osPtr();
496 
497  // If any of these fail, return (leave error handling to Ostream class)
498  if (!os.good())
499  {
500  return false;
501  }
502 
503  if (!io.writeHeader(os))
504  {
505  return false;
506  }
507 
508  // Write the data to the Ostream
509  if (!io.writeData(os))
510  {
511  return false;
512  }
513 
515  }
516  return true;
517 }
518 
519 
521 {
522  if (debug)
523  {
524  Pout<< "fileOperation::filePath :" << " fName:" << fName << endl;
525  }
526 
527  fileName path;
528  fileName pDir;
529  fileName local;
530  label gStart;
531  label gSz;
532  label numProcs;
533  label proci =
534  splitProcessorPath(fName, path, pDir, local, gStart, gSz, numProcs);
535 
536  if (numProcs != -1)
537  {
538  WarningInFunction << "Filename is already adapted:" << fName << endl;
539  }
540 
541  // Give preference to processors variant
542  if (proci != -1)
543  {
544  // Get all processor directories
545  tmpNrc<dirIndexList> procDirs(lookupProcessorsPath(fName));
546  forAll(procDirs(), i)
547  {
548  const fileName& procDir = procDirs()[i].first();
549 
550  fileName collatedName(path/procDir/local);
551  if (exists(collatedName))
552  {
553  if (debug)
554  {
555  Pout<< "fileOperation::filePath : " << collatedName << endl;
556  }
557  return collatedName;
558  }
559  }
560  }
561 
562  if (exists(fName))
563  {
564  if (debug)
565  {
566  Pout<< "fileOperation::filePath : " << fName << endl;
567  }
568  return fName;
569  }
570 
571  if (debug)
572  {
573  Pout<< "fileOperation::filePath : Not found" << endl;
574  }
575  return fileName::null;
576 }
577 
578 
580 {
581  return monitor().addWatch(fName);
582 }
583 
584 
585 bool Foam::fileOperation::removeWatch(const label watchIndex) const
586 {
587  return monitor().removeWatch(watchIndex);
588 }
589 
590 
592 (
593  const labelList& watchIndices,
594  const fileName& fName
595 ) const
596 {
597  forAll(watchIndices, i)
598  {
599  if (getFile(watchIndices[i]) == fName)
600  {
601  return i;
602  }
603  }
604  return -1;
605 }
606 
607 
609 (
610  regIOobject& rio,
611  const fileNameList& files
612 ) const
613 {
614  const labelList& watchIndices = rio.watchIndices();
615 
616  DynamicList<label> newWatchIndices;
617  labelHashSet removedWatches(watchIndices);
618 
619  for (const fileName& f : files)
620  {
621  const label index = findWatch(watchIndices, f);
622 
623  if (index == -1)
624  {
625  newWatchIndices.append(addWatch(f));
626  }
627  else
628  {
629  // Existing watch
630  newWatchIndices.append(watchIndices[index]);
631  removedWatches.erase(index);
632  }
633  }
634 
635  // Remove any unused watches
636  for (const label index : removedWatches)
637  {
638  removeWatch(watchIndices[index]);
639  }
640 
641  rio.watchIndices() = newWatchIndices;
642 }
643 
644 
646 {
647  return monitor().getFile(watchIndex);
648 }
649 
650 
652 (
653  const bool masterOnly,
654  const bool syncPar
655 ) const
656 {
657  monitor().updateStates(masterOnly, Pstream::parRun());
658 }
659 
660 
662 (
663  const label watchFd
664 ) const
665 {
666  return monitor().getState(watchFd);
667 }
668 
669 
670 void Foam::fileOperation::setUnmodified(const label watchFd) const
671 {
672  monitor().setUnmodified(watchFd);
673 }
674 
675 
677 (
678  const fileName& directory,
679  const word& constantName
680 ) const
681 {
682  if (debug)
683  {
684  Pout<< "fileOperation::findTimes : Finding times in directory "
685  << directory << endl;
686  }
687 
688  // Read directory entries into a list
689  fileNameList dirEntries
690  (
692  (
693  directory,
695  )
696  );
697 
698  instantList times = sortTimes(dirEntries, constantName);
699 
700 
701  // Get all processor directories
702  tmpNrc<dirIndexList> procDirs(lookupProcessorsPath(directory));
703  forAll(procDirs(), i)
704  {
705  const fileName& procDir = procDirs()[i].first();
706  fileName collDir(processorsPath(directory, procDir));
707  if (!collDir.empty() && collDir != directory)
708  {
709  fileNameList extraEntries
710  (
712  (
713  collDir,
715  )
716  );
717  mergeTimes
718  (
719  sortTimes(extraEntries, constantName),
720  constantName,
721  times
722  );
723  }
724  }
725 
726  if (debug)
727  {
728  Pout<< "fileOperation::findTimes : Found times:" << times << endl;
729  }
730  return times;
731 }
732 
733 
735 (
736  const IOobject& startIO,
737  const scalar startValue,
738  const word& stopInstance
739 ) const
740 {
741  const Time& time = startIO.time();
742 
743  IOobject io(startIO);
744 
745  // Note: - if name is empty, just check the directory itself
746  // - check both for isFile and headerOk since the latter does a
747  // filePath so searches for the file.
748  // - check for an object with local file scope (so no looking up in
749  // parent directory in case of parallel)
750 
751  if (exists(io))
752  {
754  << "Found exact match for \"" << io.name()
755  << "\" in " << io.instance()/io.local()
756  << endl;
757 
758  return io;
759  }
760 
761  // Search back through the time directories to find the first time
762  // that is less than or equal to the current time
763 
764  instantList ts = time.times();
765  label instanceI = ts.size()-1;
766 
767  for (; instanceI >= 0; --instanceI)
768  {
769  if (ts[instanceI].value() <= startValue)
770  {
771  break;
772  }
773  }
774 
775  // Found the time, continue from here
776  for (; instanceI >= 0; --instanceI)
777  {
778  io.instance() = ts[instanceI].name();
779 
780  // Shortcut: if actual directory is the timeName we've already tested it
781  if
782  (
783  io.instance() == startIO.instance()
784  && io.instance() != stopInstance
785  )
786  {
787  continue;
788  }
789 
790  if (exists(io))
791  {
793  << "Found exact match for \"" << io.name()
794  << "\" in " << io.instance()/io.local()
795  << endl;
796 
797  return io;
798  }
799 
800  // Check if hit minimum instance
801  if (io.instance() == stopInstance)
802  {
804  << "Hit stopInstance " << stopInstance << endl;
805 
806  if
807  (
808  startIO.readOpt() == IOobject::MUST_READ
810  )
811  {
812  if (io.name().empty())
813  {
815  << "Cannot find directory "
816  << io.local() << " in times " << startIO.instance()
817  << " down to " << stopInstance
818  << exit(FatalError);
819  }
820  else
821  {
823  << "Cannot find file \"" << io.name()
824  << "\" in directory " << io.local()
825  << " in times " << startIO.instance()
826  << " down to " << stopInstance
827  << exit(FatalError);
828  }
829  }
830 
831  return io;
832  }
833  }
834 
835  // Times usually already includes 'constant' so would have been checked
836  // above.
837  // However, re-test under these conditions:
838  // - Times is empty.
839  // Sometimes this can happen (eg, decomposePar with collated)
840  // - Times[0] is not constant
841  // - The startValue is negative (eg, kivaTest).
842  // This plays havoc with the reverse search, causing it to miss 'constant'
843 
844  if
845  (
846  ts.empty()
847  || ts.first().name() != time.constant()
848  || startValue < 0
849  )
850  {
851  io.instance() = time.constant();
852  if (exists(io))
853  {
855  << "Found constant match for \"" << io.name()
856  << "\" in " << io.instance()/io.local()
857  << endl;
858 
859  return io;
860  }
861  }
862 
863 
864  if
865  (
866  startIO.readOpt() == IOobject::MUST_READ
868  )
869  {
871  << "Cannot find file \"" << io.name() << "\" in directory "
872  << io.local() << " in times " << startIO.instance()
873  << " down to " << time.constant()
874  << exit(FatalError);
875  }
876 
877  return io;
878 }
879 
880 
882 (
883  const objectRegistry& db,
884  const fileName& instance,
885  const fileName& local,
886  word& newInstance
887 ) const
888 {
889  if (debug)
890  {
891  Pout<< "fileOperation::readObjects :"
892  << " db:" << db.objectPath()
893  << " instance:" << instance << endl;
894  }
895 
896  fileName path(db.path(instance, db.dbDir()/local));
897 
898  newInstance = word::null;
899  fileNameList objectNames;
900 
901  if (Foam::isDir(path))
902  {
903  newInstance = instance;
904  objectNames = Foam::readDir(path, fileName::FILE);
905  }
906  else
907  {
908  // Get processors equivalent of path
909  fileName procsPath(filePath(path));
910 
911  if (!procsPath.empty())
912  {
913  newInstance = instance;
914  objectNames = Foam::readDir(procsPath, fileName::FILE);
915  }
916  }
917  return objectNames;
918 }
919 
920 
922 {}
923 
924 
926 (
927  const fileName& dir,
928  const fileName& local
929 ) const
930 {
931  label nProcs = 0;
932  if (Pstream::master(comm_))
933  {
934  fileNameList dirNames(Foam::readDir(dir, fileName::Type::DIRECTORY));
935 
936  // Detect any processorsDDD or processorDDD
937  label maxProc = -1;
938  forAll(dirNames, i)
939  {
940  const fileName& dirN = dirNames[i];
941 
942  fileName path, pDir, local;
943  label start, size, n;
944  maxProc = max
945  (
946  maxProc,
947  splitProcessorPath(dirN, path, pDir, local, start, size, n)
948  );
949  if (n != -1)
950  {
951  // Direct detection of processorsDDD
952  maxProc = n-1;
953  break;
954  }
955  }
956  nProcs = maxProc+1;
957 
958 
959  if (nProcs == 0 && Foam::isDir(dir/processorsBaseDir))
960  {
961  fileName pointsFile
962  (
963  dir
964  /processorsBaseDir
965  /"constant"
966  /local
968  /"points"
969  );
970 
971  if (Foam::isFile(pointsFile))
972  {
973  nProcs = decomposedBlockData::numBlocks(pointsFile);
974  }
975  else
976  {
977  WarningInFunction << "Cannot read file " << pointsFile
978  << " to determine the number of decompositions."
979  << " Returning 1" << endl;
980  }
981  }
982  }
983  Pstream::scatter(nProcs, Pstream::msgType(), comm_);
984  return nProcs;
985 }
986 
987 
989 {
990  if (debug)
991  {
992  Pout<< "fileOperation::flush : clearing processor directories cache"
993  << endl;
994  }
995  procsDirs_.clear();
996 }
997 
998 
1001  const IOobject& io,
1002  const word& procsDir
1003 ) const
1004 {
1005  return io.rootPath()/io.time().globalCaseName()/procsDir;
1006 }
1007 
1008 
1011  const IOobject& io,
1012  const word& instance,
1013  const word& procsDir
1014 ) const
1015 {
1016  return
1017  processorsCasePath(io, procsDir)
1018  /instance
1019  /io.db().dbDir()
1020  /io.local();
1021 }
1022 
1023 
1026  const fileName& dir,
1027  const word& procsDir
1028 ) const
1029 {
1030  // Check if directory is processorDDD
1031  word caseName(dir.name());
1032 
1033  std::string::size_type pos = caseName.find("processor");
1034  if (pos == 0)
1035  {
1036  if (caseName.size() <= 9 || caseName[9] == 's')
1037  {
1038  WarningInFunction << "Directory " << dir
1039  << " does not end in old-style processorDDD" << endl;
1040  }
1041 
1042  return dir.path()/procsDir;
1043  }
1044 
1045  return fileName::null;
1046 }
1047 
1048 
1051  const fileName& objectPath,
1052  fileName& path,
1053  fileName& procDir,
1054  fileName& local,
1055 
1056  label& groupStart,
1057  label& groupSize,
1058 
1059  label& nProcs
1060 )
1061 {
1062  path.clear();
1063  procDir.clear();
1064  local.clear();
1065 
1066  // Potentially detected start of number of processors in local group
1067  groupStart = -1;
1068  groupSize = 0;
1069 
1070  // Potentially detected number of processors
1071  nProcs = -1;
1072 
1073  // Search for processor at start of line or /processor
1074  std::string::size_type pos = objectPath.find("processor");
1075  if (pos == string::npos)
1076  {
1077  return -1;
1078  }
1079 
1080  // "processorDDD"
1081  // "processorsNNN"
1082  // "processorsNNN_AA-BB"
1083 
1084 
1085  if (pos > 0 && objectPath[pos-1] != '/')
1086  {
1087  // Directory not starting with "processor" e.g. "somenamewithprocessor"
1088  return -1;
1089  }
1090 
1091  procDir = objectPath;
1092 
1093  // Strip leading directory
1094  if (pos > 0)
1095  {
1096  path = objectPath.substr(0, pos-1);
1097  procDir = objectPath.substr(pos);
1098  }
1099 
1100  // Strip trailing local directory
1101  pos = procDir.find('/');
1102  if (pos != string::npos)
1103  {
1104  local = procDir.substr(pos+1);
1105  procDir = procDir.substr(0, pos);
1106  }
1107 
1108  // Now procDir is e.g.
1109  // - processor0
1110  // - processors0
1111  // - processorBananas
1112 
1113  // Look for number after "processor"
1114 
1115  fileName f(procDir.substr(9));
1116 
1117  if (f.size() && f[0] == 's')
1118  {
1119  // "processsorsNNN"
1120 
1121  f = f.substr(1);
1122 
1123  // Detect "processorsNNN_AA-BB"
1124  {
1125  std::string::size_type fromStart = f.find("_");
1126  std::string::size_type toStart = f.find("-");
1127  if (fromStart != string::npos && toStart != string::npos)
1128  {
1129  string nProcsName(f.substr(0, fromStart));
1130  string fromName(f.substr(fromStart+1, toStart-(fromStart+1)));
1131  string toName(f.substr(toStart+1));
1132 
1133  label groupEnd = -1;
1134  if
1135  (
1136  Foam::read(fromName.c_str(), groupStart)
1137  && Foam::read(toName.c_str(), groupEnd)
1138  && Foam::read(nProcsName.c_str(), nProcs)
1139  )
1140  {
1141  groupSize = groupEnd-groupStart+1;
1142  return -1;
1143  }
1144  }
1145  }
1146 
1147  // Detect "processorsN"
1148  label n;
1149  if (Foam::read(f.c_str(), n))
1150  {
1151  nProcs = n;
1152  }
1153  return -1;
1154  }
1155  else
1156  {
1157  // Detect "processorN"
1158  label proci;
1159  if (Foam::read(f.c_str(), proci))
1160  {
1161  return proci;
1162  }
1163  else
1164  {
1165  return -1;
1166  }
1167  }
1168 }
1169 
1170 
1172 {
1173  fileName path, pDir, local;
1174  label start, size, nProcs;
1175  return splitProcessorPath(fName, path, pDir, local, start, size, nProcs);
1176 }
1177 
1178 
1179 // * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
1180 
1182 {
1183  if (!fileOperation::fileHandlerPtr_.valid())
1184  {
1185  word handler(getEnv("FOAM_FILEHANDLER"));
1186 
1187  if (handler.empty())
1188  {
1190  }
1191 
1193  }
1194 
1196 }
1197 
1198 
1200 {
1201  if
1202  (
1203  newHandler.valid() && fileOperation::fileHandlerPtr_.valid()
1204  && newHandler->type() == fileOperation::fileHandlerPtr_->type()
1205  )
1206  {
1207  return;
1208  }
1209 
1211 
1212  if (newHandler.valid())
1213  {
1214  fileOperation::fileHandlerPtr_ = std::move(newHandler);
1215  }
1216 }
1217 
1218 
1219 // ************************************************************************* //
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
Foam::fileOperation::type
virtual fileName::Type type(const fileName &, const bool followLink=true) const =0
Return the file type: DIRECTORY, FILE or LINK.
regIOobject.H
uncollatedFileOperation.H
Foam::TimePaths::globalCaseName
const fileName & globalCaseName() const
Return global case name.
Definition: TimePathsI.H:48
Foam::IOobject
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:104
Foam::Enum
Enum is a wrapper around a list of names/values that represent particular enumeration (or int) values...
Definition: IOstreamOption.H:51
Foam::exists
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: MSwindows.C:625
Foam::Time
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:73
Foam::fileName::FILE
A file.
Definition: fileName.H:79
Foam::IOobject::name
const word & name() const
Return name.
Definition: IOobjectI.H:46
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:62
Foam::fileOperation::mergeTimes
static void mergeTimes(const instantList &extraTimes, const word &constantName, instantList &times)
Merge two times.
Definition: fileOperation.C:157
Foam::fileOperation
An encapsulation of filesystem-related operations.
Definition: fileOperation.H:75
Foam::fileName
A class for handling file names.
Definition: fileName.H:69
Foam::returnReduce
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
Definition: PstreamReduceOps.H:94
Foam::fileOperation::processorsPath
fileName processorsPath(const IOobject &, const word &instance, const word &procDir) const
Generate path (like io.path) with provided instance and any.
Definition: fileOperation.C:1010
Foam::fileOperation::addWatches
virtual void addWatches(regIOobject &, const fileNameList &) const
Helper: add watches for list of regIOobjects.
Definition: fileOperation.C:609
Foam::fileName::path
static std::string path(const std::string &str)
Return directory path name (part before last /)
Definition: fileNameI.H:186
Foam::regIOobject::watchIndices
const labelList & watchIndices() const
Return file-monitoring handles.
Definition: regIOobjectI.H:94
Foam::DynamicList
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition: DynamicList.H:57
Foam::less
static bool less(const vector &x, const vector &y)
To compare normals.
Definition: meshRefinementRefine.C:57
Foam::IOobject::typeHeaderOk
bool typeHeaderOk(const bool checkType=true, const bool search=true, const bool verbose=true)
Read header (uses typeFilePath to find file) and check its info.
Definition: IOobjectTemplates.C:39
Foam::defineRunTimeSelectionTable
defineRunTimeSelectionTable(reactionRateFlameArea, dictionary)
Foam::IOobject::writeEndDivider
static Ostream & writeEndDivider(Ostream &os)
Write the standard end file divider.
Definition: IOobjectWriteHeader.C:109
Foam::regIOobject::writeData
virtual bool writeData(Ostream &) const =0
Pure virtual writeData function.
Foam::IOobject::rootPath
const fileName & rootPath() const
Definition: IOobject.C:444
Foam::IOobject::instance
const fileName & instance() const
Definition: IOobjectI.H:167
Foam::fileName::name
static std::string name(const std::string &str)
Return basename (part beyond last /), including its extension.
Definition: fileNameI.H:209
Foam::read
bool read(const char *buf, int32_t &val)
Same as readInt32.
Definition: int32.H:108
Foam::IOobject::inotifyMaster
Definition: IOobject.H:139
Foam::polyMesh::meshSubDir
static word meshSubDir
Return the mesh sub-directory name (usually "polyMesh")
Definition: polyMesh.H:315
Foam::UPstream::parRun
static bool & parRun()
Is this a parallel run?
Definition: UPstream.H:414
Foam::fileOperation::pathTypeNames_
static const Enum< pathType > pathTypeNames_
Definition: fileOperation.H:97
Foam::fileOperation::flush
virtual void flush() const
Forcibly wait until all output done. Flush any cached data.
Definition: fileOperation.C:988
objectRegistry.H
Foam::IOobject::fileModificationChecking
static fileCheckTypes fileModificationChecking
Type of file modification checking.
Definition: IOobject.H:207
Foam::fileOperation::filePath
virtual fileName filePath(const bool checkGlobal, const IOobject &, const word &typeName, const bool search=true) const =0
Search for an object. checkGlobal : also check undecomposed case.
Foam::fileOperation::splitProcessorPath
static label splitProcessorPath(const fileName &, fileName &path, fileName &procDir, fileName &local, label &groupStart, label &groupSize, label &nProcs)
Split fileName into part before 'processor' and part after.
Definition: fileOperation.C:1050
Foam::Pstream::scatter
static void scatter(const List< commsStruct > &comms, T &Value, const int tag, const label comm)
Scatter data. Distribute without modification. Reverse of gather.
Definition: gatherScatter.C:150
Foam::fileMonitor::fileState
fileState
Enumeration defining the file state.
Definition: fileMonitor.H:72
Foam::isFile
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: MSwindows.C:658
Foam::fileHandler
const fileOperation & fileHandler()
Get current file handler.
Definition: fileOperation.C:1181
Foam::autoPtr::valid
bool valid() const noexcept
True if the managed pointer is non-null.
Definition: autoPtrI.H:107
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:337
Foam::fileOperation::isFileOrDir
static bool isFileOrDir(const bool isFile, const fileName &)
Helper: check for file (isFile) or directory (!isFile)
Definition: fileOperation.C:230
Foam::fileOperation::setNProcs
virtual void setNProcs(const label nProcs)
Set number of processor directories/results. Only used in.
Definition: fileOperation.C:921
Foam::Pout
prefixOSstream Pout
An Ostream wrapper for parallel output to std::cout.
polyMesh.H
Foam::HashSet< label, Hash< label > >
Foam::IOobject::time
const Time & time() const
Return time.
Definition: IOobject.C:438
Foam::fileOperation::updateStates
virtual void updateStates(const bool masterOnly, const bool syncPar) const
Update state of all files.
Definition: fileOperation.C:652
Foam::IOobject::inotify
Definition: IOobject.H:138
Foam::getEnv
string getEnv(const std::string &envName)
Get environment value for given envName.
Definition: MSwindows.C:371
Foam::fileOperation::findTimes
virtual instantList findTimes(const fileName &, const word &) const
Get sorted list of times.
Definition: fileOperation.C:677
Foam::sumOp
Definition: ops.H:213
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:290
Foam::fileOperation::getFile
virtual fileName getFile(const label) const
Get name of file being watched (using handle)
Definition: fileOperation.C:645
Foam::fileOperation::findInstance
virtual IOobject findInstance(const IOobject &io, const scalar startValue, const word &stopInstance) const
Find instance where IOobject is. Fails if cannot be found.
Definition: fileOperation.C:735
Foam::IOobject::db
const objectRegistry & db() const
Return the local objectRegistry.
Definition: IOobject.C:432
Foam::objectRegistry
Registry of regIOobjects.
Definition: objectRegistry.H:60
Foam::fileOperation::New
static autoPtr< fileOperation > New(const word &handlerType, bool verbose=false)
Select fileHandler-type.
Definition: fileOperation.C:428
n
label n
Definition: TABSMDCalcMethod2.H:31
Foam::objectRegistry::dbDir
virtual const fileName & dbDir() const
Local directory path of this objectRegistry relative to the time.
Definition: objectRegistry.H:198
Foam::IOobject::local
const fileName & local() const
Definition: IOobjectI.H:179
Foam::fileOperation::lookupProcessorsPath
virtual tmpNrc< dirIndexList > lookupProcessorsPath(const fileName &) const
Lookup name of processorsDDD using cache. Return empty fileName.
Definition: fileOperation.C:369
Foam::label
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:62
Foam::IOstreamOption::versionNumber
Representation of a major/minor version number.
Definition: IOstreamOption.H:79
Foam::fileOperation::sortTimes
static instantList sortTimes(const fileNameList &, const word &)
Sort directory entries according to time value.
Definition: fileOperation.C:102
Foam::fileOperation::fileOperation
fileOperation(const label comm)
Construct from communicator.
Definition: fileOperation.C:421
Foam::HashTable::erase
bool erase(const iterator &iter)
Erase an entry specified by given iterator.
Definition: HashTable.C:392
DebugInFunction
#define DebugInFunction
Report an information message using Foam::Info.
Definition: messageStream.H:356
Foam::tmpNrc
A class for managing temporary objects without reference counting.
Definition: tmpNrc.H:56
Foam::name
word name(const complex &c)
Return string representation of complex.
Definition: complex.C:76
Foam::DynamicList::append
DynamicList< T, SizeMin > & append(const T &val)
Append an element to the end of this list.
Definition: DynamicListI.H:472
Foam::fileOperation::nProcs
virtual label nProcs(const fileName &dir, const fileName &local="") const
Get number of processor directories/results. Used for e.g.
Definition: fileOperation.C:926
argList.H
Foam::List::transfer
void transfer(List< T > &list)
Definition: List.C:436
Foam::fileMonitor
Checking for changes to files.
Definition: fileMonitor.H:65
Foam::sort
void sort(UList< T > &a)
Definition: UList.C:241
Foam::TimePaths::times
instantList times() const
Search the case for valid time directories.
Definition: TimePaths.C:149
Foam::fileOperation::getState
virtual fileMonitor::fileState getState(const label) const
Get current state of file (using handle)
Definition: fileOperation.C:662
size_type
graph_traits< Graph >::vertices_size_type size_type
Definition: SloanRenumber.C:75
Foam::max
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
HashSet.H
Foam::IOstreamOption::streamFormat
streamFormat
Data format (ascii | binary)
Definition: IOstreamOption.H:64
Foam::FatalError
error FatalError
FatalErrorInLookup
#define FatalErrorInLookup(lookupTag, lookupName, lookupTable)
Report an error message using Foam::FatalError.
Definition: error.H:359
fileOperation.H
Foam::fileOperation::monitorPtr_
autoPtr< fileMonitor > monitorPtr_
file-change monitor for all registered files
Definition: fileOperation.H:114
Foam::fileOperation::defaultFileHandler
static word defaultFileHandler
Default fileHandler.
Definition: fileOperation.H:163
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:137
Foam::fileOperation::objectPath
virtual fileName objectPath(const IOobject &io, const word &typeName) const
Generate disk file name for object. Opposite of filePath.
Definition: fileOperation.C:455
Foam::fileName::null
static const fileName null
An empty fileName.
Definition: fileName.H:97
Foam::fileOperation::addWatch
virtual label addWatch(const fileName &) const
Add watching of a file. Returns handle.
Definition: fileOperation.C:579
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::fileOperation::removeWatch
virtual bool removeWatch(const label) const
Remove watch on a file (using handle)
Definition: fileOperation.C:585
Foam::UPstream::master
static bool master(const label communicator=0)
Am I the master process.
Definition: UPstream.H:438
Foam::fileOperation::setUnmodified
virtual void setUnmodified(const label) const
Set current state of file (using handle) to unmodified.
Definition: fileOperation.C:670
Foam::fileOperation::monitor
fileMonitor & monitor() const
Definition: fileOperation.C:84
Time.H
Foam::autoPtr< Foam::fileOperation >
Foam::regIOobject
regIOobject is an abstract class derived from IOobject to handle automatic object registration with t...
Definition: regIOobject.H:67
Foam::UPstream::msgType
static int & msgType()
Message tag of standard messages.
Definition: UPstream.H:491
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:355
f
labelList f(nPoints)
decomposedBlockData.H
Foam::fileOperation::exists
bool exists(IOobject &io) const
Does ioobject exist. Is either a directory (empty name()) or.
Definition: fileOperation.C:376
Foam::List< instant >
Foam::IOobject::readOpt
readOption readOpt() const
The read option.
Definition: IOobjectI.H:141
Foam::start
label ListType::const_reference const label start
Definition: ListOps.H:408
Foam::IOList< label >
Foam::fileOperation::readObjects
virtual fileNameList readObjects(const objectRegistry &db, const fileName &instance, const fileName &local, word &newInstance) const
Search directory for objects. Used in IOobjectList.
Definition: fileOperation.C:882
Foam::fileName::DIRECTORY
A directory.
Definition: fileName.H:80
path
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
Foam::fileOperation::detectProcessorPath
static label detectProcessorPath(const fileName &)
Detect processor number from '/aa/bb/processorDDD/cc'.
Definition: fileOperation.C:1171
Foam::word::null
static const word null
An empty word.
Definition: word.H:77
Foam::IOobject::MUST_READ_IF_MODIFIED
Definition: IOobject.H:121
Foam::fileOperation::findWatch
virtual label findWatch(const labelList &watchIndices, const fileName &) const
Find index (or -1) of file in list of handles.
Definition: fileOperation.C:592
Foam::IOstreamOption::compressionType
compressionType
Compression treatment (UNCOMPRESSED | COMPRESSED)
Definition: IOstreamOption.H:71
Foam::fileOperation::fileHandlerPtr_
static autoPtr< fileOperation > fileHandlerPtr_
Static fileOperation.
Definition: fileOperation.H:173
Foam::IOobject::writeHeader
bool writeHeader(Ostream &os) const
Write header.
Definition: IOobjectWriteHeader.C:156
registerSwitch.H
Foam::fileOperation::processorsBaseDir
static word processorsBaseDir
Return the processors directory name (usually "processors")
Definition: fileOperation.H:160
Foam::keyType::LITERAL
String literal.
Definition: keyType.H:73
Foam::Ostream
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:56
Foam::fileOperation::lookupAndCacheProcessorsPath
tmpNrc< dirIndexList > lookupAndCacheProcessorsPath(const fileName &, const bool syncPar) const
Lookup name of processorsDDD using cache. Return empty fileName.
Definition: fileOperation.C:238
Foam::Tuple2
A 2-tuple for storing two objects of dissimilar types. The container is similar in purpose to std::pa...
Definition: Tuple2.H:57
rp
regionProperties rp(runTime)
Foam::IOstream::good
bool good() const
Return true if next operation might succeed.
Definition: IOstream.H:216
Foam::IOobject::objectPath
fileName objectPath() const
The complete path + object name.
Definition: IOobjectI.H:185
Foam::List::setSize
void setSize(const label newSize)
Alias for resize(const label)
Definition: ListI.H:146
Foam::TimePaths::constant
const word & constant() const
Return constant name.
Definition: TimePathsI.H:88
Foam::mkDir
bool mkDir(const fileName &pathName, mode_t mode=0777)
Make a directory and return an error if it could not be created.
Definition: MSwindows.C:507
Foam::IOobject::path
fileName path() const
The complete path.
Definition: IOobject.C:456
Foam::debug::optimisationSwitches
dictionary & optimisationSwitches()
The OptimisationSwitches sub-dictionary in the central controlDict(s).
Definition: debug.C:219
Foam::fileOperation::writeObject
virtual bool writeObject(const regIOobject &, IOstream::streamFormat format=IOstream::ASCII, IOstream::versionNumber version=IOstream::currentVersion, IOstream::compressionType compression=IOstream::UNCOMPRESSED, const bool valid=true) const
Writes a regIOobject (so header, contents and divider).
Definition: fileOperation.C:465
Foam::fileOperation::processorsCasePath
fileName processorsCasePath(const IOobject &, const word &procDir) const
Generate path (like io.path) from root+casename with any.
Definition: fileOperation.C:1000
Foam::readDir
fileNameList readDir(const fileName &directory, const fileName::Type type=fileName::FILE, const bool filtergz=true, const bool followLink=true)
Read a directory and return the entries as a fileName List.
Definition: MSwindows.C:707
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:294
Foam::isDir
bool isDir(const fileName &name, const bool followLink=true)
Does the name exist as a DIRECTORY in the file system?
Definition: MSwindows.C:643
Foam::IOobject::MUST_READ
Definition: IOobject.H:120
Foam::decomposedBlockData::numBlocks
static label numBlocks(const fileName &)
Detect number of blocks in a file.
Definition: decomposedBlockData.C:1143
Foam::pos
dimensionedScalar pos(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:177