MoReFEM
Loading...
Searching...
No Matches
Public Types | Public Member Functions | Private Member Functions | Private Attributes
MoReFEM::FilesystemNS::Directory Class Reference

Class used to manage directories in MoReFEM. More...

#include <Directory.hpp>

Collaboration diagram for MoReFEM::FilesystemNS::Directory:

Public Types

using self = Directory
 Alias to the type of the class.
 
using unique_ptr = std::unique_ptr<self>
 Smart pointer to hold it.
 
using const_unique_ptr = std::unique_ptr<const self>
 Smart pointer to hold it.
 

Public Member Functions

const std::string & GetPath () const noexcept
 Get the underlying Unix path.
 
File AddFile (std::string_view filename) const
 Define path to a file in the directory.
 
behaviour GetBehaviour () const noexcept
 Returns the behaviour.
 
void SetBehaviour (behaviour new_behaviour, const std::source_location location=std::source_location::current())
 Changes the behaviour.
 
const Wrappers::MpiGetMpi () const noexcept
 Accessor to Mpi object (if relevant).
 
bool IsMpi () const noexcept
 Whether mpi is considered or not.
 
bool IsWithRank () const noexcept
 Whether a rank was given in construction.
 
bool DoExist () const noexcept
 Tells whether the folder exists on the filesystem and is properly a directory.
 
void Remove (const std::source_location location=std::source_location::current())
 Remove the directory on disk.
 
void AddSubdirectory (std::string_view subdirectory)
 Modify current directory so that it points to a subdirectory.
 
const std::filesystem::directory_entry & GetDirectoryEntry () const noexcept
 Constant accessor to the underlying std::filesystem::directory_entry object.
 
void ActOnFilesystem (const std::source_location location=std::source_location::current()) const
 The method which will enact on the filesystem what has been set in the object.
 
Special members.
 Directory (const Wrappers::Mpi &mpi, const std::filesystem::path &path, behaviour directory_behaviour, add_rank do_add_rank=add_rank::yes, const std::source_location location=std::source_location::current())
 Constructor.
 
 Directory (const std::filesystem::path &path, behaviour directory_behaviour, const std::source_location location=std::source_location::current())
 Simple constructor: no mpi involved - so no rank whatsoever added.
 
 Directory (const Directory &parent_directory, std::filesystem::path &&subdirectory, std::optional< behaviour > directory_behaviour=std::nullopt, const std::source_location location=std::source_location::current())
 Constructor of a Directory which is a subdirectory on an already existing parent_directory.
 
template<class StringT >
 Directory (const Directory &parent_directory, std::vector< StringT > &&layers, std::optional< behaviour > directory_behaviour=std::nullopt, const std::source_location location=std::source_location::current())
 Constructor of a Directory which is several layers of directories inside an already existing parent_directory.
 
 ~Directory ()=default
 Destructor.
 
 Directory (const Directory &rhs)=default
 The copy constructor.
 
 Directory (Directory &&rhs)=default
 The move constructor.
 
Directoryoperator= (const Directory &rhs)=delete
 The (copy) operator=.
 
Directoryoperator= (Directory &&rhs)=delete
 The (move) operator=.
 

Private Member Functions

std::filesystem::directory_entry & GetNonCstDirectoryEntry () noexcept
 Non constant accessor to the underlying std::filesystem::directory_entry object.
 
void CollectAnswer (const std::source_location location=std::source_location::current()) const
 Helper method for the 'ask' behaviour.
 
const Wrappers::MpiGetMpiPtr () const noexcept
 Accessor to Mpi pointer - required to define some constructors.
 

Private Attributes

std::filesystem::directory_entry directory_entry_
 Path of the directory.
 
const Wrappers::Mpi *const mpi_
 Mpi object.
 
behaviour directory_behaviour_
 What to do at the construction of the Directory object.
 
const bool with_rank_
 Whether the rank was given in construction.
 

Detailed Description

Class used to manage directories in MoReFEM.

This class is built upon std::filesystem, but as I am not fond of the API provided in the STL I encapsulated it here.

Among the thing I don't like in std::filesystem:

