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-2020 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  defineTypeNameAndDebug(fileOperation, 0);
45  defineRunTimeSelectionTable(fileOperation, word);
46 
48  (
49  debug::optimisationSwitches().getOrAdd<word>
50  (
51  "fileHandler",
52  //Foam::fileOperations::uncollatedFileOperation::typeName,
53  "uncollated",
55  )
56  );
57 }
58 
59 
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_)
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,
467  IOstreamOption streamOpt,
468  const bool valid
469 ) const
470 {
471  if (valid)
472  {
473  fileName pathName(io.objectPath());
474 
475  mkDir(pathName.path());
476 
477  autoPtr<OSstream> osPtr(NewOFstream(pathName, streamOpt));
478 
479  if (!osPtr)
480  {
481  return false;
482  }
483 
484  OSstream& os = osPtr();
485 
486  // If any of these fail, return (leave error handling to Ostream class)
487  if (!os.good())
488  {
489  return false;
490  }
491 
492  if (!io.writeHeader(os))
493  {
494  return false;
495  }
496 
497  // Write the data to the Ostream
498  if (!io.writeData(os))
499  {
500  return false;
501  }
502 
504  }
505  return true;
506 }
507 
508 
510 {
511  if (debug)
512  {
513  Pout<< "fileOperation::filePath :" << " fName:" << fName << endl;
514  }
515 
516  fileName path;
517  fileName pDir;
518  fileName local;
519  label gStart;
520  label gSz;
521  label numProcs;
522  label proci =
523  splitProcessorPath(fName, path, pDir, local, gStart, gSz, numProcs);
524 
525  if (numProcs != -1)
526  {
527  WarningInFunction << "Filename is already adapted:" << fName << endl;
528  }
529 
530  // Give preference to processors variant
531  if (proci != -1)
532  {
533  // Get all processor directories
534  tmpNrc<dirIndexList> procDirs(lookupProcessorsPath(fName));
535  forAll(procDirs(), i)
536  {
537  const fileName& procDir = procDirs()[i].first();
538 
539  fileName collatedName(path/procDir/local);
540  if (exists(collatedName))
541  {
542  if (debug)
543  {
544  Pout<< "fileOperation::filePath : " << collatedName << endl;
545  }
546  return collatedName;
547  }
548  }
549  }
550 
551  if (exists(fName))
552  {
553  if (debug)
554  {
555  Pout<< "fileOperation::filePath : " << fName << endl;
556  }
557  return fName;
558  }
559 
560  if (debug)
561  {
562  Pout<< "fileOperation::filePath : Not found" << endl;
563  }
564  return fileName::null;
565 }
566 
567 
568 Foam::label Foam::fileOperation::addWatch(const fileName& fName) const
569 {
570  return monitor().addWatch(fName);
571 }
572 
573 
574 bool Foam::fileOperation::removeWatch(const label watchIndex) const
575 {
576  return monitor().removeWatch(watchIndex);
577 }
578 
579 
581 (
582  const labelList& watchIndices,
583  const fileName& fName
584 ) const
585 {
586  forAll(watchIndices, i)
587  {
588  if (getFile(watchIndices[i]) == fName)
589  {
590  return i;
591  }
592  }
593  return -1;
594 }
595 
596 
598 (
599  regIOobject& rio,
600  const fileNameList& files
601 ) const
602 {
603  const labelList& watchIndices = rio.watchIndices();
604 
605  DynamicList<label> newWatchIndices;
606  labelHashSet removedWatches(watchIndices);
607 
608  for (const fileName& f : files)
609  {
610  const label index = findWatch(watchIndices, f);
611 
612  if (index == -1)
613  {
614  newWatchIndices.append(addWatch(f));
615  }
616  else
617  {
618  // Existing watch
619  newWatchIndices.append(watchIndices[index]);
620  removedWatches.erase(index);
621  }
622  }
623 
624  // Remove any unused watches
625  for (const label index : removedWatches)
626  {
627  removeWatch(watchIndices[index]);
628  }
629 
630  rio.watchIndices() = newWatchIndices;
631 }
632 
633 
634 Foam::fileName Foam::fileOperation::getFile(const label watchIndex) const
635 {
636  return monitor().getFile(watchIndex);
637 }
638 
639 
641 (
642  const bool masterOnly,
643  const bool syncPar
644 ) const
645 {
646  monitor().updateStates(masterOnly, Pstream::parRun());
647 }
648 
649 
651 (
652  const label watchFd
653 ) const
654 {
655  return monitor().getState(watchFd);
656 }
657 
658 
659 void Foam::fileOperation::setUnmodified(const label watchFd) const
660 {
661  monitor().setUnmodified(watchFd);
662 }
663 
664 
666 (
667  const fileName& directory,
668  const word& constantName
669 ) const
670 {
671  if (debug)
672  {
673  Pout<< "fileOperation::findTimes : Finding times in directory "
674  << directory << endl;
675  }
676 
677  // Read directory entries into a list
678  fileNameList dirEntries
679  (
681  (
682  directory,
684  )
685  );
686 
687  instantList times = sortTimes(dirEntries, constantName);
688 
689 
690  // Get all processor directories
691  tmpNrc<dirIndexList> procDirs(lookupProcessorsPath(directory));
692  forAll(procDirs(), i)
693  {
694  const fileName& procDir = procDirs()[i].first();
695  fileName collDir(processorsPath(directory, procDir));
696  if (!collDir.empty() && collDir != directory)
697  {
698  fileNameList extraEntries
699  (
701  (
702  collDir,
704  )
705  );
706  mergeTimes
707  (
708  sortTimes(extraEntries, constantName),
709  constantName,
710  times
711  );
712  }
713  }
714 
715  if (debug)
716  {
717  Pout<< "fileOperation::findTimes : Found times:" << times << endl;
718  }
719  return times;
720 }
721 
722 
724 (
725  const IOobject& startIO,
726  const scalar startValue,
727  const word& stopInstance
728 ) const
729 {
730  const Time& time = startIO.time();
731 
732  IOobject io(startIO);
733 
734  // Note: - if name is empty, just check the directory itself
735  // - check both for isFile and headerOk since the latter does a
736  // filePath so searches for the file.
737  // - check for an object with local file scope (so no looking up in
738  // parent directory in case of parallel)
739 
740  if (exists(io))
741  {
743  << "Found exact match for \"" << io.name()
744  << "\" in " << io.instance()/io.local()
745  << endl;
746 
747  return io;
748  }
749 
750  // Search back through the time directories to find the first time
751  // that is less than or equal to the current time
752 
753  instantList ts = time.times();
754  label instanceI = ts.size()-1;
755 
756  for (; instanceI >= 0; --instanceI)
757  {
758  if (ts[instanceI].value() <= startValue)
759  {
760  break;
761  }
762  }
763 
764  // Found the time, continue from here
765  for (; instanceI >= 0; --instanceI)
766  {
767  io.instance() = ts[instanceI].name();
768 
769  // Shortcut: if actual directory is the timeName we've already tested it
770  if
771  (
772  io.instance() == startIO.instance()
773  && io.instance() != stopInstance
774  )
775  {
776  continue;
777  }
778 
779  if (exists(io))
780  {
782  << "Found exact match for \"" << io.name()
783  << "\" in " << io.instance()/io.local()
784  << endl;
785 
786  return io;
787  }
788 
789  // Check if hit minimum instance
790  if (io.instance() == stopInstance)
791  {
793  << "Hit stopInstance " << stopInstance << endl;
794 
795  if
796  (
797  startIO.readOpt() == IOobject::MUST_READ
799  )
800  {
801  if (io.name().empty())
802  {
804  << "Cannot find directory "
805  << io.local() << " in times " << startIO.instance()
806  << " down to " << stopInstance
807  << exit(FatalError);
808  }
809  else
810  {
812  << "Cannot find file \"" << io.name()
813  << "\" in directory " << io.local()
814  << " in times " << startIO.instance()
815  << " down to " << stopInstance
816  << exit(FatalError);
817  }
818  }
819 
820  return io;
821  }
822  }
823 
824  // Times usually already includes 'constant' so would have been checked
825  // above.
826  // However, re-test under these conditions:
827  // - Times is empty.
828  // Sometimes this can happen (eg, decomposePar with collated)
829  // - Times[0] is not constant
830  // - The startValue is negative (eg, kivaTest).
831  // This plays havoc with the reverse search, causing it to miss 'constant'
832 
833  if
834  (
835  ts.empty()
836  || ts.first().name() != time.constant()
837  || startValue < 0
838  )
839  {
840  io.instance() = time.constant();
841  if (exists(io))
842  {
844  << "Found constant match for \"" << io.name()
845  << "\" in " << io.instance()/io.local()
846  << endl;
847 
848  return io;
849  }
850  }
851 
852 
853  if
854  (
855  startIO.readOpt() == IOobject::MUST_READ
857  )
858  {
860  << "Cannot find file \"" << io.name() << "\" in directory "
861  << io.local() << " in times " << startIO.instance()
862  << " down to " << time.constant()
863  << exit(FatalError);
864  }
865 
866  return io;
867 }
868 
869 
871 (
872  const objectRegistry& db,
873  const fileName& instance,
874  const fileName& local,
875  word& newInstance
876 ) const
877 {
878  if (debug)
879  {
880  Pout<< "fileOperation::readObjects :"
881  << " db:" << db.objectPath()
882  << " instance:" << instance << endl;
883  }
884 
885  fileName path(db.path(instance, db.dbDir()/local));
886 
887  newInstance = word::null;
888  fileNameList objectNames;
889 
890  if (Foam::isDir(path))
891  {
892  newInstance = instance;
893  objectNames = Foam::readDir(path, fileName::FILE);
894  }
895  else
896  {
897  // Get processors equivalent of path
898  fileName procsPath(filePath(path));
899 
900  if (!procsPath.empty())
901  {
902  newInstance = instance;
903  objectNames = Foam::readDir(procsPath, fileName::FILE);
904  }
905  }
906  return objectNames;
907 }
908 
909 
910 void Foam::fileOperation::setNProcs(const label nProcs)
911 {}
912 
913 
914 Foam::label Foam::fileOperation::nProcs
915 (
916  const fileName& dir,
917  const fileName& local
918 ) const
919 {
920  label nProcs = 0;
921  if (Pstream::master(comm_))
922  {
923  fileNameList dirNames(Foam::readDir(dir, fileName::Type::DIRECTORY));
924 
925  // Detect any processorsDDD or processorDDD
926  label maxProc = -1;
927  forAll(dirNames, i)
928  {
929  const fileName& dirN = dirNames[i];
930 
931  fileName path, pDir, local;
932  label start, size, n;
933  maxProc = max
934  (
935  maxProc,
936  splitProcessorPath(dirN, path, pDir, local, start, size, n)
937  );
938  if (n != -1)
939  {
940  // Direct detection of processorsDDD
941  maxProc = n-1;
942  break;
943  }
944  }
945  nProcs = maxProc+1;
946 
947 
948  if (nProcs == 0 && Foam::isDir(dir/processorsBaseDir))
949  {
950  fileName pointsFile
951  (
952  dir
953  /processorsBaseDir
954  /"constant"
955  /local
957  /"points"
958  );
959 
960  if (Foam::isFile(pointsFile))
961  {
962  nProcs = decomposedBlockData::numBlocks(pointsFile);
963  }
964  else
965  {
966  WarningInFunction << "Cannot read file " << pointsFile
967  << " to determine the number of decompositions."
968  << " Returning 1" << endl;
969  }
970  }
971  }
972  Pstream::scatter(nProcs, Pstream::msgType(), comm_);
973  return nProcs;
974 }
975 
976 
978 {
979  if (debug)
980  {
981  Pout<< "fileOperation::flush : clearing processor directories cache"
982  << endl;
983  }
984  procsDirs_.clear();
985 }
986 
987 
989 (
990  const IOobject& io,
991  const word& procsDir
992 ) const
993 {
994  return io.rootPath()/io.time().globalCaseName()/procsDir;
995 }
996 
997 
999 (
1000  const IOobject& io,
1001  const word& instance,
1002  const word& procsDir
1003 ) const
1004 {
1005  return
1006  processorsCasePath(io, procsDir)
1007  /instance
1008  /io.db().dbDir()
1009  /io.local();
1010 }
1011 
1012 
1015  const fileName& dir,
1016  const word& procsDir
1017 ) const
1018 {
1019  // Check if directory is processorDDD
1020  word caseName(dir.name());
1021 
1022  std::string::size_type pos = caseName.find("processor");
1023  if (pos == 0)
1024  {
1025  if (caseName.size() <= 9 || caseName[9] == 's')
1026  {
1027  WarningInFunction << "Directory " << dir
1028  << " does not end in old-style processorDDD" << endl;
1029  }
1030 
1031  return dir.path()/procsDir;
1032  }
1033 
1034  return fileName::null;
1035 }
1036 
1037 
1040  const fileName& objectPath,
1041  fileName& path,
1042  fileName& procDir,
1043  fileName& local,
1044 
1045  label& groupStart,
1046  label& groupSize,
1047 
1048  label& nProcs
1049 )
1050 {
1051  path.clear();
1052  procDir.clear();
1053  local.clear();
1054 
1055  // Potentially detected start of number of processors in local group
1056  groupStart = -1;
1057  groupSize = 0;
1058 
1059  // Potentially detected number of processors
1060  nProcs = -1;
1061 
1062  // Search for processor at start of line or /processor
1063  std::string::size_type pos = objectPath.find("processor");
1064  if (pos == string::npos)
1065  {
1066  return -1;
1067  }
1068 
1069  // "processorDDD"
1070  // "processorsNNN"
1071  // "processorsNNN_AA-BB"
1072 
1073 
1074  if (pos > 0 && objectPath[pos-1] != '/')
1075  {
1076  // Directory not starting with "processor" e.g. "somenamewithprocessor"
1077  return -1;
1078  }
1079 
1080  procDir = objectPath;
1081 
1082  // Strip leading directory
1083  if (pos > 0)
1084  {
1085  path = objectPath.substr(0, pos-1);
1086  procDir = objectPath.substr(pos);
1087  }
1088 
1089  // Strip trailing local directory
1090  pos = procDir.find('/');
1091  if (pos != string::npos)
1092  {
1093  local = procDir.substr(pos+1);
1094  procDir = procDir.substr(0, pos);
1095  }
1096 
1097  // Now procDir is e.g.
1098  // - processor0
1099  // - processors0
1100  // - processorBananas
1101 
1102  // Look for number after "processor"
1103 
1104  fileName f(procDir.substr(9));
1105 
1106  if (f.size() && f[0] == 's')
1107  {
1108  // "processsorsNNN"
1109 
1110  f = f.substr(1);
1111 
1112  // Detect "processorsNNN_AA-BB"
1113  {
1114  std::string::size_type fromStart = f.find("_");
1115  std::string::size_type toStart = f.find("-");
1116  if (fromStart != string::npos && toStart != string::npos)
1117  {
1118  string nProcsName(f.substr(0, fromStart));
1119  string fromName(f.substr(fromStart+1, toStart-(fromStart+1)));
1120  string toName(f.substr(toStart+1));
1121 
1122  label groupEnd = -1;
1123  if
1124  (
1125  Foam::read(fromName.c_str(), groupStart)
1126  && Foam::read(toName.c_str(), groupEnd)
1127  && Foam::read(nProcsName.c_str(), nProcs)
1128  )
1129  {
1130  groupSize = groupEnd-groupStart+1;
1131  return -1;
1132  }
1133  }
1134  }
1135 
1136  // Detect "processorsN"
1137  label n;
1138  if (Foam::read(f.c_str(), n))
1139  {
1140  nProcs = n;
1141  }
1142  return -1;
1143  }
1144  else
1145  {
1146  // Detect "processorN"
1147  label proci;
1148  if (Foam::read(f.c_str(), proci))
1149  {
1150  return proci;
1151  }
1152  else
1153  {
1154  return -1;
1155  }
1156  }
1157 }
1158 
1159 
1161 {
1162  fileName path, pDir, local;
1163  label start, size, nProcs;
1164  return splitProcessorPath(fName, path, pDir, local, start, size, nProcs);
1165 }
1166 
1167 
1168 // * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
1169 
1171 {
1173  {
1174  word handler(getEnv("FOAM_FILEHANDLER"));
1175 
1176  if (handler.empty())
1177  {
1179  }
1180 
1182  }
1183 
1185 }
1186 
1187 
1189 {
1190  if
1191  (
1192  newHandler
1194  && newHandler->type() == fileOperation::fileHandlerPtr_->type()
1195  )
1196  {
1197  return;
1198  }
1199 
1200  fileOperation::fileHandlerPtr_ = std::move(newHandler);
1201 }
1202 
1203 
1204 // ************************************************************************* //
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
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:57
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:70
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:77
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:999
Foam::fileOperation::fileHandlerPtr_
static autoPtr< fileOperation > fileHandlerPtr_
Static fileOperation.
Definition: fileOperation.H:175
Foam::fileOperation::addWatches
virtual void addWatches(regIOobject &, const fileNameList &) const
Helper: add watches for list of regIOobjects.
Definition: fileOperation.C:598
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:155
Foam::DynamicList
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition: DynamicList.H:55
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:455
Foam::IOobject::instance
const fileName & instance() const
Definition: IOobjectI.H:191
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:107
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:415
Foam::fileOperation::pathTypeNames_
static const Enum< pathType > pathTypeNames_
Definition: fileOperation.H:99
Foam::fileOperation::flush
virtual void flush() const
Forcibly wait until all output done. Flush any cached data.
Definition: fileOperation.C:977
objectRegistry.H
Foam::IOobject::fileModificationChecking
static fileCheckTypes fileModificationChecking
Type of file modification checking.
Definition: IOobject.H:211
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:1039
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:73
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:1170
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:350
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:910
Foam::Pout
prefixOSstream Pout
An Ostream wrapper for parallel output to std::cout.
Foam::decomposedBlockData::numBlocks
static label numBlocks(const fileName &fName)
Detect number of blocks in a file.
Definition: decomposedBlockData.C:1087
polyMesh.H
Foam::HashSet< label, Hash< label > >
Foam::IOobject::time
const Time & time() const
Return time.
Definition: IOobject.C:449
Foam::fileOperation::updateStates
virtual void updateStates(const bool masterOnly, const bool syncPar) const
Update state of all files.
Definition: fileOperation.C:641
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:666
Foam::sumOp
Definition: ops.H:213
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::fileOperation::getFile
virtual fileName getFile(const label) const
Get name of file being watched (using handle)
Definition: fileOperation.C:634
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:724
Foam::IOobject::db
const objectRegistry & db() const
Return the local objectRegistry.
Definition: IOobject.C:443
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:203
Foam::fileOperation::lookupProcessorsPath
virtual tmpNrc< dirIndexList > lookupProcessorsPath(const fileName &) const
Lookup name of processorsDDD using cache. Return empty fileName.
Definition: fileOperation.C:369
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:360
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:915
argList.H
Foam::List::transfer
void transfer(List< T > &list)
Definition: List.C:459
Foam::fileMonitor
Checking for changes to files.
Definition: fileMonitor.H:66
Foam::sort
void sort(UList< T > &a)
Definition: UList.C:254
Foam::TimePaths::times
instantList times() const
Search the case for valid time directories.
Definition: TimePaths.C:149
Foam::IOstreamOption
The IOstreamOption is a simple container for options an IOstream can normally have.
Definition: IOstreamOption.H:63
Foam::fileOperation::writeObject
virtual bool writeObject(const regIOobject &io, IOstreamOption streamOpt=IOstreamOption(), const bool valid=true) const
Writes a regIOobject (so header, contents and divider).
Definition: fileOperation.C:465
Foam::fileOperation::getState
virtual fileMonitor::fileState getState(const label) const
Get current state of file (using handle)
Definition: fileOperation.C:651
Foam::OSstream
Generic output stream using a standard (STL) stream.
Definition: OSstream.H:54
size_type
graph_traits< Graph >::vertices_size_type size_type
Definition: SloanRenumber.C:76
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::FatalError
error FatalError
FatalErrorInLookup
#define FatalErrorInLookup(lookupTag, lookupName, lookupTable)
Report an error message using Foam::FatalError.
Definition: error.H:376
fileOperation.H
Foam::fileOperation::monitorPtr_
autoPtr< fileMonitor > monitorPtr_
file-change monitor for all registered files
Definition: fileOperation.H:116
Foam::fileOperation::defaultFileHandler
static word defaultFileHandler
Default fileHandler.
Definition: fileOperation.H:165
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:568
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:574
Foam::UPstream::master
static bool master(const label communicator=0)
Am I the master process.
Definition: UPstream.H:439
Foam::fileOperation::setUnmodified
virtual void setUnmodified(const label) const
Set current state of file (using handle) to unmodified.
Definition: fileOperation.C:659
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:68
Foam::UPstream::msgType
static int & msgType()
Message tag of standard messages.
Definition: UPstream.H:492
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:372
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:165
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:871
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:1160
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:581
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:162
Foam::keyType::LITERAL
String literal.
Definition: keyType.H:73
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:224
Foam::IOobject::objectPath
fileName objectPath() const
The complete path + object name.
Definition: IOobjectI.H:209
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:467
Foam::debug::optimisationSwitches
dictionary & optimisationSwitches()
The OptimisationSwitches sub-dictionary in the central controlDict(s).
Definition: debug.C:219
Foam::fileOperation::processorsCasePath
fileName processorsCasePath(const IOobject &, const word &procDir) const
Generate path (like io.path) from root+casename with any.
Definition: fileOperation.C:989
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:298
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::pos
dimensionedScalar pos(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:177