OutputFileHandler.cpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2010
00004 
00005 University of Oxford means the Chancellor, Masters and Scholars of the
00006 University of Oxford, having an administrative office at Wellington
00007 Square, Oxford OX1 2JD, UK.
00008 
00009 This file is part of Chaste.
00010 
00011 Chaste is free software: you can redistribute it and/or modify it
00012 under the terms of the GNU Lesser General Public License as published
00013 by the Free Software Foundation, either version 2.1 of the License, or
00014 (at your option) any later version.
00015 
00016 Chaste is distributed in the hope that it will be useful, but WITHOUT
00017 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
00019 License for more details. The offer of Chaste under the terms of the
00020 License is subject to the License being interpreted in accordance with
00021 English Law and subject to any action against the University of Oxford
00022 being under the jurisdiction of the English Courts.
00023 
00024 You should have received a copy of the GNU Lesser General Public License
00025 along with Chaste. If not, see <http://www.gnu.org/licenses/>.
00026 
00027 */
00028 
00029 
00030 #include "OutputFileHandler.hpp"
00031 
00032 #include <cstdlib>
00033 #include <sys/stat.h>
00034 
00035 #include "PetscTools.hpp"
00036 #include "Exception.hpp"
00037 #include "ArchiveLocationInfo.hpp"
00038 #include "GetCurrentWorkingDirectory.hpp"
00039 
00040 OutputFileHandler::OutputFileHandler(const std::string &rDirectory,
00041                                      bool cleanOutputDirectory)
00042 {
00043     //Is it a valid request for a directory?
00044     if (rDirectory.find("..") != std::string::npos)
00045     {
00046         EXCEPTION("Will not create directory: " + rDirectory +
00047                 " due to it potentially being above, and cleaning, CHASTE_TEST_OUTPUT.");
00048     }
00049 
00050     mDirectory = MakeFoldersAndReturnFullPath(rDirectory);
00051 
00052     // Clean the directory (default)
00053     if (rDirectory != "" && cleanOutputDirectory) // Don't clean CHASTE_TEST_OUTPUT
00054     {
00055         std::string command = "test -e " + mDirectory + ".chaste_deletable_folder";
00056         int return_value = system(command.c_str());
00057         if (return_value != 0)
00058         {
00059             EXCEPTION("Cannot delete " + mDirectory + " because signature file \".chaste_deletable_folder\" is not present.");
00060         }
00061 
00062         // Are we the master process?  Only the master should delete files
00063         if (PetscTools::AmMaster())
00064         {
00065             //Remove whatever was there before
00066             //Note that the /* part prevents removal of hidden files (.filename), which is useful in NFS systems
00067             EXPECT0(system, "rm -rf " + mDirectory + "/*");
00068         }
00069         // Wait for master to finish before going on to use the directory.
00070         PetscTools::Barrier("OutputFileHandler");
00071     }
00072 }
00073 
00074 std::string OutputFileHandler::GetChasteTestOutputDirectory()
00075 {
00076     char *chaste_test_output = getenv("CHASTE_TEST_OUTPUT");
00077     std::string directory_root;
00078     if (chaste_test_output == NULL || *chaste_test_output == 0)
00079     {
00080         // Default to 'testoutput' folder within the current directory
00081         directory_root = GetCurrentWorkingDirectory() + "/testoutput/";
00082     }
00083     else
00084     {
00085         if (*chaste_test_output != '/')
00086         {
00087             // It's a relative path; prepend with the CWD
00088             directory_root = GetCurrentWorkingDirectory() + "/" + chaste_test_output;
00089         }
00090         else
00091         {
00092 #define COVERAGE_IGNORE
00093             // This branch is never taken on the build machines, because CHASTE_TEST_OUTPUT is set to a relative path.
00094             directory_root = std::string(chaste_test_output);
00095 #undef COVERAGE_IGNORE
00096         }
00097     }
00098     AddTrailingSlash(directory_root);
00099 
00100     return directory_root;
00101 }
00102 
00103 
00104 std::string OutputFileHandler::MakeFoldersAndReturnFullPath(const std::string& rDirectory)
00105 {
00106     std::string directory_root = GetChasteTestOutputDirectory();
00107     std::string directory = directory_root + rDirectory;
00108     AddTrailingSlash(directory);
00109 
00110     // Are we the master process?  Only the master should make any new directories
00111     if (PetscTools::AmMaster())
00112     {
00113         // Re-create the output directory structure:
00114         std::string command = "test -d " + directory;
00115         int return_value = system(command.c_str());
00116         if (return_value!=0)
00117         {
00118             // We make as many folders as necessary here.
00119             EXPECT0(system,"mkdir -p " + directory);
00120 
00122             EXPECT0(system,"touch " + directory + ".chaste_deletable_folder");
00123         }
00124     }
00125     // Wait for master to finish before going on to use the directory.
00126     PetscTools::Barrier("OutputFileHandler::MakeFoldersAndReturnFullPath");
00127 
00128     return directory;
00129 }
00130 
00131 
00132 std::string OutputFileHandler::GetOutputDirectoryFullPath()
00133 {
00134     return mDirectory;
00135 }
00136 
00137 out_stream OutputFileHandler::OpenOutputFile(const std::string& rFileName,
00138                                              std::ios_base::openmode mode)
00139 {
00140     out_stream p_output_file(new std::ofstream((mDirectory+rFileName).c_str(), mode));
00141     if (!p_output_file->is_open())
00142     {
00143         EXCEPTION("Could not open file \"" + rFileName + "\" in " + mDirectory);
00144     }
00145     return p_output_file;
00146 }
00147 
00148 
00149 out_stream OutputFileHandler::OpenOutputFile(const std::string& rFileName,
00150                                              unsigned number,
00151                                              const std::string& rFileFormat,
00152                                              std::ios_base::openmode mode)
00153 {
00154     std::stringstream string_stream;
00155     string_stream << rFileName << number << rFileFormat;
00156     return OpenOutputFile(string_stream.str(), mode);
00157 }
00158 
00159 void OutputFileHandler::SetArchiveDirectory()
00160 {
00161     ArchiveLocationInfo::SetArchiveDirectory(GetOutputDirectoryFullPath());
00162 }
00163 
00164 void OutputFileHandler::AddTrailingSlash(std::string& rDirectory)
00165 {
00166     // Add a trailing slash if not already there
00167     if (! ( *(rDirectory.end()-1) == '/'))
00168     {
00169         rDirectory = rDirectory + "/";
00170     }
00171 }

Generated by  doxygen 1.6.2