std::filesystem::path path { ... };
std::filesystem::directory_entry dir_entry { path };
std::cout << dir_entry.exists() << std::endl; // Assuming the path exists, print true
bool is_properly_deleted = std::filesystem::remove(path);
assert(is_properly_deleted);
std::cout << dir_entry.exists() << std::endl; // Still print true!!!

You need to call refresh if you want the information to be up-to-date, but this is a non constant method... meaning you need to use non constant references for your filesystem-related objects!

The latter is the reason directory_entry_ data attribute is mutable: I want to be able to refresh properly under the hood but indicate clearly the filesystem object is not to be manipulated carelessly.

Moreover, this Directory class is also used to deal properly with the parallel nature of the library: we do not want to introduce race conditions when we want to create a directory, and we don't want either to make assumption upon the nature of the filesystem used in parallel (e.g. does each rank write on the same filesystem or on a different one?)

A simple way to do so which alleviate many problems is simply to automatically add a subdirectory indicating the rank; the convention in MoReFEM is to simply call it Rank_i where i is the rank. This way, each rank manage its outputs as it wishes.

Of course, it is not always what we want: for input data there is not much sense doing this. For some behaviour such as read or ignore, it is therefore possible to use in some constructors an argument to specify you do not want to extend with such Rank subdir your underlying path.

It can't be done for all behaviour: we really want to force users to use the safety net we provided within the class. If you really wat to circumvent it (might be the case for some tests, but please really don't do that in a model...) you may use the STL filesystem :

std::filesystem::path directory_to_create { ... };
std::filesystem::create_directories(directory_to_create);
FilesystemNS::Directory directory { directory_to_create, FilesystemNS::behaviour::ignore);
Class used to manage directories in MoReFEM.
Definition Directory.hpp:130

You may then benefit from Directory API such as AddFile() method,

Member Typedef Documentation

◆ self

Alias to the type of the class.

Constructor & Destructor Documentation

◆ Directory() [1/6]

MoReFEM::FilesystemNS::Directory::Directory ( const Wrappers::Mpi & mpi,
const std::filesystem::path & path,
behaviour directory_behaviour,
add_rank do_add_rank = add_rank::yes,
const std::source_location location = std::source_location::current() )
explicit

Constructor.

Parameters
[in]mpiMpi object which knows the rank of the processor, the total number of processors, etc...
Parameters
[in]directory_behaviourBehaviour of the directory, among:
  • overwrite: Remove the pre-existing one and recreate it.
  • quit: Quit the program if the directory exists.
  • read: this mode expects the directory to exist and throws an exception otherwise.
  • create: create a new directory - it is expected here it doesn't exist yet (and an exception is thrown if it does).
  • create_if_necessary: create the directory if it doesn't exist yet
  • ask: Ask the end user if he wants to override or not. If he chooses not to do so, the program ends. Mpi is properly handled (the interface is properly rerouted to root processor which is the sole able to communicate with stdin).
  • ignore: Do nothing - whether the directory exist or not. This might be useful if you want to set the behaviour later; I would nonetheless not recommend using this possibility much as we lose part of the appeal of using a class such as Directory doing so.

Remember that Directory constructor never acts directly on the filesystem; you need to call ActOnFilesystem method if you want an action on the filesystem (typically create a directory).

