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 
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  (
467  NewOFstream
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
532  tmpNrc<dirIndexList> procDirs(lookupProcessorsPath(fName));
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
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 
1000 (
1001  const IOobject& io,
1002  const word& procsDir
1003 ) const
1004 {
1005  return io.rootPath()/io.time().globalCaseName()/procsDir;
1006 }
1007 
1008 
1010 (
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 
1025 (
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 
1052 (
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 {
1186  {
1187  word handler(getEnv("FOAM_FILEHANDLER"));
1188 
1189  if (!handler.size())
1190  {
1192  }
1193 
1195  }
1197 }
1198 
1199 
1201 {
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
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 // ************************************************************************* //
Functions used by OpenFOAM that are specific to POSIX compliant operating systems and need to be repl...
graph_traits< Graph >::vertices_size_type size_type
Definition: SloanRenumber.C:73
label n
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
#define forAllConstIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:477
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition: DynamicList.H:78
DynamicList< T, SizeInc, SizeMult, SizeDiv > & append(const T &)
Append an element at the end of the list.
Definition: DynamicListI.H:296
An STL-conforming const_iterator.
Definition: HashTable.H:484
bool erase(const iterator &)
Erase a hashedEntry specified by given iterator.
Definition: HashTable.C:371
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:99
const fileName & local() const
Definition: IOobject.H:400
const Time & time() const
Return time.
Definition: IOobject.C:318
@ MUST_READ_IF_MODIFIED
Definition: IOobject.H:119
static Stream & writeEndDivider(Stream &os)
Write the standard end file divider.
Definition: IOobjectI.H:103
fileName & instance() const
Return the instance directory, constant, system, <time> etc.
Definition: IOobject.C:355
const objectRegistry & db() const
Return the local objectRegistry.
Definition: IOobject.C:312
readOption readOpt() const
Definition: IOobject.H:360
bool headerOk()
Read header of local object without type-checking.
static fileCheckTypes fileModificationChecking
Type of file modification checking.
Definition: IOobject.H:226
const word & name() const
Return name.
Definition: IOobject.H:310
const fileName & rootPath() const
Definition: IOobject.C:336
bool writeHeader(Ostream &) const
Write header.
fileName objectPath(const bool global) const
Return complete path + object name including the processor.
Definition: IOobject.H:411
Version number type.
Definition: IOstream.H:97
streamFormat
Enumeration for the format of data in the stream.
Definition: IOstream.H:87
compressionType
Enumeration for the format of data in the stream.
Definition: IOstream.H:194
bool good() const
Return true if next operation might succeed.
Definition: IOstream.H:330
void transfer(List< T > &)
Transfer the contents of the argument List into this list.
Definition: List.C:342
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
void setSize(const label)
Reset size of List.
Definition: List.C:281
Initialise the NamedEnum HashTable from the static list of names.
Definition: NamedEnum.H:54
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:57
static void scatter(const List< commsStruct > &comms, T &Value, const int tag, const label comm)
Scatter data. Distribute without modification. Reverse of gather.
static const word & constant()
Return constant name.
Definition: TimePaths.H:122
const fileName & globalCaseName() const
Return global case name.
Definition: TimePaths.H:100
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:76
instantList times() const
Search the case for valid time directories.
Definition: Time.C:640
A 2-tuple for storing two objects of different types.
Definition: Tuple2.H:63
iterator end()
Return an iterator to end traversing the UList.
Definition: UListI.H:224
static bool master(const label communicator=0)
Am I the master process.
Definition: UPstream.H:423
static bool & parRun()
Is this a parallel run?
Definition: UPstream.H:399
static int & msgType()
Message tag of standard messages.
Definition: UPstream.H:476
bool valid() const
Return true if the autoPtr valid (ie, the pointer is set)
Definition: autoPtrI.H:83
static label numBlocks(const fileName &)
Detect number of blocks in a file.
Checking for changes to files.
Definition: fileMonitor.H:62
fileState
Enumeration defining the file state.
Definition: fileMonitor.H:70
A class for handling file names.
Definition: fileName.H:82
word name() const
Return file name (part beyond last /)
Definition: fileName.C:195
static const fileName null
An empty fileName.
Definition: fileName.H:97
fileName path() const
Return directory path name (part before last /)
Definition: fileName.C:265
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).
virtual void addWatches(regIOobject &, const fileNameList &) const
Helper: add watches for list of regIOobjects.
static bool isFileOrDir(const bool isFile, const fileName &)
Helper: check for file (isFile) or directory (!isFile)
static word processorsBaseDir
Return the processors directory name (usually "processors")
static instantList sortTimes(const fileNameList &, const word &)
Sort directory entries according to time value.
Definition: fileOperation.C:99
virtual void setNProcs(const label nProcs)
Set number of processor directories/results. Only used in.
virtual label addWatch(const fileName &) const
Add watching of a file. Returns handle.
fileOperation(const label comm)
Construct null.
static label detectProcessorPath(const fileName &)
Detect processor number from '/aa/bb/processorDDD/cc'.
virtual void flush() const
Forcibly wait until all output done. Flush any cached data.
static autoPtr< fileOperation > New(const word &type, const bool verbose)
Select type.
virtual bool removeWatch(const label) const
Remove watch on a file (using handle)
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.
static word defaultFileHandler
Default fileHandler.
virtual label findWatch(const labelList &watchIndices, const fileName &) const
Find index (or -1) of file in list of handles.
pathType
Enumeration for the location of an IOobject.
Definition: fileOperation.H:62
fileName processorsCasePath(const IOobject &, const word &procDir) const
Generate path (like io.path) from root+casename with any.
virtual IOobject findInstance(const IOobject &io, const scalar startValue, const word &stopInstance) const
Find instance where IOobject is. Fails if cannot be found.
static const NamedEnum< pathType, 12 > pathTypeNames_
Definition: fileOperation.H:79
virtual fileMonitor::fileState getState(const label) const
Get current state of file (using handle)
autoPtr< fileMonitor > monitorPtr_
file-change monitor for all registered files
virtual void setUnmodified(const label) const
Set current state of file (using handle) to unmodified.
virtual label nProcs(const fileName &dir, const fileName &local="") const
Get number of processor directories/results. Used for e.g.
virtual void updateStates(const bool masterOnly, const bool syncPar) const
Update state of all files.
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.
fileMonitor & monitor() const
Definition: fileOperation.C:81
fileName processorsPath(const IOobject &, const word &instance, const word &procDir) const
Generate path (like io.path) with provided instance and any.
virtual instantList findTimes(const fileName &, const word &) const
Get sorted list of times.
tmpNrc< dirIndexList > lookupProcessorsPath(const fileName &) const
Lookup name of processorsDDD using cache. Return empty fileName.
virtual ~fileOperation()
Destructor.
static autoPtr< fileOperation > fileHandlerPtr_
Static fileOperation.
virtual fileName getFile(const label) const
Get name of file being watched (using handle)
virtual fileName objectPath(const IOobject &io, const word &typeName) const
Generate disk file name for object. Opposite of filePath.
static void mergeTimes(const instantList &extraTimes, const word &constantName, instantList &times)
Merge two times.
virtual fileName filePath(const bool globalFile, const IOobject &, const word &typeName) const =0
Search for an object. globalFile : also check undecomposed case.
Less function class used in sorting instants.
Definition: instant.H:79
Registry of regIOobjects.
fileName path(const word &instance, const fileName &local="") const
Return complete path with alternative instance and local.
virtual const fileName & dbDir() const
Local directory path of this objectRegistry relative to the time.
static word meshSubDir
Return the mesh sub-directory name (usually "polyMesh")
Definition: polyMesh.H:269
regIOobject is an abstract class derived from IOobject to handle automatic object registration with t...
Definition: regIOobject.H:55
const labelList & watchIndices() const
Return file-monitoring handles.
Definition: regIOobjectI.H:100
fileName objectPath() const
Return complete path + object name.
Definition: regIOobject.H:159
virtual bool writeData(Ostream &) const =0
Pure virtual writaData function.
A class for managing temporary objects without reference counting.
Definition: tmpNrc.H:53
A class for handling words, derived from string.
Definition: word.H:62
static const word null
An empty word.
Definition: word.H:77
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:306
#define WarningInFunction
Report a warning using Foam::Warning.
#define InfoInFunction
Report an information message using Foam::Info.
bool valid(const PtrList< ModelType > &l)
dictionary & optimisationSwitches()
The OptimisationSwitches sub-dictionary in the central controlDict.
Definition: debug.C:205
void write(std::ostream &os, const bool binary, List< floatScalar > &fField)
Write floats ascii or binary.
Namespace for OpenFOAM.
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
const fileOperation & fileHandler()
Get current file handler.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
dimensionedScalar pos(const dimensionedScalar &ds)
bool read(const char *, int32_t &)
Definition: int32IO.C:85
void cpFiles(const fileName &srcDir, const fileName &targetDir)
Copy all the files from the source to the target directory.
defineRunTimeSelectionTable(reactionRateFlameArea, dictionary)
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:59
bool mkDir(const fileName &, mode_t=0777)
Make a directory and return an error if it could not be created.
Definition: POSIX.C:290
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
errorManip< error > abort(error &err)
Definition: errorManip.H:131
bool exists(const fileName &, const bool checkVariants=true, const bool followLink=true)
Does the name exist (as directory or file) in the file system?
Definition: POSIX.C:520
void sort(UList< T > &)
Definition: UList.C:115
bool readScalar(const char *buf, doubleScalar &s)
Read whole of buf as a scalar. Return true if successful.
Definition: doubleScalar.H:75
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
defineTypeNameAndDebug(combustionModel, 0)
bool isDir(const fileName &, const bool followLink=true)
Does the name exist as a directory in the file system?
Definition: POSIX.C:539
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
string getEnv(const word &)
Return environment variable of given name.
Definition: POSIX.C:97
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
bool cp(const fileName &src, const fileName &dst, const bool followLink=true)
Copy, recursively if necessary, the source to the destination.
Definition: POSIX.C:753
error FatalError
word name(const complex &)
Return a string representation of a complex.
Definition: complex.C:47
static const char nl
Definition: Ostream.H:260
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
fileType type(const fileName &, const bool checkVariants=true, const bool followLink=true)
Return the file type: directory or file.
Definition: POSIX.C:488
fileName search(const word &file, const fileName &directory)
Recursively search the given directory for the file.
labelList f(nPoints)