fileOperation.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2017-2022 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "fileOperation.H"
27 #include "decomposedBlockData.H"
28 #include "polyMesh.H"
29 #include "Time.H"
30 #include "OSspecific.H"
31 
32 /* * * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * */
33 
34 namespace Foam
35 {
36  autoPtr<fileOperation> fileOperation::fileHandlerPtr_;
37 
38  defineTypeNameAndDebug(fileOperation, 0);
39  defineRunTimeSelectionTable(fileOperation, word);
40 
41  template<>
42  const char* Foam::NamedEnum
43  <
45  12
46  >::names[] =
47  {
48  "notFound",
49  "absolute",
50  "objectPath",
51  "writeObject",
52  "uncollatedProc",
53  "globalProc",
54  "localProc",
55  "parentObjectPath",
56  "findInstance",
57  "uncollatedProcInstance",
58  "globalProcInstance",
59  "localProcInstance"
60  };
62 
64  (
65  debug::optimisationSwitches().lookupOrAddDefault
66  (
67  "fileHandler",
68  // Foam::fileOperations::uncollatedFileOperation::typeName,
69  word("uncollated"),
70  false,
71  false
72  )
73  );
74 
76 }
77 
78 
79 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
80 
82 {
83  if (!monitorPtr_.valid())
84  {
85  monitorPtr_.reset
86  (
87  new fileMonitor
88  (
91  )
92  );
93  }
94  return monitorPtr_();
95 }
96 
97 
99 (
100  const fileNameList& dirEntries,
101  const word& constantName
102 )
103 {
104  // Initialise instant list
105  instantList Times(dirEntries.size() + 1);
106  label nTimes = 0;
107 
108  // Check for "constant"
109  bool haveConstant = false;
110  forAll(dirEntries, i)
111  {
112  if (dirEntries[i] == constantName)
113  {
114  Times[nTimes].value() = 0;
115  Times[nTimes].name() = dirEntries[i];
116  nTimes++;
117  haveConstant = true;
118  break;
119  }
120  }
121 
122  // Read and parse all the entries in the directory
123  forAll(dirEntries, i)
124  {
125  scalar timeValue;
126  if (readScalar(dirEntries[i].c_str(), timeValue))
127  {
128  Times[nTimes].value() = timeValue;
129  Times[nTimes].name() = dirEntries[i];
130  nTimes++;
131  }
132  }
133 
134  // Reset the length of the times list
135  Times.setSize(nTimes);
136 
137  if (haveConstant)
138  {
139  if (nTimes > 2)
140  {
141  std::sort(&Times[1], Times.end(), instant::less());
142  }
143  }
144  else if (nTimes > 1)
145  {
146  std::sort(&Times[0], Times.end(), instant::less());
147  }
148 
149  return Times;
150 }
151 
152 
154 (
155  const instantList& extraTimes,
156  const word& constantName,
157  instantList& times
158 )
159 {
160  if (extraTimes.size())
161  {
162  bool haveConstant =
163  (
164  times.size() > 0
165  && times[0].name() == constantName
166  );
167 
168  bool haveExtraConstant =
169  (
170  extraTimes.size() > 0
171  && extraTimes[0].name() == constantName
172  );
173 
174  // Combine times
175  instantList combinedTimes(times.size()+extraTimes.size());
176  label sz = 0;
177  label extrai = 0;
178  if (haveExtraConstant)
179  {
180  extrai = 1;
181  if (!haveConstant)
182  {
183  combinedTimes[sz++] = extraTimes[0]; // constant
184  }
185  }
186  forAll(times, i)
187  {
188  combinedTimes[sz++] = times[i];
189  }
190  for (; extrai < extraTimes.size(); extrai++)
191  {
192  combinedTimes[sz++] = extraTimes[extrai];
193  }
194  combinedTimes.setSize(sz);
195  times.transfer(combinedTimes);
196 
197  // Sort
198  if (times.size() > 1)
199  {
200  label starti = 0;
201  if (times[0].name() == constantName)
202  {
203  starti = 1;
204  }
205  std::sort(&times[starti], times.end(), instant::less());
206 
207  // Filter out duplicates
208  label newi = starti+1;
209  for (label i = newi; i < times.size(); i++)
210  {
211  if (times[i].value() != times[i-1].value())
212  {
213  if (newi != i)
214  {
215  times[newi] = times[i];
216  }
217  newi++;
218  }
219  }
220 
221  times.setSize(newi);
222  }
223  }
224 }
225 
226 
228 {
229  return
230  (isFile && Foam::isFile(f))
231  || (!isFile && Foam::isDir(f));
232 }
233 
234 
237 {
238  // If path is local to a processor (e.g. contains 'processor2')
239  // find the corresponding actual processor directory (e.g. 'processors4')
240  // and index (2)
241 
242  fileName path;
243  fileName pDir;
244  fileName local;
245  label gStart;
246  label gSz;
247  label numProcs;
248  label proci =
249  splitProcessorPath(fName, path, pDir, local, gStart, gSz, numProcs);
250 
251  if (proci != -1)
252  {
253  const fileName procPath(path/pDir);
254 
256  procsDirs_.find(procPath);
257 
258  if (iter != procsDirs_.end())
259  {
260  return iter();
261  }
262 
263  // Read all directories to see any beginning with processor
264  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
265 
266  DynamicList<dirIndex> procDirs;
267 
268  // Note: use parallel synchronised reading so cache will be same
269  // order on all processors
270  fileNameList dirNames(readDir(path, fileType::directory));
271 
272  // Extract info from processorsDDD or processorDDD:
273  // - highest processor number
274  // - directory+offset containing data for proci
275  label maxProc = -1;
276 
277  forAll(dirNames, i)
278  {
279  const fileName& dirN = dirNames[i];
280 
281  // Analyse directory name
282  fileName rp, rd, rl;
283  label rStart, rSize, rNum;
284  label readProci =
285  splitProcessorPath(dirN, rp, rd, rl, rStart, rSize, rNum);
286  maxProc = max(maxProc, readProci);
287 
288  if (proci == readProci)
289  {
290  // Found "processorDDD". No need for index.
291  procDirs.append
292  (
293  dirIndex
294  (
295  dirN,
296  Tuple2<pathType, label>(PROCUNCOLLATED, -1)
297  )
298  );
299  }
300  else if (proci >= rStart && proci < rStart+rSize)
301  {
302  // "processorsDDD_start-end"
303  // Found the file that contains the data for proci
304  procDirs.append
305  (
306  dirIndex
307  (
308  dirN,
309  Tuple2<pathType, label>(PROCOBJECT, proci-rStart)
310  )
311  );
312  }
313  if (rNum != -1)
314  {
315  // Direct detection of processorsDDD
316  maxProc = rNum-1;
317 
318  if (rStart == -1)
319  {
320  // "processorsDDD"
321  procDirs.append
322  (
323  dirIndex
324  (
325  dirN,
326  Tuple2<pathType, label>(PROCBASEOBJECT, proci)
327  )
328  );
329  }
330  }
331  }
332  if (!Pstream::parRun())
333  {
334  // If (as a side effect) we found the number of decompositions
335  // use it
336  if (maxProc != -1)
337  {
338  const_cast<fileOperation&>(*this).setNProcs(maxProc+1);
339  }
340  }
341 
342  if (returnReduce(procDirs.size(), sumOp<label>()))
343  {
344  procsDirs_.insert(procPath, procDirs);
345 
346  if (debug)
347  {
348  Pout<< "fileOperation::lookupProcessorsPath : For:" << procPath
349  << " detected:" << procDirs << endl;
350  }
351 
352  // Make sure to return a reference
353  return procsDirs_[procPath];
354  }
355  }
356  return tmpNrc<dirIndexList>(new dirIndexList(0, dirIndex()));
357 }
358 
359 
361 {
362  // Generate output filename for object
363  fileName objPath(objectPath(io, word::null));
364 
365  // Test for either directory or a (valid) file & IOobject
366  bool ok;
367  if (io.name().empty())
368  {
369  ok = isDir(objPath);
370  }
371  else
372  {
373  // IOobject::headerOk assumes local scope
374  ok = isFile(objPath) && io.headerOk();
375  }
376 
377  if (!ok)
378  {
379  // Re-test with searched for objectPath. This is for backwards
380  // compatibility
381  fileName originalPath(filePath(io.objectPath(false)));
382  if (originalPath != objPath)
383  {
384  // Test for either directory or a (valid) file & IOobject
385  if (io.name().empty())
386  {
387  ok = isDir(originalPath);
388  }
389  else
390  {
391  // IOobject::headerOk assumes local scope
392  ok = isFile(originalPath) && io.headerOk();
393  }
394  }
395  }
396 
397  return ok;
398 }
399 
400 
401 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
402 
404 :
405  comm_(comm)
406 {}
407 
408 
410 (
411  const word& type,
412  const bool verbose
413 )
414 {
415  wordConstructorTable::iterator cstrIter =
416  wordConstructorTablePtr_->find(type);
417 
418  if (cstrIter == wordConstructorTablePtr_->end())
419  {
421  << "Unknown fileOperation type "
422  << type << nl << nl
423  << "Valid fileOperation types are" << endl
424  << wordConstructorTablePtr_->sortedToc()
425  << abort(FatalError);
426  }
427 
428  return autoPtr<fileOperation>(cstrIter()(verbose));
429 }
430 
431 
432 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
433 
435 {}
436 
437 
438 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
439 
441 (
442  const IOobject& io,
443  const word& typeName
444 ) const
445 {
446  return io.objectPath(false);
447 }
448 
449 
451 (
452  const regIOobject& io,
456  const bool write
457 ) const
458 {
459  if (write)
460  {
461  const fileName filePath(io.objectPath());
462 
463  mkDir(filePath.path());
464 
465  autoPtr<Ostream> osPtr
466  (
468  (
469  filePath,
470  fmt,
471  ver,
472  cmp
473  )
474  );
475 
476  if (!osPtr.valid())
477  {
478  return false;
479  }
480 
481  Ostream& os = osPtr();
482 
483  // If any of these fail, return (leave error handling to Ostream class)
484  if (!os.good())
485  {
486  return false;
487  }
488 
489  if (!io.writeHeader(os))
490  {
491  return false;
492  }
493 
494  // Write the data to the Ostream
495  if (!io.writeData(os))
496  {
497  return false;
498  }
499 
501  }
502 
503  return true;
504 }
505 
506 
508 {
509  if (debug)
510  {
511  Pout<< "fileOperation::filePath :" << " fName:" << fName << endl;
512  }
513 
514  fileName path;
515  fileName pDir;
516  fileName local;
517  label gStart;
518  label gSz;
519  label numProcs;
520  label proci =
521  splitProcessorPath(fName, path, pDir, local, gStart, gSz, numProcs);
522 
523  if (numProcs != -1)
524  {
525  WarningInFunction << "Filename is already adapted:" << fName << endl;
526  }
527 
528  // Give preference to processors variant
529  if (proci != -1)
530  {
531  // Get all processor directories
533  forAll(procDirs(), i)
534  {
535  const fileName& procDir = procDirs()[i].first();
536 
537  fileName collatedName(path/procDir/local);
538  if (exists(collatedName))
539  {
540  if (debug)
541  {
542  Pout<< "fileOperation::filePath : " << collatedName << endl;
543  }
544  return collatedName;
545  }
546  }
547  }
548 
549  if (exists(fName))
550  {
551  if (debug)
552  {
553  Pout<< "fileOperation::filePath : " << fName << endl;
554  }
555  return fName;
556  }
557  else
558  {
559  if (debug)
560  {
561  Pout<< "fileOperation::filePath : Not found" << endl;
562  }
563  return fileName::null;
564  }
565 }
566 
567 
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  forAll(files, i)
609  {
610  const fileName& f = files[i];
611  label index = findWatch(watchIndices, f);
612 
613  if (index == -1)
614  {
615  newWatchIndices.append(addWatch(f));
616  }
617  else
618  {
619  // Existing watch
620  newWatchIndices.append(watchIndices[index]);
621  removedWatches.erase(index);
622  }
623  }
624 
625  // Remove any unused watches
626  forAllConstIter(labelHashSet, removedWatches, iter)
627  {
628  removeWatch(watchIndices[iter.key()]);
629  }
630 
631  rio.watchIndices() = newWatchIndices;
632 }
633 
634 
636 {
637  return monitor().getFile(watchIndex);
638 }
639 
640 
642 (
643  const bool masterOnly,
644  const bool syncPar
645 ) const
646 {
647  monitor().updateStates(masterOnly, Pstream::parRun());
648 }
649 
650 
652 (
653  const label watchFd
654 ) const
655 {
656  return monitor().getState(watchFd);
657 }
658 
659 
660 void Foam::fileOperation::setUnmodified(const label watchFd) const
661 {
662  monitor().setUnmodified(watchFd);
663 }
664 
665 
667 (
668  const fileName& directory,
669  const word& constantName
670 ) const
671 {
672  if (debug)
673  {
674  Pout<< "fileOperation::findTimes : Finding times in directory "
675  << directory << endl;
676  }
677 
678  // Read directory entries into a list
679  fileNameList dirEntries
680  (
682  (
683  directory,
685  )
686  );
687 
688  instantList times = sortTimes(dirEntries, constantName);
689 
690 
691  // Get all processor directories
692  tmpNrc<dirIndexList> procDirs(lookupProcessorsPath(directory));
693  forAll(procDirs(), i)
694  {
695  const fileName& procDir = procDirs()[i].first();
696  fileName collDir(processorsPath(directory, procDir));
697  if (!collDir.empty() && collDir != directory)
698  {
699  fileNameList extraEntries
700  (
702  (
703  collDir,
705  )
706  );
707  mergeTimes
708  (
709  sortTimes(extraEntries, constantName),
710  constantName,
711  times
712  );
713  }
714  }
715 
716  if (debug)
717  {
718  Pout<< "fileOperation::findTimes : Found times:" << times << endl;
719  }
720  return times;
721 }
722 
723 
725 (
726  const IOobject& startIO,
727  const scalar startValue,
728  const word& stopInstance
729 ) const
730 {
731  const Time& time = startIO.time();
732 
733  IOobject io(startIO);
734 
735  // Note: - if name is empty, just check the directory itself
736  // - check both for isFile and headerOk since the latter does a
737  // filePath so searches for the file.
738  // - check for an object with local file scope (so no looking up in
739  // parent directory in case of parallel)
740 
741  if (exists(io))
742  {
743  if (debug)
744  {
746  << "Found exact match for \"" << io.name()
747  << "\" in " << io.instance()/io.local()
748  << endl;
749  }
750 
751  return io;
752  }
753 
754  // Search back through the time directories to find the time
755  // closest to and lower than current time
756 
757  instantList ts = time.times();
758  label instanceI;
759 
760  for (instanceI = ts.size()-1; instanceI >= 0; --instanceI)
761  {
762  if
763  (
764  ts[instanceI].name() == time.constant()
765  || ts[instanceI].value() <= startValue
766  )
767  {
768  break;
769  }
770  }
771 
772  // continue searching from here
773  for (; instanceI >= 0; --instanceI)
774  {
775  // Shortcut: if actual directory is the timeName we've already tested it
776  if
777  (
778  ts[instanceI].name() == startIO.instance()
779  && ts[instanceI].name() != stopInstance
780  )
781  {
782  continue;
783  }
784 
785  io.instance() = ts[instanceI].name();
786  if (exists(io))
787  {
788  if (debug)
789  {
791  << "Found exact match for \"" << io.name()
792  << "\" in " << io.instance()/io.local()
793  << endl;
794  }
795 
796  return io;
797  }
798 
799  // Check if hit minimum instance
800  if (ts[instanceI].name() == stopInstance)
801  {
802  if (debug)
803  {
805  << "Hit stopInstance " << stopInstance << endl;
806  }
807 
808  if
809  (
810  startIO.readOpt() == IOobject::MUST_READ
812  )
813  {
814  if (io.name().empty())
815  {
817  << "Cannot find directory "
818  << io.local() << " in times " << startIO.instance()
819  << " down to " << stopInstance
820  << exit(FatalError);
821  }
822  else
823  {
825  << "Cannot find file \"" << io.name()
826  << "\" in directory " << io.local()
827  << " in times " << startIO.instance()
828  << " down to " << stopInstance
829  << exit(FatalError);
830  }
831  }
832 
833  return io;
834  }
835  }
836 
837  // times() usually already includes the constant() so would have been
838  // checked above. Re-test if
839  // - times() is empty. Sometimes this can happen (e.g. decomposePar with
840  // collated)
841  // - times()[0] is not constant
842  if (!ts.size() || ts[0].name() != time.constant())
843  {
844  // Note. This needs to be a hard-coded constant, rather than the
845  // constant function of the time, because the latter points to
846  // the case constant directory in parallel cases
847 
848  io.instance() = time.constant();
849  if (exists(io))
850  {
851  if (debug)
852  {
854  << "Found constant match for \"" << io.name()
855  << "\" in " << io.instance()/io.local()
856  << endl;
857  }
858  return io;
859  }
860  }
861 
862 
863  if
864  (
865  startIO.readOpt() == IOobject::MUST_READ
867  )
868  {
870  << "Cannot find file \"" << io.name() << "\" in directory "
871  << io.local() << " in times " << startIO.instance()
872  << " down to " << time.constant()
873  << exit(FatalError);
874  }
875 
876  return io;
877 }
878 
879 
881 (
882  const objectRegistry& db,
883  const fileName& instance,
884  const fileName& local,
885  word& newInstance
886 ) const
887 {
888  if (debug)
889  {
890  Pout<< "fileOperation::readObjects :"
891  << " db:" << db.objectPath()
892  << " instance:" << instance << endl;
893  }
894 
895  fileName path(db.path(instance, local));
896 
897  newInstance = word::null;
898  fileNameList objectNames;
899 
900  if (Foam::isDir(path))
901  {
902  newInstance = instance;
903  objectNames = Foam::readDir(path, fileType::file);
904  }
905  else
906  {
907  // Get processors equivalent of path
908  fileName procsPath(filePath(path));
909 
910  if (!procsPath.empty())
911  {
912  newInstance = instance;
913  objectNames = Foam::readDir(procsPath, fileType::file);
914  }
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  {
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
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  }
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  else
1045  {
1046  return fileName::null;
1047  }
1048 }
1049 
1050 
1053  const fileName& objectPath,
1054  fileName& path,
1055  fileName& procDir,
1056  fileName& local,
1057 
1058  label& groupStart,
1059  label& groupSize,
1060 
1061  label& nProcs
1062 )
1063 {
1064  path.clear();
1065  procDir.clear();
1066  local.clear();
1067 
1068  // Potentially detected start of number of processors in local group
1069  groupStart = -1;
1070  groupSize = 0;
1071 
1072  // Potentially detected number of processors
1073  nProcs = -1;
1074 
1075  // Search for processor at start of line or /processor
1076  std::string::size_type pos = objectPath.find("processor");
1077  if (pos == string::npos)
1078  {
1079  return -1;
1080  }
1081 
1082  // "processorDDD"
1083  // "processorsNNN"
1084  // "processorsNNN_AA-BB"
1085 
1086 
1087  if (pos > 0 && objectPath[pos-1] != '/')
1088  {
1089  // Directory not starting with "processor" e.g. "somenamewithprocessor"
1090  return -1;
1091  }
1092 
1093  procDir = objectPath;
1094 
1095  // Strip leading directory
1096  if (pos > 0)
1097  {
1098  path = objectPath.substr(0, pos-1);
1099  procDir = objectPath.substr(pos);
1100  }
1101 
1102  // Strip trailing local directory
1103  pos = procDir.find('/');
1104  if (pos != string::npos)
1105  {
1106  local = procDir.substr(pos+1);
1107  procDir = procDir.substr(0, pos);
1108  }
1109 
1110  // Now procDir is e.g.
1111  // - processor0
1112  // - processors0
1113  // - processorBananas
1114 
1115  // Look for number after "processor"
1116 
1117  fileName f(procDir.substr(9));
1118 
1119  if (f.size() && f[0] == 's')
1120  {
1121  // "processorsNNN"
1122 
1123  f = f.substr(1);
1124 
1125  // Detect "processorsNNN_AA-BB"
1126  {
1127  std::string::size_type fromStart = f.find("_");
1128  std::string::size_type toStart = f.find("-");
1129  if (fromStart != string::npos && toStart != string::npos)
1130  {
1131  string nProcsName(f.substr(0, fromStart));
1132  string fromName(f.substr(fromStart+1, toStart-(fromStart+1)));
1133  string toName(f.substr(toStart+1));
1134 
1135  label groupEnd = -1;
1136  if
1137  (
1138  Foam::read(fromName.c_str(), groupStart)
1139  && Foam::read(toName.c_str(), groupEnd)
1140  && Foam::read(nProcsName.c_str(), nProcs)
1141  )
1142  {
1143  groupSize = groupEnd-groupStart+1;
1144  return -1;
1145  }
1146  }
1147  }
1148 
1149  // Detect "processorsN"
1150  label n;
1151  if (Foam::read(f.c_str(), n))
1152  {
1153  nProcs = n;
1154  }
1155  return -1;
1156  }
1157  else
1158  {
1159  // Detect "processorN"
1160  label proci;
1161  if (Foam::read(f.c_str(), proci))
1162  {
1163  return proci;
1164  }
1165  else
1166  {
1167  return -1;
1168  }
1169  }
1170 }
1171 
1172 
1174 {
1175  fileName path, pDir, local;
1176  label start, size, nProcs;
1177  return splitProcessorPath(fName, path, pDir, local, start, size, nProcs);
1178 }
1179 
1180 
1181 // * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
1182 
1184 {
1185  if (!fileOperation::fileHandlerPtr_.valid())
1186  {
1187  word handler(getEnv("FOAM_FILEHANDLER"));
1188 
1189  if (!handler.size())
1190  {
1192  }
1193 
1195  }
1197 }
1198 
1199 
1201 {
1202  if (fileOperation::fileHandlerPtr_.valid())
1203  {
1204  if
1205  (
1206  newHandlerPtr.valid()
1207  && newHandlerPtr->type() == fileOperation::fileHandlerPtr_->type()
1208  )
1209  {
1210  return;
1211  }
1212  }
1214 
1215  if (newHandlerPtr.valid())
1216  {
1217  fileOperation::fileHandlerPtr_ = newHandlerPtr;
1218  }
1219 }
1220 
1221 
1222 Foam::fileName Foam::search(const word& file, const fileName& directory)
1223 {
1224  // Search the current directory for the file
1225  fileNameList files(fileHandler().readDir(directory));
1226  forAll(files, i)
1227  {
1228  if (files[i] == file)
1229  {
1230  return directory/file;
1231  }
1232  }
1233 
1234  // If not found search each of the sub-directories
1236  forAll(dirs, i)
1237  {
1238  fileName path = search(file, directory/dirs[i]);
1239  if (path != fileName::null)
1240  {
1241  return path;
1242  }
1243  }
1244 
1245  return fileName::null;
1246 }
1247 
1248 
1249 void Foam::cpFiles(const fileName& srcDir, const fileName& targetDir)
1250 {
1251  mkDir(targetDir);
1252 
1253  const fileNameList srcFiles(readDir(srcDir, fileType::file, true));
1254 
1255  forAll(srcFiles, filei)
1256  {
1257  cp(srcDir/srcFiles[filei], targetDir);
1258  }
1259 }
1260 
1261 
1262 // ************************************************************************* //
pathType
Enumeration for the location of an IOobject.
Definition: fileOperation.H:61
string getEnv(const word &)
Return environment variable of given name.
Definition: POSIX.C:97
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
const word & name() const
Return name.
Definition: IOobject.H:315
A class for handling file names.
Definition: fileName.H:79
An STL-conforming const_iterator.
Definition: HashTable.H:481
virtual fileMonitor::fileState getState(const label) const
Get current state of file (using handle)
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
error FatalError
Checking for changes to files.
Definition: fileMonitor.H:61
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:306
#define forAllConstIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:477
A 2-tuple for storing two objects of different types.
Definition: HashTable.H:65
void cpFiles(const fileName &srcDir, const fileName &targetDir)
Copy all the files from the source to the target directory.
bool isFile(const fileName &, const bool checkVariants=true, const bool followLink=true)
Does the name exist as a file in the file system?
Definition: POSIX.C:555
fileState getState(const label watchFd) const
Check state using handle.
Definition: fileMonitor.C:508
fileState
Enumeration defining the file state.
Definition: fileMonitor.H:69
void setUnmodified(const label watchFd)
Reset state (e.g. after having read it) using handle.
Definition: fileMonitor.C:611
static word meshSubDir
Return the mesh sub-directory name (usually "polyMesh")
Definition: polyMesh.H:328
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
static const fileName null
An empty fileName.
Definition: fileName.H:97
virtual void setUnmodified(const label) const
Set current state of file (using handle) to unmodified.
virtual bool mkDir(const fileName &, mode_t=0777) const =0
Make directory.
bool exists(IOobject &io) const
Does ioobject exist. Is either a directory (empty name()) or.
virtual fileNameList readObjects(const objectRegistry &db, const fileName &instance, const fileName &local, word &newInstance) const
Search directory for objects. Used in IOobjectList.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
static label numBlocks(const fileName &)
Detect number of blocks in a file.
fileName objectPath() const
Return complete path + object name.
Definition: regIOobject.H:159
static bool master(const label communicator=0)
Am I the master process.
Definition: UPstream.H:423
const labelList & watchIndices() const
Return file-monitoring handles.
Definition: regIOobjectI.H:100
virtual ~fileOperation()
Destructor.
static int & msgType()
Message tag of standard messages.
Definition: UPstream.H:476
fileName path(const word &instance, const fileName &local="") const
Return complete path with alternative instance and local.
tmpNrc< dirIndexList > lookupProcessorsPath(const fileName &) const
Lookup name of processorsDDD using cache. Return empty fileName.
iterator end()
Return an iterator to end traversing the UList.
Definition: UListI.H:224
Initialise the NamedEnum HashTable from the static list of names.
Definition: NamedEnum.H:51
fileName processorsPath(const IOobject &, const word &instance, const word &procDir) const
Generate path (like io.path) with provided instance and any.
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:69
static bool less(const vector &x, const vector &y)
To compare normals.
bool good() const
Return true if next operation might succeed.
Definition: IOstream.H:330
virtual autoPtr< Ostream > NewOFstream(const fileName &filePath, IOstream::streamFormat format=IOstream::ASCII, IOstream::versionNumber version=IOstream::currentVersion, IOstream::compressionType compression=IOstream::UNCOMPRESSED, const bool write=true) const =0
Generate an Ostream that writes a file.
bool erase(const iterator &)
Erase a hashedEntry specified by given iterator.
Definition: HashTable.C:371
static autoPtr< fileOperation > New(const word &type, const bool verbose)
Select type.
virtual void updateStates(const bool masterOnly, const bool syncPar) const
Update state of all files.
Functions used by OpenFOAM that are specific to POSIX compliant operating systems and need to be repl...
dimensionedScalar pos(const dimensionedScalar &ds)
virtual fileNameList readDir(const fileName &, const fileType=fileType::file, const bool filterVariants=true, const bool followLink=true) const =0
Read a directory and return the entries as a string list.
bool read(const char *, int32_t &)
Definition: int32IO.C:85
bool removeWatch(const label watchFd)
Remove file to watch. Return true if successful.
Definition: fileMonitor.C:489
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects...
Definition: DynamicList.H:56
bool isDir(const fileName &, const bool followLink=true)
Does the name exist as a directory in the file system?
Definition: POSIX.C:539
A class for handling words, derived from string.
Definition: word.H:59
void updateStates(const bool masterOnly, const bool syncPar) const
Check state of all files. Updates state_.
Definition: fileMonitor.C:516
virtual fileName getFile(const label) const
Get name of file being watched (using handle)
virtual fileName filePath(const bool globalFile, const IOobject &, const word &typeName) const =0
Search for an object. globalFile : also check undecomposed case.
virtual IOobject findInstance(const IOobject &io, const scalar startValue, const word &stopInstance) const
Find instance where IOobject is. Fails if cannot be found.
virtual instantList findTimes(const fileName &, const word &) const
Get sorted list of times.
const fileName & getFile(const label watchFd) const
Get name of file being watched.
Definition: fileMonitor.C:502
void sort(UList< T > &)
Definition: UList.C:115
const fileName & local() const
Definition: IOobject.H:409
const word & constant() const
Return constant name.
Definition: TimePaths.H:123
regionProperties rp(runTime)
word name() const
Return file name (part beyond last /)
Definition: fileName.C:195
streamFormat
Enumeration for the format of data in the stream.
Definition: IOstream.H:86
DynamicList< T, SizeInc, SizeMult, SizeDiv > & append(const T &)
Append an element at the end of the list.
Definition: DynamicListI.H:296
static const word null
An empty word.
Definition: word.H:77
virtual void addWatches(regIOobject &, const fileNameList &) const
Helper: add watches for list of regIOobjects.
const fileOperation & fileHandler()
Get current file handler.
bool readScalar(const char *buf, doubleScalar &s)
Read whole of buf as a scalar. Return true if successful.
Definition: doubleScalar.H:75
virtual label addWatch(const fileName &) const
Add watching of a file. Returns handle.
fileNameList readDir(const fileName &, const fileType=fileType::file, const bool filterVariants=true, const bool followLink=true)
Read a directory and return the entries as a string list.
Definition: POSIX.C:662
graph_traits< Graph >::vertices_size_type size_type
Definition: SloanRenumber.C:73
bool valid() const
Return true if the autoPtr valid (ie, the pointer is set)
Definition: autoPtrI.H:83
errorManip< error > abort(error &err)
Definition: errorManip.H:131
static void scatter(const List< commsStruct > &comms, T &Value, const int tag, const label comm)
Scatter data. Distribute without modification. Reverse of gather.
virtual bool cp(const fileName &src, const fileName &dst, const bool followLink=true) const =0
Copy, recursively if necessary, the source to the destination.
static void mergeTimes(const instantList &extraTimes, const word &constantName, instantList &times)
Merge two times.
compressionType
Enumeration for the format of data in the stream.
Definition: IOstream.H:193
static word processorsBaseDir
Return the processors directory name (usually "processors")
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:54
virtual bool writeObject(const regIOobject &, IOstream::streamFormat format=IOstream::ASCII, IOstream::versionNumber version=IOstream::currentVersion, IOstream::compressionType compression=IOstream::UNCOMPRESSED, const bool write=true) const
Writes a regIOobject (so header, contents and divider).
const fileName & globalCaseName() const
Return global case name.
Definition: TimePaths.H:101
static const char nl
Definition: Ostream.H:260
defineRunTimeSelectionTable(reactionRateFlameArea, dictionary)
fileName processorsCasePath(const IOobject &, const word &procDir) const
Generate path (like io.path) from root+casename with any.
fileOperation(const label comm)
Construct null.
defineTypeNameAndDebug(combustionModel, 0)
static fileCheckTypes fileModificationChecking
Type of file modification checking.
Definition: IOobject.H:231
fileMonitor & monitor() const
Definition: fileOperation.C:81
HashTable< dirIndexList > procsDirs_
Detected processors directories.
Definition: fileOperation.H:99
labelList f(nPoints)
word name(const complex &)
Return a string representation of a complex.
Definition: complex.C:47
virtual void flush() const
Forcibly wait until all output done. Flush any cached data.
A class for managing temporary objects without reference counting.
Definition: tmpNrc.H:52
static bool isFileOrDir(const bool isFile, const fileName &)
Helper: check for file (isFile) or directory (!isFile)
const fileName & rootPath() const
Definition: IOobject.C:336
void setSize(const label)
Reset size of List.
Definition: List.C:281
static autoPtr< fileOperation > fileHandlerPtr_
Static fileOperation.
static bool & parRun()
Is this a parallel run?
Definition: UPstream.H:399
static Stream & writeEndDivider(Stream &os)
Write the standard end file divider.
Definition: IOobjectI.H:123
virtual label nProcs(const fileName &dir, const fileName &local="") const
Get number of processor directories/results. Used for e.g.
static word defaultFileHandler
Default fileHandler.
#define WarningInFunction
Report a warning using Foam::Warning.
label addWatch(const fileName &)
Add file to watch. Return watch descriptor.
Definition: fileMonitor.C:450
const Time & time() const
Return time.
Definition: IOobject.C:318
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
static instantList sortTimes(const fileNameList &, const word &)
Sort directory entries according to time value.
Definition: fileOperation.C:99
instantList times() const
Search the case for valid time directories.
Definition: Time.C:682
Version number type.
Definition: IOstream.H:96
regIOobject is an abstract class derived from IOobject to handle automatic object registration with t...
Definition: regIOobject.H:52
bool writeHeader(Ostream &) const
Write header.
const label comm_
Communicator to use.
Definition: fileOperation.H:96
bool headerOk()
Read header of local object without type-checking.
label n
virtual const fileName & dbDir() const
Local directory path of this objectRegistry relative to the time.
fileName path() const
Return directory path name (part before last /)
Definition: fileName.C:265
fileName search(const word &file, const fileName &directory)
Recursively search the given directory for the file.
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
dictionary & optimisationSwitches()
The OptimisationSwitches sub-dictionary in the central controlDict.
Definition: debug.C:205
fileName & instance() const
Return the instance directory, constant, system, <time> etc.
Definition: IOobject.C:355
static label detectProcessorPath(const fileName &)
Detect processor number from &#39;/aa/bb/processorDDD/cc&#39;.
Registry of regIOobjects.
virtual bool writeData(Ostream &) const =0
Pure virtual writaData function.
const objectRegistry & db() const
Return the local objectRegistry.
Definition: IOobject.C:312
virtual label findWatch(const labelList &watchIndices, const fileName &) const
Find index (or -1) of file in list of handles.
readOption readOpt() const
Definition: IOobject.H:365
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:98
static const NamedEnum< pathType, 12 > pathTypeNames_
Definition: fileOperation.H:79
virtual fileName objectPath(const IOobject &io, const word &typeName) const
Generate disk file name for object. Opposite of filePath.
static label splitProcessorPath(const fileName &, fileName &path, fileName &procDir, fileName &local, label &groupStart, label &groupSize, label &nProcs)
Split fileName into part before &#39;processor&#39; and part after.
virtual void setNProcs(const label nProcs)
Set number of processor directories/results. Only used in.
void transfer(List< T > &)
Transfer the contents of the argument List into this list.
Definition: List.C:342
fileName objectPath(const bool global) const
Return complete path + object name including the processor.
Definition: IOobject.H:420
virtual bool removeWatch(const label) const
Remove watch on a file (using handle)
Namespace for OpenFOAM.
#define InfoInFunction
Report an information message using Foam::Info.