Parameters
[in]pathUnix path of the directory.
[in]do_add_rankWhether a "Rank_" part is added to the path.
Attention
This function is syntactic sugar for file or directory manipulation and has no pretension to handle by itself thread safety.
Parameters
[in]locationSTL object with relevant information about the calling site (usually to help when an exception is thrown.

◆ Directory() [2/6]

MoReFEM::FilesystemNS::Directory::Directory ( const std::filesystem::path & path,
behaviour directory_behaviour,
const std::source_location location = std::source_location::current() )
explicit

Simple constructor: no mpi involved - so no rank whatsoever added.

This constructor can only be used with 'read' and 'ignore' policy (this evacuates race conditions and management on whether each rank is on the same filesystem or not).

Parameters
[in]directory_behaviourBehaviour of the directory, among:
  • overwrite: Remove the pre-existing one and recreate it.
  • quit: Quit the program if the directory exists.
  • read: this mode expects the directory to exist and throws an exception otherwise.
  • create: create a new directory - it is expected here it doesn't exist yet (and an exception is thrown if it does).
  • create_if_necessary: create the directory if it doesn't exist yet
  • ask: Ask the end user if he wants to override or not. If he chooses not to do so, the program ends. Mpi is properly handled (the interface is properly rerouted to root processor which is the sole able to communicate with stdin).
  • ignore: Do nothing - whether the directory exist or not. This might be useful if you want to set the behaviour later; I would nonetheless not recommend using this possibility much as we lose part of the appeal of using a class such as Directory doing so.

Remember that Directory constructor never acts directly on the filesystem; you need to call ActOnFilesystem method if you want an action on the filesystem (typically create a directory).

Parameters
[in]pathPath of the directory. Will be adjusted to match your OS filesystem.
Attention
This function is syntactic sugar for file or directory manipulation and has no pretension to handle by itself thread safety.
Parameters
[in]locationSTL object with relevant information about the calling site (usually to help when an exception is thrown.

◆ Directory() [3/6]

MoReFEM::FilesystemNS::Directory::Directory ( const Directory & parent_directory,
std::filesystem::path && subdirectory,
std::optional< behaviour > directory_behaviour = std::nullopt,
const std::source_location location = std::source_location::current() )
explicit

Constructor of a Directory which is a subdirectory on an already existing parent_directory.

Parameters
[in]subdirectoryName of the subdirectory relative to parent_directory.
[in]parent_directoryThe directory into which the new one is created (or read - depends on behaviour). The constructed directory takes the same attributes than its parent directory - except obviously for the path.
[in]directory_behaviourDirectory behaviour; if nullopt the behaviour of the parent directory is used (you should stick with this choice most of the time),
Attention
This function is syntactic sugar for file or directory manipulation and has no pretension to handle by itself thread safety.
Parameters
[in]locationSTL object with relevant information about the calling site (usually to help when an exception is thrown.

◆ Directory() [4/6]

template<class StringT >
MoReFEM::FilesystemNS::Directory::Directory ( const Directory & parent_directory,
std::vector< StringT > && layers,
std::optional< behaviour > directory_behaviour = std::nullopt,
const std::source_location location = std::source_location::current() )
explicit

Constructor of a Directory which is several layers of directories inside an already existing parent_directory.

Parameters
[in]layersNames of the layers of subdirectories. For instance if { "Foo", "Bar"}, it will create inside parent_directory the subdirectory "Foo/Bar/".
[in]parent_directoryThe directory into which the new one is created (or read - depends on behaviour). The constructed directory takes the same attributes than its parent directory - except obviously for the path.
[in]directory_behaviourDirectory behaviour; if nullopt the behaviour of the parent directory is used (you should stick with this choice most of the time),
Attention
This function is syntactic sugar for file or directory manipulation and has no pretension to handle by itself thread safety.
Template Parameters
StringTType of subdirectory, which may actually be anything for which operator<< has been overloaded (avoid nonetheless values with spaces inside...)
Parameters
[in]locationSTL object with relevant information about the calling site (usually to help when an exception is thrown.

◆ Directory() [5/6]

MoReFEM::FilesystemNS::Directory::Directory ( const Directory & rhs)
default

The copy constructor.

Parameters
[in]rhsThe object from which the construction occurs.

◆ Directory() [6/6]

MoReFEM::FilesystemNS::Directory::Directory ( Directory && rhs)
default

The move constructor.

Parameters
[in]rhsThe object from which the construction occurs.

Member Function Documentation

◆ operator=() [1/2]

Directory & MoReFEM::FilesystemNS::Directory::operator= ( const Directory & rhs)
delete

The (copy) operator=.

Parameters
[in]rhsThe object from which the affectation occurs.
Returns
Reference to the object (to enable chained affectation).

◆ operator=() [2/2]

Directory & MoReFEM::FilesystemNS::Directory::operator= ( Directory && rhs)
delete

The (move) operator=.

Parameters
[in]rhsThe object from which the affectation occurs.
Returns
Reference to the object (to enable chained affectation).

◆ AddFile()

File MoReFEM::FilesystemNS::Directory::AddFile ( std::string_view filename) const

Define path to a file in the directory.

Parameters
[in]filenameName of the file.
Returns
File object.
Attention
This function is syntactic sugar for file or directory manipulation and has no pretension to handle by itself thread safety.

◆ SetBehaviour()

void MoReFEM::FilesystemNS::Directory::SetBehaviour ( behaviour new_behaviour,
const std::source_location location = std::source_location::current() )

Changes the behaviour.

Parameters
[in]new_behaviourAs written on the tag...
Parameters
[in]locationSTL object with relevant information about the calling site (usually to help when an exception is thrown.
Attention
You should be cautious before using this one; this was introduced to soften the behaviour (i.e. overwrite -> read) for some tests which create first directories and then use some post-processing on them.

◆ Remove()

void MoReFEM::FilesystemNS::Directory::Remove ( const std::source_location location = std::source_location::current())

Remove the directory on disk.

Parameters
[in]locationSTL object with relevant information about the calling site (usually to help when an exception is thrown.

◆ AddSubdirectory()

void MoReFEM::FilesystemNS::Directory::AddSubdirectory ( std::string_view subdirectory)

Modify current directory so that it points to a subdirectory.

Attention
It is NOT the preferred way to create a subdirectory: it is much better to create another Directory object with the proper constructor to do so. However, it is handy as it cut short the code for testing models outputs and comparing them to the stored expected results.
Parameters
[in]subdirectoryName of the subdirectory layer that will hence be pointed by current object.
Attention
This function is syntactic sugar for file or directory manipulation and has no pretension to handle by itself thread safety.

◆ ActOnFilesystem()

void MoReFEM::FilesystemNS::Directory::ActOnFilesystem ( const std::source_location location = std::source_location::current()) const

The method which will enact on the filesystem what has been set in the object.

For instance, if behaviour_ is behaviour::create the directory will be created on the filesystem (or STL will throw an exception).

Parameters
[in]locationSTL object with relevant information about the calling site (usually to help when an exception is thrown.

◆ CollectAnswer()

void MoReFEM::FilesystemNS::Directory::CollectAnswer ( const std::source_location location = std::source_location::current()) const
private

Helper method for the 'ask' behaviour.

This behaviour requires inter-processor communication: each rank must tell root processor whether the directory already exist or not, and if some do root processor must ask the user what to do. Then it musts transmit back answers to each rank, which then must take action.

Parameters
[in]locationSTL object with relevant information about the calling site (usually to help when an exception is thrown.

Field Documentation

◆ directory_entry_

std::filesystem::directory_entry MoReFEM::FilesystemNS::Directory::directory_entry_
mutableprivate

Path of the directory.

The 'mutable' is due to a quirk in STL I dislike: some methods of std::filesystem::directory_entry such as exists may provide a wrong answer if refresh() is not called first... but the latter is non constant. To circumvent the potential wrong answer I this need to call refresh() first, but aside from that the methods such as DoExist() are morally const...

◆ directory_behaviour_

behaviour MoReFEM::FilesystemNS::Directory::directory_behaviour_
private

What to do at the construction of the Directory object.

Options are:

  • overwrite: Remove the pre-existing one and recreate it.
  • quit: Quit the program if the directory exists.
  • read: this mode expects the directory to exist and throws an exception otherwise.
  • create: create a new directory - it is expected here it doesn't exist yet (and an exception is thrown if it does).
  • create_if_necessary: create the directory if it doesn't exist yet
  • ask: Ask the end user if he wants to override or not. If he chooses not to do so, the program ends. Mpi is properly handled (the interface is properly rerouted to root processor which is the sole able to communicate with stdin).
  • ignore: Do nothing - whether the directory exist or not. This might be useful if you want to set the behaviour later; I would nonetheless not recommend using this possibility much as we lose part of the appeal of using a class such as Directory doing so.

Remember that Directory constructor never acts directly on the filesystem; you need to call ActOnFilesystem method if you want an action on the filesystem (typically create a directory).


The documentation for this class was generated from the following file: