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-2020 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  ok =
374  isFile(objPath)
375  && io.typeHeaderOk<IOList<label>>(false);// object with local scope
376  }
377 
378  if (!ok)
379  {
380  // Re-test with searched for objectPath. This is for backwards
381  // compatibility
382  fileName originalPath(filePath(io.objectPath()));
383  if (originalPath != objPath)
384  {
385  // Test for either directory or a (valid) file & IOobject
386  if (io.name().empty())
387  {
388  ok = isDir(originalPath);
389  }
390  else
391  {
392  ok =
393  isFile(originalPath)
394  && io.typeHeaderOk<IOList<label>>(false);
395  }
396  }
397  }
398 
399  return ok;
400 }
401 
402 
403 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
404 
406 :
407  comm_(comm)
408 {}
409 
410 
412 (
413  const word& type,
414  const bool verbose
415 )
416 {
417  wordConstructorTable::iterator cstrIter =
418  wordConstructorTablePtr_->find(type);
419 
420  if (cstrIter == wordConstructorTablePtr_->end())
421  {
423  << "Unknown fileOperation type "
424  << type << nl << nl
425  << "Valid fileOperation types are" << endl
426  << wordConstructorTablePtr_->sortedToc()
427  << abort(FatalError);
428  }
429 
430  return autoPtr<fileOperation>(cstrIter()(verbose));
431 }
432 
433 
434 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
435 
437 {}
438 
439 
440 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
441 
443 (
444  const IOobject& io,
445  const word& typeName
446 ) const
447 {
448  return io.objectPath();
449 }
450 
451 
453 (
454  const regIOobject& io,
458  const bool write
459 ) const
460 {
461  if (write)
462  {
464 
465  mkDir(filePath.path());
466 
467  autoPtr<Ostream> osPtr
468  (
470  (
471  filePath,
472  fmt,
473  ver,
474  cmp
475  )
476  );
477 
478  if (!osPtr.valid())
479  {
480  return false;
481  }
482 
483  Ostream& os = osPtr();
484 
485  // If any of these fail, return (leave error handling to Ostream class)
486  if (!os.good())
487  {
488  return false;
489  }
490 
491  if (!io.writeHeader(os))
492  {
493  return false;
494  }
495 
496  // Write the data to the Ostream
497  if (!io.writeData(os))
498  {
499  return false;
500  }
501 
503  }
504  return true;
505 }
506 
507 
509 {
510  if (debug)
511  {
512  Pout<< "fileOperation::filePath :" << " fName:" << fName << endl;
513  }
514 
515  fileName path;
516  fileName pDir;
517  fileName local;
518  label gStart;
519  label gSz;
520  label numProcs;
521  label proci =
522  splitProcessorPath(fName, path, pDir, local, gStart, gSz, numProcs);
523 
524  if (numProcs != -1)
525  {
526  WarningInFunction << "Filename is already adapted:" << fName << endl;
527  }
528 
529  // Give preference to processors variant
530  if (proci != -1)
531  {
532  // Get all processor directories
534  forAll(procDirs(), i)
535  {
536  const fileName& procDir = procDirs()[i].first();
537 
538  fileName collatedName(path/procDir/local);
539  if (exists(collatedName))
540  {
541  if (debug)
542  {
543  Pout<< "fileOperation::filePath : " << collatedName << endl;
544  }
545  return collatedName;
546  }
547  }
548  }
549 
550  if (exists(fName))
551  {
552  if (debug)
553  {
554  Pout<< "fileOperation::filePath : " << fName << endl;
555  }
556  return fName;
557  }
558  else
559  {
560  if (debug)
561  {
562  Pout<< "fileOperation::filePath : Not found" << endl;
563  }
564  return fileName::null;
565  }
566 }
567 
568 
570 {
571  return monitor().addWatch(fName);
572 }
573 
574 
575 bool Foam::fileOperation::removeWatch(const label watchIndex) const
576 {
577  return monitor().removeWatch(watchIndex);
578 }
579 
580 
582 (
583  const labelList& watchIndices,
584  const fileName& fName
585 ) const
586 {
587  forAll(watchIndices, i)
588  {
589  if (getFile(watchIndices[i]) == fName)
590  {
591  return i;
592  }
593  }
594  return -1;
595 }
596 
597 
599 (
600  regIOobject& rio,
601  const fileNameList& files
602 ) const
603 {
604  const labelList& watchIndices = rio.watchIndices();
605 
606  DynamicList<label> newWatchIndices;
607  labelHashSet removedWatches(watchIndices);
608 
609  forAll(files, i)
610  {
611  const fileName& f = files[i];
612  label index = findWatch(watchIndices, f);
613 
614  if (index == -1)
615  {
616  newWatchIndices.append(addWatch(f));
617  }
618  else
619  {
620  // Existing watch
621  newWatchIndices.append(watchIndices[index]);
622  removedWatches.erase(index);
623  }
624  }
625 
626  // Remove any unused watches
627  forAllConstIter(labelHashSet, removedWatches, iter)
628  {
629  removeWatch(watchIndices[iter.key()]);
630  }
631 
632  rio.watchIndices() = newWatchIndices;
633 }
634 
635 
637 {
638  return monitor().getFile(watchIndex);
639 }
640 
641 
643 (
644  const bool masterOnly,
645  const bool syncPar
646 ) const
647 {
648  monitor().updateStates(masterOnly, Pstream::parRun());
649 }
650 
651 
653 (
654  const label watchFd
655 ) const
656 {
657  return monitor().getState(watchFd);
658 }
659 
660 
661 void Foam::fileOperation::setUnmodified(const label watchFd) const
662 {
663  monitor().setUnmodified(watchFd);
664 }
665 
666 
668 (
669  const fileName& directory,
670  const word& constantName
671 ) const
672 {
673  if (debug)
674  {
675  Pout<< "fileOperation::findTimes : Finding times in directory "
676  << directory << endl;
677  }
678 
679  // Read directory entries into a list
680  fileNameList dirEntries
681  (
683  (
684  directory,
686  )
687  );
688 
689  instantList times = sortTimes(dirEntries, constantName);
690 
691 
692  // Get all processor directories
693  tmpNrc<dirIndexList> procDirs(lookupProcessorsPath(directory));
694  forAll(procDirs(), i)
695  {
696  const fileName& procDir = procDirs()[i].first();
697  fileName collDir(processorsPath(directory, procDir));
698  if (!collDir.empty() && collDir != directory)
699  {
700  fileNameList extraEntries
701  (
703  (
704  collDir,
706  )
707  );
708  mergeTimes
709  (
710  sortTimes(extraEntries, constantName),
711  constantName,
712  times
713  );
714  }
715  }
716 
717  if (debug)
718  {
719  Pout<< "fileOperation::findTimes : Found times:" << times << endl;
720  }
721  return times;
722 }
723 
724 
726 (
727  const IOobject& startIO,
728  const scalar startValue,
729  const word& stopInstance
730 ) const
731 {
732  const Time& time = startIO.time();
733 
734  IOobject io(startIO);
735 
736  // Note: - if name is empty, just check the directory itself
737  // - check both for isFile and headerOk since the latter does a
738  // filePath so searches for the file.
739  // - check for an object with local file scope (so no looking up in
740  // parent directory in case of parallel)
741 
742  if (exists(io))
743  {
744  if (debug)
745  {
747  << "Found exact match for \"" << io.name()
748  << "\" in " << io.instance()/io.local()
749  << endl;
750  }
751 
752  return io;
753  }
754 
755  // Search back through the time directories to find the time
756  // closest to and lower than current time
757 
758  instantList ts = time.times();
759  label instanceI;
760 
761  for (instanceI = ts.size()-1; instanceI >= 0; --instanceI)
762  {
763  if (ts[instanceI].value() <= startValue)
764  {
765  break;
766  }
767  }
768 
769  // continue searching from here
770  for (; instanceI >= 0; --instanceI)
771  {
772  // Shortcut: if actual directory is the timeName we've already tested it
773  if
774  (
775  ts[instanceI].name() == startIO.instance()
776  && ts[instanceI].name() != stopInstance
777  )
778  {
779  continue;
780  }
781 
782  io.instance() = ts[instanceI].name();
783  if (exists(io))
784  {
785  if (debug)
786  {
788  << "Found exact match for \"" << io.name()
789  << "\" in " << io.instance()/io.local()
790  << endl;
791  }
792 
793  return io;
794  }
795 
796  // Check if hit minimum instance
797  if (ts[instanceI].name() == stopInstance)
798  {
799  if (debug)
800  {
802  << "Hit stopInstance " << stopInstance << endl;
803  }
804 
805  if
806  (
807  startIO.readOpt() == IOobject::MUST_READ
809  )
810  {
811  if (io.name().empty())
812  {
814  << "Cannot find directory "
815  << io.local() << " in times " << startIO.instance()
816  << " down to " << stopInstance
817  << exit(FatalError);
818  }
819  else
820  {
822  << "Cannot find file \"" << io.name()
823  << "\" in directory " << io.local()
824  << " in times " << startIO.instance()
825  << " down to " << stopInstance
826  << exit(FatalError);
827  }
828  }
829 
830  return io;
831  }
832  }
833 
834  // times() usually already includes the constant() so would have been
835  // checked above. Re-test if
836  // - times() is empty. Sometimes this can happen (e.g. decomposePar with
837  // collated)
838  // - times()[0] is not constant
839  if (!ts.size() || ts[0].name() != time.constant())
840  {
841  // Note. This needs to be a hard-coded constant, rather than the
842  // constant function of the time, because the latter points to
843  // the case constant directory in parallel cases
844 
845  io.instance() = time.constant();
846  if (exists(io))
847  {
848  if (debug)
849  {
851  << "Found constant match for \"" << io.name()
852  << "\" in " << io.instance()/io.local()
853  << endl;
854  }
855  return io;
856  }
857  }
858 
859 
860  if
861  (
862  startIO.readOpt() == IOobject::MUST_READ
864  )
865  {
867  << "Cannot find file \"" << io.name() << "\" in directory "
868  << io.local() << " in times " << startIO.instance()
869  << " down to " << time.constant()
870  << exit(FatalError);
871  }
872 
873  return io;
874 }
875 
876 
878 (
879  const objectRegistry& db,
880  const fileName& instance,
881  const fileName& local,
882  word& newInstance
883 ) const
884 {
885  if (debug)
886  {
887  Pout<< "fileOperation::readObjects :"
888  << " db:" << db.objectPath()
889  << " instance:" << instance << endl;
890  }
891 
892  fileName path(db.path(instance, db.dbDir()/local));
893 
894  newInstance = word::null;
895  fileNameList objectNames;
896 
897  if (Foam::isDir(path))
898  {
899  newInstance = instance;
900  objectNames = Foam::readDir(path, fileType::file);
901  }
902  else
903  {
904  // Get processors equivalent of path
905  fileName procsPath(filePath(path));
906 
907  if (!procsPath.empty())
908  {
909  newInstance = instance;
910  objectNames = Foam::readDir(procsPath, fileType::file);
911  }
912  }
913  return objectNames;
914 }
915 
916 
918 {}
919 
920 
922 (
923  const fileName& dir,
924  const fileName& local
925 ) const
926 {
927  label nProcs = 0;
928  if (Pstream::master(comm_))
929  {
931 
932  // Detect any processorsDDD or processorDDD
933  label maxProc = -1;
934  forAll(dirNames, i)
935  {
936  const fileName& dirN = dirNames[i];
937 
938  fileName path, pDir, local;
939  label start, size, n;
940  maxProc = max
941  (
942  maxProc,
943  splitProcessorPath(dirN, path, pDir, local, start, size, n)
944  );
945  if (n != -1)
946  {
947  // Direct detection of processorsDDD
948  maxProc = n-1;
949  break;
950  }
951  }
952  nProcs = maxProc+1;
953 
954 
955  if (nProcs == 0 && Foam::isDir(dir/processorsBaseDir))
956  {
957  fileName pointsFile
958  (
959  dir
961  /"constant"
962  /local
964  /"points"
965  );
966 
967  if (Foam::isFile(pointsFile))
968  {
969  nProcs = decomposedBlockData::numBlocks(pointsFile);
970  }
971  else
972  {
973  WarningInFunction << "Cannot read file " << pointsFile
974  << " to determine the number of decompositions."
975  << " Returning 1" << endl;
976  }
977  }
978  }
980  return nProcs;
981 }
982 
983 
985 {
986  if (debug)
987  {
988  Pout<< "fileOperation::flush : clearing processor directories cache"
989  << endl;
990  }
991  procsDirs_.clear();
992 }
993 
994 
996 (
997  const IOobject& io,
998  const word& procsDir
999 ) const
1000 {
1001  return io.rootPath()/io.time().globalCaseName()/procsDir;
1002 }
1003 
1004 
1007  const IOobject& io,
1008  const word& instance,
1009  const word& procsDir
1010 ) const
1011 {
1012  return
1013  processorsCasePath(io, procsDir)
1014  /instance
1015  /io.db().dbDir()
1016  /io.local();
1017 }
1018 
1019 
1022  const fileName& dir,
1023  const word& procsDir
1024 ) const
1025 {
1026  // Check if directory is processorDDD
1027  word caseName(dir.name());
1028 
1029  std::string::size_type pos = caseName.find("processor");
1030  if (pos == 0)
1031  {
1032  if (caseName.size() <= 9 || caseName[9] == 's')
1033  {
1034  WarningInFunction << "Directory " << dir
1035  << " does not end in old-style processorDDD" << endl;
1036  }
1037 
1038  return dir.path()/procsDir;
1039  }
1040  else
1041  {
1042  return fileName::null;
1043  }
1044 }
1045 
1046 
1049  const fileName& objectPath,
1050  fileName& path,
1051  fileName& procDir,
1052  fileName& local,
1053 
1054  label& groupStart,
1055  label& groupSize,
1056 
1057  label& nProcs
1058 )
1059 {
1060  path.clear();
1061  procDir.clear();
1062  local.clear();
1063 
1064  // Potentially detected start of number of processors in local group
1065  groupStart = -1;
1066  groupSize = 0;
1067 
1068  // Potentially detected number of processors
1069  nProcs = -1;
1070 
1071  // Search for processor at start of line or /processor
1072  std::string::size_type pos = objectPath.find("processor");
1073  if (pos == string::npos)
1074  {
1075  return -1;
1076  }
1077 
1078  // "processorDDD"
1079  // "processorsNNN"
1080  // "processorsNNN_AA-BB"
1081 
1082 
1083  if (pos > 0 && objectPath[pos-1] != '/')
1084  {
1085  // Directory not starting with "processor" e.g. "somenamewithprocessor"
1086  return -1;
1087  }
1088 
1089  procDir = objectPath;
1090 
1091  // Strip leading directory
1092  if (pos > 0)
1093  {
1094  path = objectPath.substr(0, pos-1);
1095  procDir = objectPath.substr(pos);
1096  }
1097 
1098  // Strip trailing local directory
1099  pos = procDir.find('/');
1100  if (pos != string::npos)
1101  {
1102  local = procDir.substr(pos+1);
1103  procDir = procDir.substr(0, pos);
1104  }
1105 
1106  // Now procDir is e.g.
1107  // - processor0
1108  // - processors0
1109  // - processorBananas
1110 
1111  // Look for number after "processor"
1112 
1113  fileName f(procDir.substr(9));
1114 
1115  if (f.size() && f[0] == 's')
1116  {
1117  // "processorsNNN"
1118 
1119  f = f.substr(1);
1120 
1121  // Detect "processorsNNN_AA-BB"
1122  {
1123  std::string::size_type fromStart = f.find("_");
1124  std::string::size_type toStart = f.find("-");
1125  if (fromStart != string::npos && toStart != string::npos)
1126  {
1127  string nProcsName(f.substr(0, fromStart));
1128  string fromName(f.substr(fromStart+1, toStart-(fromStart+1)));
1129  string toName(f.substr(toStart+1));
1130 
1131  label groupEnd = -1;
1132  if
1133  (
1134  Foam::read(fromName.c_str(), groupStart)
1135  && Foam::read(toName.c_str(), groupEnd)
1136  && Foam::read(nProcsName.c_str(), nProcs)
1137  )
1138  {
1139  groupSize = groupEnd-groupStart+1;
1140  return -1;
1141  }
1142  }
1143  }
1144 
1145  // Detect "processorsN"
1146  label n;
1147  if (Foam::read(f.c_str(), n))
1148  {
1149  nProcs = n;
1150  }
1151  return -1;
1152  }
1153  else
1154  {
1155  // Detect "processorN"
1156  label proci;
1157  if (Foam::read(f.c_str(), proci))
1158  {
1159  return proci;
1160  }
1161  else
1162  {
1163  return -1;
1164  }
1165  }
1166 }
1167 
1168 
1170 {
1171  fileName path, pDir, local;
1172  label start, size, nProcs;
1173  return splitProcessorPath(fName, path, pDir, local, start, size, nProcs);
1174 }
1175 
1176 
1177 // * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
1178 
1180 {
1181  if (!fileOperation::fileHandlerPtr_.valid())
1182  {
1183  word handler(getEnv("FOAM_FILEHANDLER"));
1184 
1185  if (!handler.size())
1186  {
1188  }
1189 
1191  }
1193 }
1194 
1195 
1197 {
1198  if (fileOperation::fileHandlerPtr_.valid())
1199  {
1200  if
1201  (
1202  newHandlerPtr.valid()
1203  && newHandlerPtr->type() == fileOperation::fileHandlerPtr_->type()
1204  )
1205  {
1206  return;
1207  }
1208  }
1210 
1211  if (newHandlerPtr.valid())
1212  {
1213  fileOperation::fileHandlerPtr_ = newHandlerPtr;
1214  }
1215 }
1216 
1217 
1218 Foam::fileName Foam::search(const word& file, const fileName& directory)
1219 {
1220  // Search the current directory for the file
1221  fileNameList files(fileHandler().readDir(directory));
1222  forAll(files, i)
1223  {
1224  if (files[i] == file)
1225  {
1226  return directory/file;
1227  }
1228  }
1229 
1230  // If not found search each of the sub-directories
1232  forAll(dirs, i)
1233  {
1234  fileName path = search(file, directory/dirs[i]);
1235  if (path != fileName::null)
1236  {
1237  return path;
1238  }
1239  }
1240 
1241  return fileName::null;
1242 }
1243 
1244 
1245 void Foam::cpFiles(const fileName& srcDir, const fileName& targetDir)
1246 {
1247  mkDir(targetDir);
1248 
1249  const fileNameList srcFiles(readDir(srcDir, fileType::file, true));
1250 
1251  forAll(srcFiles, filei)
1252  {
1253  cp(srcDir/srcFiles[filei], targetDir);
1254  }
1255 }
1256 
1257 
1258 // ************************************************************************* //
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
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:303
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: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
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
Checking for changes to files.
Definition: fileMonitor.H:61
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:323
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:312
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.
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:94
virtual ~fileOperation()
Destructor.
static int & msgType()
Message tag of standard messages.
Definition: UPstream.H:476
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: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: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.
fileName path() const
Return complete path.
Definition: IOobject.C:348
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 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:400
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.
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: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
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
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:219
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:342
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
const fileName & instance() const
Definition: IOobject.H:390
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:652
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
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
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:353
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:419
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.
fileName path(UMean.rootPath()/UMean.caseName()/functionObjects::writeFile::outputPrefix/"graphs"/UMean.instance())
#define InfoInFunction
Report an information message using Foam::Info.