OutputFileHandler.cpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2011
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 #include "OutputFileHandler.hpp"
00030 
00031 #include <cstdlib>
00032 #include <sys/stat.h>
00033 
00034 #include "PetscTools.hpp"
00035 #include "Exception.hpp"
00036 #include "ArchiveLocationInfo.hpp"
00037 #include "GetCurrentWorkingDirectory.hpp"
00038 #include "FileFinder.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             ABORT_IF_NON0(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 std::string OutputFileHandler::MakeFoldersAndReturnFullPath(const std::string& rDirectory) const
00104 {
00105     std::string directory_root = GetChasteTestOutputDirectory();
00106     std::string directories_to_add = rDirectory; // Get from a const to something we can mess with.
00107     AddTrailingSlash(directories_to_add);
00108     std::string directory = directory_root + directories_to_add;
00109 
00110     // Are we the master process? Only the master should make any new directories
00111     if (PetscTools::AmMaster())
00112     {
00113         // If necessary make the ChasteTestOutputDirectory - don't make it deleteable by Chaste
00114         std::string command = "test -d " + directory_root;
00115         int return_value = system(command.c_str());
00116         if (return_value!=0)
00117         {
00118             // We make as many folders as necessary here
00119             ABORT_IF_NON0(system, "mkdir -p " + directory_root);
00120         }
00121 
00122         // Now make all the sub-folders requested one-by-one and add the .chaste_deletable_folder file to them
00123         std::string remaining_directories = directories_to_add;
00124         std::string directory_to_add = "";
00125 
00126         // Create the output directory structure one folder at a time
00127         while (remaining_directories.find("/") != std::string::npos)
00128         {
00129             size_t found = remaining_directories.find_first_of("/");
00130             directory_to_add += remaining_directories.substr(0,found+1);
00131             remaining_directories = remaining_directories.substr(found+1);
00132 
00133             command = "test -d " + directory_root + directory_to_add;
00134             return_value = system(command.c_str());
00135             if (return_value!=0)
00136             {
00137                 // We make only the next folder here
00138                 ABORT_IF_NON0(system, "mkdir -p " + directory_root + directory_to_add);
00139 
00140                 // Put the Chaste signature file into this folder
00141                 ABORT_IF_NON0(system, "touch " + directory_root + directory_to_add + ".chaste_deletable_folder");
00142             }
00143         }
00144     }
00145 
00146     // Wait for master to finish before going on to use the directory.
00147     PetscTools::Barrier("OutputFileHandler::MakeFoldersAndReturnFullPath");
00148 
00149     return directory;
00150 }
00151 
00152 std::string OutputFileHandler::GetOutputDirectoryFullPath() const
00153 {
00154     return mDirectory;
00155 }
00156 
00157 out_stream OutputFileHandler::OpenOutputFile(const std::string& rFileName,
00158                                              std::ios_base::openmode mode) const
00159 {
00160     out_stream p_output_file(new std::ofstream((mDirectory+rFileName).c_str(), mode));
00161     if (!p_output_file->is_open())
00162     {
00163         EXCEPTION("Could not open file \"" + rFileName + "\" in " + mDirectory);
00164     }
00165     return p_output_file;
00166 }
00167 
00168 out_stream OutputFileHandler::OpenOutputFile(const std::string& rFileName,
00169                                              unsigned number,
00170                                              const std::string& rFileFormat,
00171                                              std::ios_base::openmode mode) const
00172 {
00173     std::stringstream string_stream;
00174     string_stream << rFileName << number << rFileFormat;
00175     return OpenOutputFile(string_stream.str(), mode);
00176 }
00177 
00178 void OutputFileHandler::SetArchiveDirectory() const
00179 {
00180     FileFinder dir(GetOutputDirectoryFullPath(), RelativeTo::Absolute);
00181     ArchiveLocationInfo::SetArchiveDirectory(dir);
00182 }
00183 
00184 void OutputFileHandler::AddTrailingSlash(std::string& rDirectory)
00185 {
00186     // Add a trailing slash if not already there
00187     if (rDirectory!="" && !( *(rDirectory.end()-1) == '/'))
00188     {
00189         rDirectory = rDirectory + "/";
00190     }
00191 }
00192 
00193 FileFinder OutputFileHandler::CopyFileTo(const FileFinder& rSourceFile) const
00194 {
00195     if (!rSourceFile.IsFile())
00196     {
00197         EXCEPTION("Can only copy single files:\n" << rSourceFile.GetAbsolutePath() << " is not a file.");
00198     }
00199     if (PetscTools::AmMaster())
00200     {
00201         ABORT_IF_NON0(system, "cp " + rSourceFile.GetAbsolutePath() + " " + GetOutputDirectoryFullPath());
00202     }
00203     PetscTools::Barrier("OutputFileHandler::CopyFileTo");
00204     return FindFile(rSourceFile.GetLeafName());
00205 }
00206 
00207 FileFinder OutputFileHandler::FindFile(std::string leafName) const
00208 {
00209     return FileFinder(GetOutputDirectoryFullPath() + leafName, RelativeTo::Absolute);
00210 }
Generated on Thu Dec 22 13:00:05 2011 for Chaste by  doxygen 1.6.3