fileOperation.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | Copyright (C) 2017 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"
32 #include "objectRegistry.H"
33 #include "decomposedBlockData.H"
34 #include "polyMesh.H"
35 #include "registerSwitch.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 
47  {
48  public:
50  {
52  (
53  "fileHandler",
54  "handler",
55  "override the fileHandler"
56  );
57  }
58  };
59 
61 
63  (
64  debug::optimisationSwitches().lookupOrAddDefault
65  (
66  "fileHandler",
67  //Foam::fileOperations::uncollatedFileOperation::typeName,
68  word("uncollated"),
69  false,
70  false
71  )
72  );
73 
74  word fileOperation::processorsDir = "processors";
75 }
76 
77 
78 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
79 
81 {
82  if (!monitorPtr_.valid())
83  {
84  monitorPtr_.reset
85  (
86  new fileMonitor
87  (
90  )
91  );
92  }
93  return monitorPtr_();
94 }
95 
96 
98 (
99  const fileNameList& dirEntries,
100  const word& constantName
101 )
102 {
103  // Initialise instant list
104  instantList Times(dirEntries.size() + 1);
105  label nTimes = 0;
106 
107  // Check for "constant"
108  bool haveConstant = false;
109  forAll(dirEntries, i)
110  {
111  if (dirEntries[i] == constantName)
112  {
113  Times[nTimes].value() = 0;
114  Times[nTimes].name() = dirEntries[i];
115  nTimes++;
116  haveConstant = true;
117  break;
118  }
119  }
120 
121  // Read and parse all the entries in the directory
122  forAll(dirEntries, i)
123  {
124  //IStringStream timeStream(dirEntries[i]);
125  //token timeToken(timeStream);
126 
127  //if (timeToken.isNumber() && timeStream.eof())
128  scalar timeValue;
129  if (readScalar(dirEntries[i].c_str(), timeValue))
130  {
131  Times[nTimes].value() = timeValue;
132  Times[nTimes].name() = dirEntries[i];
133  nTimes++;
134  }
135  }
136 
137  // Reset the length of the times list
138  Times.setSize(nTimes);
139 
140  if (haveConstant)
141  {
142  if (nTimes > 2)
143  {
144  std::sort(&Times[1], Times.end(), instant::less());
145  }
146  }
147  else if (nTimes > 1)
148  {
149  std::sort(&Times[0], Times.end(), instant::less());
150  }
151 
152  return Times;
153 }
154 
155 
157 {
158  return
159  (isFile && Foam::isFile(f))
160  || (!isFile && Foam::isDir(f));
161 }
162 
163 
164 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
165 
167 {}
168 
169 
171 (
172  const word& type,
173  const bool verbose
174 )
175 {
176  if (debug)
177  {
178  InfoInFunction << "Constructing fileOperation" << endl;
179  }
180 
181  wordConstructorTable::iterator cstrIter =
182  wordConstructorTablePtr_->find(type);
183 
184  if (cstrIter == wordConstructorTablePtr_->end())
185  {
187  << "Unknown fileOperation type "
188  << type << nl << nl
189  << "Valid fileOperation types are" << endl
190  << wordConstructorTablePtr_->sortedToc()
191  << abort(FatalError);
192  }
193 
194  return autoPtr<fileOperation>(cstrIter()(verbose));
195 }
196 
197 
198 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
199 
201 {}
202 
203 
204 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
205 
207 (
208  const IOobject& io,
209  const word& typeName
210 ) const
211 {
212  return io.objectPath();
213 }
214 
215 
217 (
218  const regIOobject& io,
222  const bool valid
223 ) const
224 {
225  if (valid)
226  {
227  fileName pathName(io.objectPath());
228 
229  mkDir(pathName.path());
230 
231  autoPtr<Ostream> osPtr
232  (
233  NewOFstream
234  (
235  pathName,
236  fmt,
237  ver,
238  cmp
239  )
240  );
241 
242  if (!osPtr.valid())
243  {
244  return false;
245  }
246 
247  Ostream& os = osPtr();
248 
249  // If any of these fail, return (leave error handling to Ostream class)
250  if (!os.good())
251  {
252  return false;
253  }
254 
255  if (!io.writeHeader(os))
256  {
257  return false;
258  }
259 
260  // Write the data to the Ostream
261  if (!io.writeData(os))
262  {
263  return false;
264  }
265 
267  }
268  return true;
269 }
270 
271 
272 //Foam::fileName Foam::fileOperation::objectPath(const fileName& fName) const
273 //{
274 // return fName;
275 //}
276 
277 
279 {
280  fileName path;
281  fileName local;
284  (
285  fName,
286  path,
287  local
288  );
289 
290  fileName procsName(path/processorsDir/local);
291 
292  // Give preference to processors variant
293  if (proci != -1 && exists(procsName))
294  {
295  return procsName;
296  }
297  else if (exists(fName))
298  {
299  return fName;
300  }
301  else
302  {
303  return fileName::null;
304  }
305 }
306 
307 
309 {
310  return monitor().addWatch(fName);
311 }
312 
313 
314 bool Foam::fileOperation::removeWatch(const label watchIndex) const
315 {
316  return monitor().removeWatch(watchIndex);
317 }
318 
319 
321 (
322  const labelList& watchIndices,
323  const fileName& fName
324 ) const
325 {
326  forAll(watchIndices, i)
327  {
328  if (getFile(watchIndices[i]) == fName)
329  {
330  return i;
331  }
332  }
333  return -1;
334 }
335 
336 
338 (
339  regIOobject& rio,
340  const fileNameList& files
341 ) const
342 {
343  const labelList& watchIndices = rio.watchIndices();
344 
345  DynamicList<label> newWatchIndices;
346  labelHashSet removedWatches(watchIndices);
347 
348  forAll(files, i)
349  {
350  const fileName& f = files[i];
351  label index = findWatch(watchIndices, f);
352 
353  if (index == -1)
354  {
355  newWatchIndices.append(addWatch(f));
356  }
357  else
358  {
359  // Existing watch
360  newWatchIndices.append(watchIndices[index]);
361  removedWatches.erase(index);
362  }
363  }
364 
365  // Remove any unused watches
366  forAllConstIter(labelHashSet, removedWatches, iter)
367  {
368  removeWatch(watchIndices[iter.key()]);
369  }
370 
371  rio.watchIndices() = newWatchIndices;
372 }
373 
374 
376 {
377  return monitor().getFile(watchIndex);
378 }
379 
380 
382 (
383  const bool masterOnly,
384  const bool syncPar
385 ) const
386 {
387  monitor().updateStates(masterOnly, Pstream::parRun());
388 }
389 
390 
392 (
393  const label watchFd
394 ) const
395 {
396  return monitor().getState(watchFd);
397 }
398 
399 
400 void Foam::fileOperation::setUnmodified(const label watchFd) const
401 {
402  monitor().setUnmodified(watchFd);
403 }
404 
405 
407 (
408  const fileName& directory,
409  const word& constantName
410 ) const
411 {
412  if (debug)
413  {
415  << " : Finding times in directory " << directory << endl;
416  }
417 
418  // Read directory entries into a list
419  fileNameList dirEntries
420  (
422  (
423  directory,
425  )
426  );
427 
428  instantList times = sortTimes(dirEntries, constantName);
429 
430  // Check if directory is processorXXX
431  fileName procsDir
432  (
434  (
435  directory
436  )
437  );
438 
439  if (!procsDir.empty() && procsDir != directory)
440  {
441  fileNameList extraEntries
442  (
444  (
445  procsDir,
447  )
448  );
449 
450  instantList extraTimes = sortTimes(extraEntries, constantName);
451 
452  if (extraTimes.size())
453  {
454  bool haveConstant =
455  (
456  times.size() > 0
457  && times[0].name() == constantName
458  );
459 
460  bool haveExtraConstant =
461  (
462  extraTimes.size() > 0
463  && extraTimes[0].name() == constantName
464  );
465 
466  // Combine times
467  instantList combinedTimes(times.size()+extraTimes.size());
468  label sz = 0;
469  label extrai = 0;
470  if (haveExtraConstant)
471  {
472  extrai = 1;
473  if (!haveConstant)
474  {
475  combinedTimes[sz++] = extraTimes[0]; // constant
476  }
477  }
478  forAll(times, i)
479  {
480  combinedTimes[sz++] = times[i];
481  }
482  for (; extrai < extraTimes.size(); extrai++)
483  {
484  combinedTimes[sz++] = extraTimes[extrai];
485  }
486  combinedTimes.setSize(sz);
487  times.transfer(combinedTimes);
488 
489  // Sort
490  if (times.size() > 1)
491  {
492  label starti = 0;
493  if (times[0].name() == constantName)
494  {
495  starti = 1;
496  }
497  std::sort(&times[starti], times.end(), instant::less());
498 
499  // Filter out duplicates
500  label newi = starti+1;
501  for (label i = newi; i < times.size(); i++)
502  {
503  if (times[i].value() != times[i-1].value())
504  {
505  if (newi != i)
506  {
507  times[newi] = times[i];
508  }
509  newi++;
510  }
511  }
512 
513  times.setSize(newi);
514  }
515  }
516  }
517 
518  if (debug)
519  {
521  << " : Found times:" << times << endl;
522  }
523  return times;
524 }
525 
526 
528 (
529  const objectRegistry& db,
530  const fileName& instance,
531  const fileName& local,
532  word& newInstance
533 ) const
534 {
535  if (debug)
536  {
537  Pout<< "fileOperation::readObjects :"
538  << " db:" << db.objectPath()
539  << " instance:" << instance << endl;
540  }
541 
542  fileName path(db.path(instance, db.dbDir()/local));
543 
544  newInstance = word::null;
545  fileNameList objectNames;
546 
547  if (Foam::isDir(path))
548  {
549  newInstance = instance;
550  objectNames = Foam::readDir(path, fileName::FILE);
551  }
552  else
553  {
554  // Get processors equivalent of path
555 
556  fileName prefix;
557  fileName postfix;
560  (
561  path,
562  prefix,
563  postfix
564  );
565  fileName procsPath(prefix/processorsDir/postfix);
566 
567  if (proci != -1 && Foam::isDir(procsPath))
568  {
569  newInstance = instance;
570  objectNames = Foam::readDir(procsPath, fileName::FILE);
571  }
572  }
573  return objectNames;
574 }
575 
576 
578 (
579  const fileName& dir,
580  const fileName& local
581 ) const
582 {
583  if (Foam::isDir(dir/processorsDir))
584  {
585  fileName pointsFile
586  (
587  dir
588  /processorsDir
589  /"constant"
590  /local
592  /"points"
593  );
594 
595  if (Foam::isFile(pointsFile))
596  {
597  return decomposedBlockData::numBlocks(pointsFile);
598  }
599  else
600  {
601  WarningInFunction << "Cannot read file " << pointsFile
602  << " to determine the number of decompositions."
603  << " Falling back to looking for processor.*" << endl;
604  }
605  }
606 
607  label nProcs = 0;
608  while
609  (
610  isDir
611  (
612  dir
613  /(word("processor") + name(nProcs))
614  /"constant"
615  /local
617  )
618  )
619  {
620  ++nProcs;
621  }
622 
623  return nProcs;
624 }
625 
626 
628 {
629  if (!fileOperation::fileHandlerPtr_.valid())
630  {
631  word handler(getEnv("FOAM_FILEHANDLER"));
632 
633  if (!handler.size())
634  {
636  }
637 
638  fileOperation::fileHandlerPtr_ = fileOperation::New(handler, true);
639  }
641 }
642 
643 
645 {
646  if (fileOperation::fileHandlerPtr_.valid())
647  {
648  if
649  (
650  newHandlerPtr.valid()
651  && newHandlerPtr->type() == fileOperation::fileHandlerPtr_->type()
652  )
653  {
654  return;
655  }
656  }
657  fileOperation::fileHandlerPtr_.clear();
658 
659  if (newHandlerPtr.valid())
660  {
661  fileOperation::fileHandlerPtr_ = newHandlerPtr;
662  }
663 }
664 
665 
666 // ************************************************************************* //
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:104
#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
A class for handling file names.
Definition: fileName.H:69
fileOperation()
Construct null.
virtual fileMonitor::fileState getState(const label) const
Get current state of file (using handle)
error FatalError
Checking for changes to files.
Definition: fileMonitor.H:61
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:319
fileState
Enumeration defining the file state.
Definition: fileMonitor.H:69
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 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:253
static label numBlocks(const fileName &)
Detect number of blocks in a file.
const labelList & watchIndices() const
Return file-monitoring handles.
Definition: regIOobjectI.H:91
virtual ~fileOperation()
Destructor.
iterator end()
Return an iterator to end traversing the UList.
Definition: UListI.H:237
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:385
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.
static label splitProcessorPath(const fileName &, fileName &path, fileName &local)
Split fileName into part before processor and part after.
bool isDir(const fileName &, const bool followLink=true)
Does the name exist as a DIRECTORY in the file system?
Definition: POSIX.C:536
A class for handling words, derived from string.
Definition: word.H:59
virtual fileName getFile(const label) const
Get name of file being watched (using handle)
virtual instantList findTimes(const fileName &, const word &) const
Get sorted list of times.
void sort(UList< T > &)
Definition: UList.C:115
static void addOption(const word &opt, const string &param="", const string &usage="")
Add to an option to validOptions with usage information.
Definition: argList.C:95
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 succesful.
Definition: doubleScalar.H:63
virtual label addWatch(const fileName &) const
Add watching of a file. Returns handle.
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
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:551
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:53
static word processorsDir
Return the processors directory name (usually "processors")
Definition: fileOperation.H:78
static const char nl
Definition: Ostream.H:262
defineRunTimeSelectionTable(reactionRateFlameArea, dictionary)
#define FUNCTION_NAME
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
defineTypeNameAndDebug(combustionModel, 0)
static fileCheckTypes fileModificationChecking
Type of file modification checking.
Definition: IOobject.H:208
fileMonitor & monitor() const
Definition: fileOperation.C:80
labelList f(nPoints)
bool mkDir(const fileName &, mode_t=0777)
Make a directory and return an error if it could not be created.
Definition: POSIX.C:297
word name(const complex &)
Return a string representation of a complex.
Definition: complex.C:47
static bool isFileOrDir(const bool isFile, const fileName &)
Helper: check for file (isFile) or directory (!isFile)
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:394
static Stream & writeEndDivider(Stream &os)
Write the standard end file divider.
Definition: IOobjectI.H:108
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.
Definition: fileOperation.H:81
#define WarningInFunction
Report a warning using Foam::Warning.
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
static fileName processorsPath(const IOobject &, const word &)
Like io.path with provided instance and any &#39;processorXXX&#39;.
static instantList sortTimes(const fileNameList &, const word &)
Sort directory entries according to time value.
Definition: fileOperation.C:98
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.
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:641
virtual const fileName & dbDir() const
Local directory path of this objectRegistry relative to the time.
dictionary & optimisationSwitches()
The OptimisationSwitches sub-dictionary in the central controlDict.
Definition: debug.C:162
Registry of regIOobjects.
virtual bool writeData(Ostream &) const =0
Pure virtual writaData function.
virtual label findWatch(const labelList &watchIndices, const fileName &) const
Find index (or -1) of file in list of handles.
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:92
virtual fileName objectPath(const IOobject &io, const word &typeName) const
Generate disk file name for object. Opposite of filePath.
fileName objectPath() const
Return complete path + object name.
Definition: IOobject.H:412
void transfer(List< T > &)
Transfer the contents of the argument List into this list.
Definition: List.C:342
addArgsOptions intObj
Definition: fileOperation.C:60
bool exists(const fileName &, const bool checkGzip=true, const bool followLink=true)
Does the name exist (as DIRECTORY or FILE) in the file system?
Definition: POSIX.C:517
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.