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-2018 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"
28 #include "regIOobject.H"
29 #include "argList.H"
30 #include "HashSet.H"
31 #include "objectRegistry.H"
32 #include "decomposedBlockData.H"
33 #include "polyMesh.H"
34 #include "registerSwitch.H"
35 #include "Time.H"
36 
37 /* * * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * */
38 
39 namespace Foam
40 {
41  autoPtr<fileOperation> fileOperation::fileHandlerPtr_;
42 
43  defineTypeNameAndDebug(fileOperation, 0);
44  defineRunTimeSelectionTable(fileOperation, word);
45 
46  template<>
47  const char* Foam::NamedEnum
48  <
50  12
51  >::names[] =
52  {
53  "notFound",
54  "absolute",
55  "objectPath",
56  "writeObject",
57  "uncollatedProc",
58  "globalProc",
59  "localProc",
60  "parentObjectPath",
61  "findInstance",
62  "uncollatedProcInstance",
63  "globalProcInstance",
64  "localProcInstance"
65  };
67 
69  (
70  debug::optimisationSwitches().lookupOrAddDefault
71  (
72  "fileHandler",
73  // Foam::fileOperations::uncollatedFileOperation::typeName,
74  word("uncollated"),
75  false,
76  false
77  )
78  );
79 
81 }
82 
83 
84 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
85 
87 {
88  if (!monitorPtr_.valid())
89  {
90  monitorPtr_.reset
91  (
92  new fileMonitor
93  (
96  )
97  );
98  }
99  return monitorPtr_();
100 }
101 
102 
104 (
105  const fileNameList& dirEntries,
106  const word& constantName
107 )
108 {
109  // Initialise instant list
110  instantList Times(dirEntries.size() + 1);
111  label nTimes = 0;
112 
113  // Check for "constant"
114  bool haveConstant = false;
115  forAll(dirEntries, i)
116  {
117  if (dirEntries[i] == constantName)
118  {
119  Times[nTimes].value() = 0;
120  Times[nTimes].name() = dirEntries[i];
121  nTimes++;
122  haveConstant = true;
123  break;
124  }
125  }
126 
127  // Read and parse all the entries in the directory
128  forAll(dirEntries, i)
129  {
130  scalar timeValue;
131  if (readScalar(dirEntries[i].c_str(), timeValue))
132  {
133  Times[nTimes].value() = timeValue;
134  Times[nTimes].name() = dirEntries[i];
135  nTimes++;
136  }
137  }
138 
139  // Reset the length of the times list
140  Times.setSize(nTimes);
141 
142  if (haveConstant)
143  {
144  if (nTimes > 2)
145  {
146  std::sort(&Times[1], Times.end(), instant::less());
147  }
148  }
149  else if (nTimes > 1)
150  {
151  std::sort(&Times[0], Times.end(), instant::less());
152  }
153 
154  return Times;
155 }
156 
157 
159 (
160  const instantList& extraTimes,
161  const word& constantName,
162  instantList& times
163 )
164 {
165  if (extraTimes.size())
166  {
167  bool haveConstant =
168  (
169  times.size() > 0
170  && times[0].name() == constantName
171  );
172 
173  bool haveExtraConstant =
174  (
175  extraTimes.size() > 0
176  && extraTimes[0].name() == constantName
177  );
178 
179  // Combine times
180  instantList combinedTimes(times.size()+extraTimes.size());
181  label sz = 0;
182  label extrai = 0;
183  if (haveExtraConstant)
184  {
185  extrai = 1;
186  if (!haveConstant)
187  {
188  combinedTimes[sz++] = extraTimes[0]; // constant
189  }
190  }
191  forAll(times, i)
192  {
193  combinedTimes[sz++] = times[i];
194  }
195  for (; extrai < extraTimes.size(); extrai++)
196  {
197  combinedTimes[sz++] = extraTimes[extrai];
198  }
199  combinedTimes.setSize(sz);
200  times.transfer(combinedTimes);
201 
202  // Sort
203  if (times.size() > 1)
204  {
205  label starti = 0;
206  if (times[0].name() == constantName)
207  {
208  starti = 1;
209  }
210  std::sort(&times[starti], times.end(), instant::less());
211 
212  // Filter out duplicates
213  label newi = starti+1;
214  for (label i = newi; i < times.size(); i++)
215  {
216  if (times[i].value() != times[i-1].value())
217  {
218  if (newi != i)
219  {
220  times[newi] = times[i];
221  }
222  newi++;
223  }
224  }
225 
226  times.setSize(newi);
227  }
228  }
229 }
230 
231 
233 {
234  return
235  (isFile && Foam::isFile(f))
236  || (!isFile && Foam::isDir(f));
237 }
238 
239 
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 
261  procsDirs_.find(procPath);
262 
263  if (iter != procsDirs_.end())
264  {
265  return iter();
266  }
267 
268  // Read all directories to see any beginning with processor
269  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
270 
271  DynamicList<dirIndex> procDirs;
272 
273  // Note: use parallel synchronised reading so cache will be same
274  // order on all processors
275  fileNameList dirNames(readDir(path, fileName::Type::DIRECTORY));
276 
277  // Extract info from processorsDDD or processorDDD:
278  // - highest processor number
279  // - directory+offset containing data for proci
280  label maxProc = -1;
281 
282  forAll(dirNames, i)
283  {
284  const fileName& dirN = dirNames[i];
285 
286  // Analyse directory name
287  fileName rp, rd, rl;
288  label rStart, rSize, rNum;
289  label readProci =
290  splitProcessorPath(dirN, rp, rd, rl, rStart, rSize, rNum);
291  maxProc = max(maxProc, readProci);
292 
293  if (proci == readProci)
294  {
295  // Found "processorDDD". No need for index.
296  procDirs.append
297  (
298  dirIndex
299  (
300  dirN,
301  Tuple2<pathType, label>(PROCUNCOLLATED, -1)
302  )
303  );
304  }
305  else if (proci >= rStart && proci < rStart+rSize)
306  {
307  // "processorsDDD_start-end"
308  // Found the file that contains the data for proci
309  procDirs.append
310  (
311  dirIndex
312  (
313  dirN,
314  Tuple2<pathType, label>(PROCOBJECT, proci-rStart)
315  )
316  );
317  }
318  if (rNum != -1)
319  {
320  // Direct detection of processorsDDD
321  maxProc = rNum-1;
322 
323  if (rStart == -1)
324  {
325  // "processorsDDD"
326  procDirs.append
327  (
328  dirIndex
329  (
330  dirN,
331  Tuple2<pathType, label>(PROCBASEOBJECT, proci)
332  )
333  );
334  }
335  }
336  }
337  if (!Pstream::parRun())
338  {
339  // If (as a side effect) we found the number of decompositions
340  // use it
341  if (maxProc != -1)
342  {
343  const_cast<fileOperation&>(*this).setNProcs(maxProc+1);
344  }
345  }
346 
347  if (returnReduce(procDirs.size(), sumOp<label>()))
348  {
349  procsDirs_.insert(procPath, procDirs);
350 
351  if (debug)
352  {
353  Pout<< "fileOperation::lookupProcessorsPath : For:" << procPath
354  << " detected:" << procDirs << endl;
355  }
356 
357  // Make sure to return a reference
358  return procsDirs_[procPath];
359  }
360  }
361  return tmpNrc<dirIndexList>(new dirIndexList(0, dirIndex()));
362 }
363 
364 
366 {
367  // Generate output filename for object
368  fileName objPath(objectPath(io, word::null));
369 
370  // Test for either directory or a (valid) file & IOobject
371  bool ok;
372  if (io.name().empty())
373  {
374  ok = isDir(objPath);
375  }
376  else
377  {
378  ok =
379  isFile(objPath)
380  && io.typeHeaderOk<IOList<label>>(false);// object with local scope
381  }
382 
383  if (!ok)
384  {
385  // Re-test with searched for objectPath. This is for backwards
386  // compatibility
387  fileName originalPath(filePath(io.objectPath()));
388  if (originalPath != objPath)
389  {
390  // Test for either directory or a (valid) file & IOobject
391  if (io.name().empty())
392  {
393  ok = isDir(originalPath);
394  }
395  else
396  {
397  ok =
398  isFile(originalPath)
399  && io.typeHeaderOk<IOList<label>>(false);
400  }
401  }
402  }
403 
404  return ok;
405 }
406 
407 
408 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
409 
411 :
412  comm_(comm)
413 {}
414 
415 
417 (
418  const word& type,
419  const bool verbose
420 )
421 {
422  wordConstructorTable::iterator cstrIter =
423  wordConstructorTablePtr_->find(type);
424 
425  if (cstrIter == wordConstructorTablePtr_->end())
426  {
428  << "Unknown fileOperation type "
429  << type << nl << nl
430  << "Valid fileOperation types are" << endl
431  << wordConstructorTablePtr_->sortedToc()
432  << abort(FatalError);
433  }
434 
435  return autoPtr<fileOperation>(cstrIter()(verbose));
436 }
437 
438 
439 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
440 
442 {}
443 
444 
445 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
446 
448 (
449  const IOobject& io,
450  const word& typeName
451 ) const
452 {
453  return io.objectPath();
454 }
455 
456 
458 (
459  const regIOobject& io,
463  const bool valid
464 ) const
465 {
466  if (valid)
467  {
468  fileName pathName(io.objectPath());
469 
470  mkDir(pathName.path());
471 
472  autoPtr<Ostream> osPtr
473  (
475  (
476  pathName,
477  fmt,
478  ver,
479  cmp
480  )
481  );
482 
483  if (!osPtr.valid())
484  {
485  return false;
486  }
487 
488  Ostream& os = osPtr();
489 
490  // If any of these fail, return (leave error handling to Ostream class)
491  if (!os.good())
492  {
493  return false;
494  }
495 
496  if (!io.writeHeader(os))
497  {
498  return false;
499  }
500 
501  // Write the data to the Ostream
502  if (!io.writeData(os))
503  {
504  return false;
505  }
506 
508  }
509  return true;
510 }
511 
512 
514 {
515  if (debug)
516  {
517  Pout<< "fileOperation::filePath :" << " fName:" << fName << endl;
518  }
519 
520  fileName path;
521  fileName pDir;
522  fileName local;
523  label gStart;
524  label gSz;
525  label numProcs;
526  label proci =
527  splitProcessorPath(fName, path, pDir, local, gStart, gSz, numProcs);
528 
529  if (numProcs != -1)
530  {
531  WarningInFunction << "Filename is already adapted:" << fName << endl;
532  }
533 
534  // Give preference to processors variant
535  if (proci != -1)
536  {
537  // Get all processor directories
539  forAll(procDirs(), i)
540  {
541  const fileName& procDir = procDirs()[i].first();
542 
543  fileName collatedName(path/procDir/local);
544  if (exists(collatedName))
545  {
546  if (debug)
547  {
548  Pout<< "fileOperation::filePath : " << collatedName << endl;
549  }
550  return collatedName;
551  }
552  }
553  }
554 
555  if (exists(fName))
556  {
557  if (debug)
558  {
559  Pout<< "fileOperation::filePath : " << fName << endl;
560  }
561  return fName;
562  }
563  else
564  {
565  if (debug)
566  {
567  Pout<< "fileOperation::filePath : Not found" << endl;
568  }
569  return fileName::null;
570  }
571 }
572 
573 
575 {
576  return monitor().addWatch(fName);
577 }
578 
579 
580 bool Foam::fileOperation::removeWatch(const label watchIndex) const
581 {
582  return monitor().removeWatch(watchIndex);
583 }
584 
585 
587 (
588  const labelList& watchIndices,
589  const fileName& fName
590 ) const
591 {
592  forAll(watchIndices, i)
593  {
594  if (getFile(watchIndices[i]) == fName)
595  {
596  return i;
597  }
598  }
599  return -1;
600 }
601 
602 
604 (
605  regIOobject& rio,
606  const fileNameList& files
607 ) const
608 {
609  const labelList& watchIndices = rio.watchIndices();
610 
611  DynamicList<label> newWatchIndices;
612  labelHashSet removedWatches(watchIndices);
613 
614  forAll(files, i)
615  {
616  const fileName& f = files[i];
617  label index = findWatch(watchIndices, f);
618 
619  if (index == -1)
620  {
621  newWatchIndices.append(addWatch(f));
622  }
623  else
624  {
625  // Existing watch
626  newWatchIndices.append(watchIndices[index]);
627  removedWatches.erase(index);
628  }
629  }
630 
631  // Remove any unused watches
632  forAllConstIter(labelHashSet, removedWatches, iter)
633  {
634  removeWatch(watchIndices[iter.key()]);
635  }
636 
637  rio.watchIndices() = newWatchIndices;
638 }
639 
640 
642 {
643  return monitor().getFile(watchIndex);
644 }
645 
646 
648 (
649  const bool masterOnly,
650  const bool syncPar
651 ) const
652 {
653  monitor().updateStates(masterOnly, Pstream::parRun());
654 }
655 
656 
658 (
659  const label watchFd
660 ) const
661 {
662  return monitor().getState(watchFd);
663 }
664 
665 
666 void Foam::fileOperation::setUnmodified(const label watchFd) const
667 {
668  monitor().setUnmodified(watchFd);
669 }
670 
671 
673 (
674  const fileName& directory,
675  const word& constantName
676 ) const
677 {
678  if (debug)
679  {
680  Pout<< "fileOperation::findTimes : Finding times in directory "
681  << directory << endl;
682  }
683 
684  // Read directory entries into a list
685  fileNameList dirEntries
686  (
688  (
689  directory,
691  )
692  );
693 
694  instantList times = sortTimes(dirEntries, constantName);
695 
696 
697  // Get all processor directories
698  tmpNrc<dirIndexList> procDirs(lookupProcessorsPath(directory));
699  forAll(procDirs(), i)
700  {
701  const fileName& procDir = procDirs()[i].first();
702  fileName collDir(processorsPath(directory, procDir));
703  if (!collDir.empty() && collDir != directory)
704  {
705  fileNameList extraEntries
706  (
708  (
709  collDir,
711  )
712  );
713  mergeTimes
714  (
715  sortTimes(extraEntries, constantName),
716  constantName,
717  times
718  );
719  }
720  }
721 
722  if (debug)
723  {
724  Pout<< "fileOperation::findTimes : Found times:" << times << endl;
725  }
726  return times;
727 }
728 
729 
731 (
732  const IOobject& startIO,
733  const scalar startValue,
734  const word& stopInstance
735 ) const
736 {
737  const Time& time = startIO.time();
738 
739  IOobject io(startIO);
740 
741  // Note: - if name is empty, just check the directory itself
742  // - check both for isFile and headerOk since the latter does a
743  // filePath so searches for the file.
744  // - check for an object with local file scope (so no looking up in
745  // parent directory in case of parallel)
746 
747  if (exists(io))
748  {
749  if (debug)
750  {
752  << "Found exact match for \"" << io.name()
753  << "\" in " << io.instance()/io.local()
754  << endl;
755  }
756 
757  return io;
758  }
759 
760  // Search back through the time directories to find the time
761  // closest to and lower than current time
762 
763  instantList ts = time.times();
764  label instanceI;
765 
766  for (instanceI = ts.size()-1; instanceI >= 0; --instanceI)
767  {
768  if (ts[instanceI].value() <= startValue)
769  {
770  break;
771  }
772  }
773 
774  // continue searching from here
775  for (; instanceI >= 0; --instanceI)
776  {
777  // Shortcut: if actual directory is the timeName we've already tested it
778  if
779  (
780  ts[instanceI].name() == startIO.instance()
781  && ts[instanceI].name() != stopInstance
782  )
783  {
784  continue;
785  }
786 
787  io.instance() = ts[instanceI].name();
788  if (exists(io))
789  {
790  if (debug)
791  {
793  << "Found exact match for \"" << io.name()
794  << "\" in " << io.instance()/io.local()
795  << endl;
796  }
797 
798  return io;
799  }
800 
801  // Check if hit minimum instance
802  if (ts[instanceI].name() == stopInstance)
803  {
804  if (debug)
805  {
807  << "Hit stopInstance " << stopInstance << endl;
808  }
809 
810  if
811  (
812  startIO.readOpt() == IOobject::MUST_READ
814  )
815  {
816  if (io.name().empty())
817  {
819  << "Cannot find directory "
820  << io.local() << " in times " << startIO.instance()
821  << " down to " << stopInstance
822  << exit(FatalError);
823  }
824  else
825  {
827  << "Cannot find file \"" << io.name()
828  << "\" in directory " << io.local()
829  << " in times " << startIO.instance()
830  << " down to " << stopInstance
831  << exit(FatalError);
832  }
833  }
834 
835  return io;
836  }
837  }
838 
839  // times() usually already includes the constant() so would have been
840  // checked above. Re-test if
841  // - times() is empty. Sometimes this can happen (e.g. decomposePar with
842  // collated)
843  // - times()[0] is not constant
844  if (!ts.size() || ts[0].name() != time.constant())
845  {
846  // Note. This needs to be a hard-coded constant, rather than the
847  // constant function of the time, because the latter points to
848  // the case constant directory in parallel cases
849 
850  io.instance() = time.constant();
851  if (exists(io))
852  {
853  if (debug)
854  {
856  << "Found constant match for \"" << io.name()
857  << "\" in " << io.instance()/io.local()
858  << endl;
859  }
860  return io;
861  }
862  }
863 
864 
865  if
866  (
867  startIO.readOpt() == IOobject::MUST_READ
869  )
870  {
872  << "Cannot find file \"" << io.name() << "\" in directory "
873  << io.local() << " in times " << startIO.instance()
874  << " down to " << time.constant()
875  << exit(FatalError);
876  }
877 
878  return io;
879 }
880 
881 
883 (
884  const objectRegistry& db,
885  const fileName& instance,
886  const fileName& local,
887  word& newInstance
888 ) const
889 {
890  if (debug)
891  {
892  Pout<< "fileOperation::readObjects :"
893  << " db:" << db.objectPath()
894  << " instance:" << instance << endl;
895  }
896 
897  fileName path(db.path(instance, db.dbDir()/local));
898 
899  newInstance = word::null;
900  fileNameList objectNames;
901 
902  if (Foam::isDir(path))
903  {
904  newInstance = instance;
905  objectNames = Foam::readDir(path, fileName::FILE);
906  }
907  else
908  {
909  // Get processors equivalent of path
910  fileName procsPath(filePath(path));
911 
912  if (!procsPath.empty())
913  {
914  newInstance = instance;
915  objectNames = Foam::readDir(procsPath, fileName::FILE);
916  }
917  }
918  return objectNames;
919 }
920 
921 
923 {}
924 
925 
927 (
928  const fileName& dir,
929  const fileName& local
930 ) const
931 {
932  label nProcs = 0;
933  if (Pstream::master(comm_))
934  {
935  fileNameList dirNames(Foam::readDir(dir, fileName::Type::DIRECTORY));
936 
937  // Detect any processorsDDD or processorDDD
938  label maxProc = -1;
939  forAll(dirNames, i)
940  {
941  const fileName& dirN = dirNames[i];
942 
943  fileName path, pDir, local;
944  label start, size, n;
945  maxProc = max
946  (
947  maxProc,
948  splitProcessorPath(dirN, path, pDir, local, start, size, n)
949  );
950  if (n != -1)
951  {
952  // Direct detection of processorsDDD
953  maxProc = n-1;
954  break;
955  }
956  }
957  nProcs = maxProc+1;
958 
959 
960  if (nProcs == 0 && Foam::isDir(dir/processorsBaseDir))
961  {
962  fileName pointsFile
963  (
964  dir
966  /"constant"
967  /local
969  /"points"
970  );
971 
972  if (Foam::isFile(pointsFile))
973  {
974  nProcs = decomposedBlockData::numBlocks(pointsFile);
975  }
976  else
977  {
978  WarningInFunction << "Cannot read file " << pointsFile
979  << " to determine the number of decompositions."
980  << " Returning 1" << endl;
981  }
982  }
983  }
985  return nProcs;
986 }
987 
988 
990 {
991  if (debug)
992  {
993  Pout<< "fileOperation::flush : clearing processor directories cache"
994  << endl;
995  }
996  procsDirs_.clear();
997 }
998 
999 
1002  const IOobject& io,
1003  const word& procsDir
1004 ) const
1005 {
1006  return io.rootPath()/io.time().globalCaseName()/procsDir;
1007 }
1008 
1009 
1012  const IOobject& io,
1013  const word& instance,
1014  const word& procsDir
1015 ) const
1016 {
1017  return
1018  processorsCasePath(io, procsDir)
1019  /instance
1020  /io.db().dbDir()
1021  /io.local();
1022 }
1023 
1024 
1027  const fileName& dir,
1028  const word& procsDir
1029 ) const
1030 {
1031  // Check if directory is processorDDD
1032  word caseName(dir.name());
1033 
1034  std::string::size_type pos = caseName.find("processor");
1035  if (pos == 0)
1036  {
1037  if (caseName.size() <= 9 || caseName[9] == 's')
1038  {
1039  WarningInFunction << "Directory " << dir
1040  << " does not end in old-style processorDDD" << endl;
1041  }
1042 
1043  return dir.path()/procsDir;
1044  }
1045  else
1046  {
1047  return fileName::null;
1048  }
1049 }
1050 
1051 
1054  const fileName& objectPath,
1055  fileName& path,
1056  fileName& procDir,
1057  fileName& local,
1058 
1059  label& groupStart,
1060  label& groupSize,
1061 
1062  label& nProcs
1063 )
1064 {
1065  path.clear();
1066  procDir.clear();
1067  local.clear();
1068 
1069  // Potentially detected start of number of processors in local group
1070  groupStart = -1;
1071  groupSize = 0;
1072 
1073  // Potentially detected number of processors
1074  nProcs = -1;
1075 
1076  // Search for processor at start of line or /processor
1077  std::string::size_type pos = objectPath.find("processor");
1078  if (pos == string::npos)
1079  {
1080  return -1;
1081  }
1082 
1083  // "processorDDD"
1084  // "processorsNNN"
1085  // "processorsNNN_AA-BB"
1086 
1087 
1088  if (pos > 0 && objectPath[pos-1] != '/')
1089  {
1090  // Directory not starting with "processor" e.g. "somenamewithprocessor"
1091  return -1;
1092  }
1093 
1094  procDir = objectPath;
1095 
1096  // Strip leading directory
1097  if (pos > 0)
1098  {
1099  path = objectPath.substr(0, pos-1);
1100  procDir = objectPath.substr(pos);
1101  }
1102 
1103  // Strip trailing local directory
1104  pos = procDir.find('/');
1105  if (pos != string::npos)
1106  {
1107  local = procDir.substr(pos+1);
1108  procDir = procDir.substr(0, pos);
1109  }
1110 
1111  // Now procDir is e.g.
1112  // - processor0
1113  // - processors0
1114  // - processorBananas
1115 
1116  // Look for number after "processor"
1117 
1118  fileName f(procDir.substr(9));
1119 
1120  if (f.size() && f[0] == 's')
1121  {
1122  // "processsorsNNN"
1123 
1124  f = f.substr(1);
1125 
1126  // Detect "processorsNNN_AA-BB"
1127  {
1128  std::string::size_type fromStart = f.find("_");
1129  std::string::size_type toStart = f.find("-");
1130  if (fromStart != string::npos && toStart != string::npos)
1131  {
1132  string nProcsName(f.substr(0, fromStart));
1133  string fromName(f.substr(fromStart+1, toStart-(fromStart+1)));
1134  string toName(f.substr(toStart+1));
1135 
1136  label groupEnd = -1;
1137  if
1138  (
1139  Foam::read(fromName.c_str(), groupStart)
1140  && Foam::read(toName.c_str(), groupEnd)
1141  && Foam::read(nProcsName.c_str(), nProcs)
1142  )
1143  {
1144  groupSize = groupEnd-groupStart+1;
1145  return -1;
1146  }
1147  }
1148  }
1149 
1150  // Detect "processorsN"
1151  label n;
1152  if (Foam::read(f.c_str(), n))
1153  {
1154  nProcs = n;
1155  }
1156  return -1;
1157  }
1158  else
1159  {
1160  // Detect "processorN"
1161  label proci;
1162  if (Foam::read(f.c_str(), proci))
1163  {
1164  return proci;
1165  }
1166  else
1167  {
1168  return -1;
1169  }
1170  }
1171 }
1172 
1173 
1175 {
1176  fileName path, pDir, local;
1177  label start, size, nProcs;
1178  return splitProcessorPath(fName, path, pDir, local, start, size, nProcs);
1179 }
1180 
1181 
1182 // * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
1183 
1185 {
1186  if (!fileOperation::fileHandlerPtr_.valid())
1187  {
1188  word handler(getEnv("FOAM_FILEHANDLER"));
1189 
1190  if (!handler.size())
1191  {
1193  }
1194 
1196  }
1198 }
1199 
1200 
1202 {
1203  if (fileOperation::fileHandlerPtr_.valid())
1204  {
1205  if
1206  (
1207  newHandlerPtr.valid()
1208  && newHandlerPtr->type() == fileOperation::fileHandlerPtr_->type()
1209  )
1210  {
1211  return;
1212  }
1213  }
1215 
1216  if (newHandlerPtr.valid())
1217  {
1218  fileOperation::fileHandlerPtr_ = newHandlerPtr;
1219  }
1220 }
1221 
1222 
1223 Foam::fileName Foam::search(const word& file, const fileName& directory)
1224 {
1225  // Search the current directory for the file
1226  fileNameList files(fileHandler().readDir(directory));
1227  forAll(files, i)
1228  {
1229  if (files[i] == file)
1230  {
1231  return directory/file;
1232  }
1233  }
1234 
1235  // If not found search each of the sub-directories
1237  forAll(dirs, i)
1238  {
1239  fileName path = search(file, directory/dirs[i]);
1240  if (path != fileName::null)
1241  {
1242  return path;
1243  }
1244  }
1245 
1246  return fileName::null;
1247 }
1248 
1249 
1250 void Foam::cpFiles(const fileName& srcDir, const fileName& targetDir)
1251 {
1252  mkDir(targetDir);
1253 
1254  const fileNameList srcFiles(readDir(srcDir, fileName::FILE, true));
1255 
1256  forAll(srcFiles, filei)
1257  {
1258  cp(srcDir/srcFiles[filei], targetDir);
1259  }
1260 }
1261 
1262 
1263 // ************************************************************************* //
pathType
Enumeration for the location of an IOobject.
Definition: fileOperation.H:61
virtual bool writeObject(const regIOobject &, IOstream::streamFormat format=IOstream::ASCII, IOstream::versionNumber version=IOstream::currentVersion, IOstream::compressionType compression=IOstream::UNCOMPRESSED, const bool valid=true) const
Writes a regIOobject (so header, contents and divider).
string getEnv(const word &)
Return environment variable of given name.
Definition: POSIX.C:96
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:428
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
const word & name() const
Return name.
Definition: IOobject.H:297
bool typeHeaderOk(const bool checkType=true)
Read header (uses typeFilePath to find file) and check header.
A class for handling file names.
Definition: fileName.H:69
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
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
Checking for changes to files.
Definition: fileMonitor.H:61
virtual fileNameList readDir(const fileName &, const fileName::Type=fileName::FILE, const bool filtergz=true, const bool followLink=true) const =0
Read a directory and return the entries as a string list.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:319
A 2-tuple for storing two objects of different types.
Definition: HashTable.H:66
void cpFiles(const fileName &srcDir, const fileName &targetDir)
Copy all the files from the source to the target directory.
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:312
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:163
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:256
static label numBlocks(const fileName &)
Detect number of blocks in a file.
static bool master(const label communicator=0)
Am I the master process.
Definition: UPstream.H:421
const labelList & watchIndices() const
Return file-monitoring handles.
Definition: regIOobjectI.H:91
virtual ~fileOperation()
Destructor.
static int & msgType()
Message tag of standard messages.
Definition: UPstream.H:474
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:237
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:68
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:333
fileName path() const
Return complete path.
Definition: IOobject.C:397
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.
dimensionedScalar pos(const dimensionedScalar &ds)
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:528
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 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:402
const word & constant() const
Return constant name.
Definition: TimePaths.H:124
regionProperties rp(runTime)
word name() const
Return file name (part beyond last /)
Definition: fileName.C:179
virtual autoPtr< Ostream > NewOFstream(const fileName &pathname, IOstream::streamFormat format=IOstream::ASCII, IOstream::versionNumber version=IOstream::currentVersion, IOstream::compressionType compression=IOstream::UNCOMPRESSED, const bool valid=true) const =0
Generate an Ostream that writes a file.
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:292
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.
virtual fileName filePath(const bool checkGlobal, const IOobject &, const word &typeName) const =0
Search for an object. checkGlobal : also check undecomposed case.
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:68
virtual label addWatch(const fileName &) const
Add watching of a file. Returns handle.
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
forAllConstIter(PtrDictionary< phaseModel >, mixture.phases(), phase)
Definition: pEqn.H:29
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
bool isFile(const fileName &, const bool checkGzip=true, const bool followLink=true)
Does the name exist as a FILE in the file system?
Definition: POSIX.C:543
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:53
const fileName & globalCaseName() const
Return global case name.
Definition: TimePaths.H:102
static const char nl
Definition: Ostream.H:265
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.
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
defineTypeNameAndDebug(combustionModel, 0)
static fileCheckTypes fileModificationChecking
Type of file modification checking.
Definition: IOobject.H:214
fileMonitor & monitor() const
Definition: fileOperation.C:86
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:391
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:397
const fileName & instance() const
Definition: IOobject.H:392
static Stream & writeEndDivider(Stream &os)
Write the standard end file divider.
Definition: IOobjectI.H:103
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:367
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
static instantList sortTimes(const fileNameList &, const word &)
Sort directory entries according to time value.
instantList times() const
Search the case for valid time directories.
Definition: Time.C:642
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:65
bool writeHeader(Ostream &) const
Write header.
const label comm_
Communicator to use.
Definition: fileOperation.H:96
fileNameList readDir(const fileName &, const fileName::Type=fileName::FILE, const bool filtergz=true, const bool followLink=true)
Read a directory and return the entries as a string list.
Definition: POSIX.C:635
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:249
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:172
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:361
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:359
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:92
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.
fileName objectPath() const
Return complete path + object name.
Definition: IOobject.H:418
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
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.