From b4413727b9a1f7aad1d65ca89e5ff3266b577637 Mon Sep 17 00:00:00 2001 From: Matthew Abruzzo Date: Thu, 7 Sep 2023 12:33:29 -0400 Subject: [PATCH] Ensures that any directories specifed as part of ``outdir`` exist. This is accomplished through the new ``Ensure_Outdir_Exists`` function. Along the way, I introduced a helper function ``Is_Root_Proc()``, local to ``io.cpp`` so that we can reduce some of the ``ifdef`` statements. --- src/io/io.cpp | 68 +++++++++++++++++++++++++++++++++++++++++---------- src/io/io.h | 6 +++++ src/main.cpp | 1 + 3 files changed, 62 insertions(+), 13 deletions(-) diff --git a/src/io/io.cpp b/src/io/io.cpp index 420982309..b487608eb 100644 --- a/src/io/io.cpp +++ b/src/io/io.cpp @@ -6,9 +6,11 @@ #include #include +#include #include #include #include +#include #ifdef HDF5 #include #endif // HDF5 @@ -32,13 +34,22 @@ * output routine */ void rotate_point(Real x, Real y, Real z, Real delta, Real phi, Real theta, Real *xp, Real *yp, Real *zp); -void Create_Log_File(struct parameters P) +/* local function that designates whether we are using a root-process. It gives + * gives a sensible result regardless of whether we are using MPI */ +static inline bool Is_Root_Proc() { #ifdef MPI_CHOLLA - if (procID != 0) { + return procID == root; +#else + return true; +#endif +} + +void Create_Log_File(struct parameters P) +{ + if (!Is_Root_Proc()) { return; } -#endif std::string file_name(LOG_FILE_NAME); chprintf("\nCreating Log File: %s \n\n", file_name.c_str()); @@ -64,11 +75,9 @@ void Create_Log_File(struct parameters P) void Write_Message_To_Log_File(const char *message) { -#ifdef MPI_CHOLLA - if (procID != 0) { + if (!!Is_Root_Proc()) { return; } -#endif std::string file_name(LOG_FILE_NAME); std::ofstream out_file; @@ -2587,20 +2596,14 @@ void Grid3D::Read_Grid_HDF5(hid_t file_id, struct parameters P) int chprintf(const char *__restrict sdata, ...) // NOLINT(cert-dcl50-cpp) { int code = 0; -#ifdef MPI_CHOLLA /*limit printf to root process only*/ - if (procID == root) { -#endif /*MPI_CHOLLA*/ - + if (!Is_Root_Proc()) { va_list ap; va_start(ap, sdata); code = vfprintf(stdout, sdata, ap); // NOLINT(clang-analyzer-valist.Uninitialized) va_end(ap); fflush(stdout); - -#ifdef MPI_CHOLLA } -#endif /*MPI_CHOLLA*/ return code; } @@ -2661,3 +2664,42 @@ void write_debug(Real *Value, const char *fname, int nValues, int iProc) fclose(fp); } + +void Ensure_Outdir_Exists(std::string outdir) +{ + if (outdir == "") { + return; + } else if (Is_Root_Proc()) { + // if the last character of outdir is not a '/', then the substring of + // characters after the final '/' (or entire string if there isn't any '/') + // is treated as a file-prefix + // + // this is accomplished here: + std::filesystem::path without_file_prefix = std::filesystem::path(outdir).parent_path(); + + if (!without_file_prefix.empty()) { + // try to create all directories specified within outdir (does nothing if + // the directories already exist) + std::error_code err_code; + std::filesystem::create_directories(without_file_prefix, err_code); + + // confirm that an error-code wasn't set & that the path actually refers + // to a directory (it's unclear from docs whether err-code is set in that + // case) + if (err_code || !std::filesystem::is_directory(without_file_prefix)) { + chprintf( + "something went wrong while trying to create the path to the " + "output-dir: %s\n", + outdir.c_str()); + chexit(1); + } + } + } + + // this barrier ensures we won't ever encounter a scenario when 1 process + // tries to write a file to a non-existent directory before the root process + // has a chance to create it +#ifdef MPI_CHOLLA + MPI_Barrier(world); +#endif +} diff --git a/src/io/io.h b/src/io/io.h index a24fe788c..bf547616e 100644 --- a/src/io/io.h +++ b/src/io/io.h @@ -51,6 +51,12 @@ void Write_Message_To_Log_File(const char* message); void write_debug(Real* Value, const char* fname, int nValues, int iProc); +/* Checks whether the directories referred to within outdir exist. Creates them + * if they don't. It gracefully handles cases where outdir contains a prefix + * for the output files. + */ +void Ensure_Outdir_Exists(std::string outdir); + #ifdef HDF5 // From io/io.cpp diff --git a/src/main.cpp b/src/main.cpp index b33ee8eba..39c201ce2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -93,6 +93,7 @@ int main(int argc, char *argv[]) chprintf("Input directory: %s\n", P.indir); } chprintf("Output directory: %s\n", P.outdir); + Ensure_Outdir_Exists(P.outdir); // Check the configuration Check_Configuration(P);