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