ExecutableSupport.cpp

00001 /*
00002 
00003 Copyright (c) 2005-2014, University of Oxford.
00004 All rights reserved.
00005 
00006 University of Oxford means the Chancellor, Masters and Scholars of the
00007 University of Oxford, having an administrative office at Wellington
00008 Square, Oxford OX1 2JD, UK.
00009 
00010 This file is part of Chaste.
00011 
00012 Redistribution and use in source and binary forms, with or without
00013 modification, are permitted provided that the following conditions are met:
00014  * Redistributions of source code must retain the above copyright notice,
00015    this list of conditions and the following disclaimer.
00016  * Redistributions in binary form must reproduce the above copyright notice,
00017    this list of conditions and the following disclaimer in the documentation
00018    and/or other materials provided with the distribution.
00019  * Neither the name of the University of Oxford nor the names of its
00020    contributors may be used to endorse or promote products derived from this
00021    software without specific prior written permission.
00022 
00023 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00024 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00025 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00026 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00027 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00028 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
00029 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00030 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
00032 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00033 
00034 */
00035 
00036 #include "ExecutableSupport.hpp"
00037 
00038 #include "Version.hpp"
00039 
00040 #include <iostream>
00041 #include <sstream>
00042 #ifdef _MSC_VER
00043 #include <windows.h> // For system info on Windows
00044 //GetCurrentTime clashes with a similarly-named API in <windows.h>
00045 #define GetCurrentTime() ChasteBuildInfo::GetCurrentTime()
00046 #define ChasteGetCurrentTime() GetCurrentTime()
00047 #else
00048 #include <sys/utsname.h> // For uname
00049 #define ChasteGetCurrentTime() ChasteBuildInfo::GetCurrentTime()
00050 #endif
00051 #include <hdf5.h>
00052 #include <parmetis.h>
00053 
00054 #include <boost/foreach.hpp>
00055 typedef std::pair<std::string, std::string> StringPair;
00056 
00057 #include "CommandLineArguments.hpp"
00058 #include "Exception.hpp"
00059 #include "PetscTools.hpp"
00060 #include "PetscException.hpp"
00061 #include "ChasteSerialization.hpp"
00062 
00063 #ifdef CHASTE_VTK
00064 #define _BACKWARD_BACKWARD_WARNING_H 1 //Cut out the strstream deprecated warning for now (gcc4.3)
00065 #include <vtkVersion.h>
00066 #endif
00067 
00068 #ifdef CHASTE_CVODE
00069 #include <sundials/sundials_config.h>
00070 #endif
00071 //#include <xsd/cxx/version.hxx>
00072 
00073 // Check whether the version of ParMETIS being used is the one we wanted
00074 #ifdef CHASTE_PARMETIS_REQUIRED
00075 #  if PARMETIS_MAJOR_VERSION != CHASTE_PARMETIS_REQUIRED
00076 #    error "Wrong ParMETIS version found: " #CHASTE_PARMETIS_REQUIRED " requested but " #PARMETIS_MAJOR_VERSION " present"
00077 #  endif
00078 #endif
00079 
00080 FileFinder ExecutableSupport::mOutputDirectory;
00081 
00082 void ExecutableSupport::SetOutputDirectory(const std::string& rOutputDirectory)
00083 {
00084     if (FileFinder::IsAbsolutePath(rOutputDirectory))
00085     {
00086         mOutputDirectory.SetPath(rOutputDirectory, RelativeTo::Absolute);
00087     }
00088     else
00089     {
00090         mOutputDirectory.SetPath(rOutputDirectory, RelativeTo::ChasteTestOutput);
00091     }
00092 }
00093 
00094 void ExecutableSupport::InitializePetsc(int* pArgc, char*** pArgv)
00095 {
00096     // Store the arguments in case other code needs them
00097     CommandLineArguments::Instance()->p_argc = pArgc;
00098     CommandLineArguments::Instance()->p_argv = pArgv;
00099     // Initialise PETSc
00100     PETSCEXCEPT(PetscInitialize(pArgc, pArgv, PETSC_NULL, PETSC_NULL));
00101     // Set default output folder
00102     if (!mOutputDirectory.IsPathSet())
00103     {
00104 #define COVERAGE_IGNORE
00105         //depends on order of calls.  Extract to method?
00106         mOutputDirectory.SetPath("", RelativeTo::ChasteTestOutput);
00107 #undef COVERAGE_IGNORE
00108     }
00109 }
00110 
00111 void ExecutableSupport::ShowCopyright()
00112 {
00113     // Compilation information
00114     std::stringstream provenance_msg;
00115     provenance_msg << "This version of Chaste was compiled on:\n";
00116     provenance_msg << ChasteBuildInfo::GetBuildTime() << " by " << ChasteBuildInfo::GetBuilderUnameInfo() << " (uname)\n";
00117     provenance_msg << "from revision number " << ChasteBuildInfo::GetRevisionNumber() << " with build type " << ChasteBuildInfo::GetBuildInformation() << ".\n\n";
00118 
00119     // Only show one copy of copyright/header
00120     if (PetscTools::AmMaster())
00121     {
00122         std::cout << ChasteBuildInfo::GetLicenceText() << std::endl;
00123 
00124         // Write provenance information to stdout
00125         std::cout << provenance_msg.str() << std::flush;
00126     }
00127 }
00128 
00129 void ExecutableSupport::ShowParallelLaunching()
00130 {
00131     if (PetscTools::IsParallel())
00132     {
00133         // Information to show that Chaste is being run in parallel
00134         PetscTools::BeginRoundRobin();
00135         std::cout << "Chaste launched on process " << PetscTools::GetMyRank()
00136             << " of " << PetscTools::GetNumProcs() << "." << std::endl << std::flush;
00137         PetscTools::EndRoundRobin();
00138     }
00139 }
00140 
00141 void ExecutableSupport::WriteMachineInfoFile(std::string fileBaseName)
00142 {
00143     if (!mOutputDirectory.IsPathSet())
00144     {
00145 #define COVERAGE_IGNORE
00146         //depends on order of calls.  Extract to method?
00147         mOutputDirectory.SetPath("", RelativeTo::ChasteTestOutput);
00148 #undef COVERAGE_IGNORE
00149     }
00150     OutputFileHandler out_file_handler(mOutputDirectory, false);
00151     std::stringstream file_name;
00152     file_name << fileBaseName << "_" << PetscTools::GetMyRank() << ".txt";
00153     out_stream out_file = out_file_handler.OpenOutputFile(file_name.str());
00154     *out_file << "Process " << PetscTools::GetMyRank() << " of "
00155         << PetscTools::GetNumProcs() << "." << std::endl << std::flush;
00156 
00157 #ifdef _MSC_VER
00158     //use native windows equivalent of system info. from uname and /proc/cpuinfo
00159 
00160     //operating system and machine name
00161     *out_file << "uname sysname  = " << "Microsoft Windows" << std::endl;
00162     #define INFO_BUFFER_SIZE 32767
00163     TCHAR info_buffer[INFO_BUFFER_SIZE];
00164     DWORD buffer_char_count = INFO_BUFFER_SIZE;
00165     if(!GetComputerName(info_buffer, &buffer_char_count))
00166         *out_file << "uname nodename = " << "Windows machine name is unknown" << std::endl;
00167     else
00168         *out_file << "uname nodename = " << info_buffer << std::endl;
00169     //more detailed operating system version information
00170     OSVERSIONINFOEX os_info;
00171     ZeroMemory(&os_info, sizeof(OSVERSIONINFO));
00172     os_info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
00173     //copy os version info into the structure
00174     GetVersionEx((OSVERSIONINFO*) &os_info);
00175     //Pivot around Windows Vista (dwMajorVersion >= 6)
00176     //See http://msdn.microsoft.com/en-us/library/ms724834%28v=vs.85%29.aspx for details
00177     if(os_info.dwMajorVersion < 6)
00178     { //earlier than Windows Vista
00179         *out_file << "uname release  = " << "Microsoft Windows Server 2003 R2 (or earlier)" << std::endl;
00180     }
00181     else {
00182         //reverse chronological order (simply add newer OS version to the top)
00183         if(os_info.dwMajorVersion > 6)
00184         {
00185             *out_file << "uname release  = " << "Microsoft Windows (Later than Microsoft Windows 8)" << std::endl;
00186         }
00187         else  //os_info.dwMajorVersion == 6
00188         {
00189             if(os_info.dwMinorVersion == 2)
00190             {
00191                 if(os_info.wProductType == VER_NT_WORKSTATION)
00192                     *out_file << "uname release  = " << "Microsoft Windows 8" << std::endl;
00193                 else
00194                     *out_file << "uname release  = " << "Microsoft Windows Server 2012" << std::endl;
00195             }
00196             else if(os_info.dwMinorVersion == 1)
00197             {
00198                 if(os_info.wProductType == VER_NT_WORKSTATION)
00199                     *out_file << "uname release  = " << "Microsoft Windows 7" << std::endl;
00200                 else
00201                     *out_file << "uname release  = " << "Microsoft Windows Server 2008 R2" << std::endl;
00202             }
00203             else if(os_info.dwMinorVersion == 0)
00204             {
00205                 if(os_info.wProductType == VER_NT_WORKSTATION)
00206                     *out_file << "uname release  = " << "Microsoft Windows Server 2008" << std::endl;
00207                 else
00208                     *out_file << "uname release  = " << "Microsoft Windows Vista" << std::endl;
00209             }
00210         }
00211     }
00212     *out_file << "uname version  = " << os_info.dwMajorVersion << "." << os_info.dwMinorVersion << std::endl;
00213 
00214     //hardware information
00215     // See http://msdn.microsoft.com/en-us/library/ms724958%28v=vs.85%29.aspx for details of the SYSTEM_INFO structure
00216     SYSTEM_INFO sys_info;
00217     GetSystemInfo(&sys_info);
00218     switch (sys_info.wProcessorArchitecture)
00219     {
00220     case PROCESSOR_ARCHITECTURE_AMD64:
00221         *out_file << "uname machine  = " << "x64 (AMD or Intel)" << std::endl;
00222         break;
00223     case PROCESSOR_ARCHITECTURE_ARM:
00224         *out_file << "uname machine  = " << "ARM" << std::endl;
00225         break;
00226     case PROCESSOR_ARCHITECTURE_IA64:
00227         *out_file << "uname machine  = " << "Intel Itanium-based" << std::endl;
00228         break;
00229     case PROCESSOR_ARCHITECTURE_INTEL:
00230         *out_file << "uname machine  = " << "x86" << std::endl;
00231         break;
00232     case PROCESSOR_ARCHITECTURE_UNKNOWN:
00233         *out_file << "uname machine  = " << "Unknown Architecture" << std::endl;
00234         break;
00235     default:
00236         *out_file << "uname machine  = " << "Other Architecture. Code = " << sys_info.wProcessorArchitecture << std::endl;
00237         break;
00238     }
00239 
00240     *out_file << "\nInformation on number and type of processors:" << std::endl;
00241     *out_file << sys_info.dwNumberOfProcessors;
00242     *out_file << "\nInformation on processor caches, in the same order as above:" << std::endl;
00243     *out_file << "Unknown" << std::endl; 
00244 
00245     //get physical memory
00246     MEMORYSTATUSEX mem_status;
00247     mem_status.dwLength = sizeof (mem_status);
00248     GlobalMemoryStatusEx (&mem_status);
00249     *out_file << "\nInformation on system memory:" << std::endl;
00250     *out_file << mem_status.ullTotalPhys/1024 << " kB" << std::endl;
00251 #else
00252     struct utsname uts_info;
00253     uname(&uts_info);
00254 
00255     *out_file << "uname sysname  = " << uts_info.sysname << std::endl << std::flush;
00256     *out_file << "uname nodename = " << uts_info.nodename << std::endl << std::flush;
00257     *out_file << "uname release  = " << uts_info.release << std::endl << std::flush;
00258     *out_file << "uname version  = " << uts_info.version << std::endl << std::flush;
00259     *out_file << "uname machine  = " << uts_info.machine << std::endl << std::flush;
00260     char buffer[100];
00261     FILE* system_info;
00262 
00263 #ifdef __APPLE__
00264     *out_file << "\nInformation on number and type processors, and cache and memory sizes (in bytes)\n";
00265     system_info = popen("sysctl hw.ncpu hw.physicalcpu machdep.cpu.brand_string hw.l1icachesize hw.l1dcachesize hw.l2cachesize hw.l3cachesize hw.memsize", "r");
00266     while ( fgets(buffer, 100, system_info) != NULL )
00267     {
00268         *out_file << buffer;
00269     }
00270     fclose(system_info);
00271 #else
00272     //GNU
00273     *out_file << "\nInformation on number and type of processors:\n";
00274     system_info = popen("grep ^model.name /proc/cpuinfo", "r");
00275     while ( fgets(buffer, 100, system_info) != NULL )
00276     {
00277         *out_file << buffer;
00278     }
00279     fclose(system_info);
00280 
00281     *out_file << "\nInformation on processor caches, in the same order as above:\n";
00282     system_info = popen("grep ^cache.size /proc/cpuinfo", "r");
00283     while ( fgets(buffer, 100, system_info) != NULL )
00284     {
00285         *out_file << buffer;
00286     }
00287     fclose(system_info);
00288 
00289     *out_file << "\nInformation on system memory:\n";
00290     system_info = popen("grep ^MemTotal /proc/meminfo", "r");
00291     while ( fgets(buffer, 100, system_info) != NULL )
00292     {
00293         *out_file << buffer;
00294     }
00295     fclose(system_info);
00296 #endif //end of __APPLE__ not defined
00297 #endif //end of _MSC_VER not defined
00298 
00299     out_file->close();
00300 }
00301 
00302 void ExecutableSupport::WriteProvenanceInfoFile()
00303 {
00304     if (!mOutputDirectory.IsPathSet())
00305     {
00306 #define COVERAGE_IGNORE
00307         //depends on order of calls.  Extract to method?
00308         mOutputDirectory.SetPath("", RelativeTo::ChasteTestOutput);
00309 #undef COVERAGE_IGNORE
00310     }
00311     OutputFileHandler out_file_handler(mOutputDirectory, false);
00312     out_stream out_file = out_file_handler.OpenOutputFile("provenance_info_", PetscTools::GetMyRank(), ".txt");
00313 
00314     // Compilation information
00315     std::stringstream provenance_msg;
00316     provenance_msg << "This version of Chaste was compiled on:\n";
00317     provenance_msg << ChasteBuildInfo::GetBuildTime() << " by " << ChasteBuildInfo::GetBuilderUnameInfo() << " (uname)\n";
00318     provenance_msg << "from revision number " << ChasteBuildInfo::GetRevisionNumber() << " with build type " << ChasteBuildInfo::GetBuildInformation() << ".\n\n";
00319     *out_file << provenance_msg.str();
00320 
00321     std::string output;
00322     GetBuildInfo(output);
00323     *out_file << output;
00324 
00325     out_file->close();
00326 }
00327 
00328 void ExecutableSupport::GetBuildInfo(std::string& rInfo)
00329 {
00330     std::stringstream output;
00331     output << "<ChasteBuildInfo>\n";
00332 
00333     output << "\t<ProvenanceInfo>\n";
00334     output << "\t\t<VersionString>"<< ChasteBuildInfo::GetVersionString() << "</VersionString> <!-- build specific -->\n";
00335     output << "\t\t<IsWorkingCopyModified>"<< ChasteBuildInfo::IsWorkingCopyModified() << "</IsWorkingCopyModified>\n";
00336     output << "\t\t<BuildInformation>"<< ChasteBuildInfo::GetBuildInformation() << "</BuildInformation>\n";
00337     output << "\t\t<BuildTime>"<< ChasteBuildInfo::GetBuildTime() << "</BuildTime>\n";
00338     output << "\t\t<CurrentTime>"<< ChasteGetCurrentTime() << "</CurrentTime>\n";
00339     output << "\t\t<BuilderUnameInfo>"<< ChasteBuildInfo::GetBuilderUnameInfo() << "</BuilderUnameInfo>\n";
00340     output << "\t\t<Projects>\n";
00341     BOOST_FOREACH(const StringPair& r_project_version, ChasteBuildInfo::rGetProjectVersions())
00342     {
00343 #define COVERAGE_IGNORE
00344         // No projects are checked out for continuous builds normally!
00345         output<< "\t\t\t<Name>" << r_project_version.first << "</Name><Version>"
00346                  << r_project_version.second << "</Version>\n";
00347 #undef COVERAGE_IGNORE
00348     }
00349     output << "\t\t</Projects>\n";
00350     output << "\t</ProvenanceInfo>\n";
00351 
00352     output << "\t<Compiler>\n";
00353     output << "\t\t<NameAndVersion>" << ChasteBuildInfo::GetCompilerType() << ", version " << ChasteBuildInfo::GetCompilerVersion() << "</NameAndVersion>\n" ;
00354     output << "\t\t<Flags>" << ChasteBuildInfo::GetCompilerFlags() << "</Flags>\n" ;
00355     output << "\t</Compiler>\n";
00356 
00357     output << "\t<Libraries>\n";
00358 
00359     output << "\t\t<CompiledIn>\n";
00360     output << "\t\t\t<PETSc>" << PETSC_VERSION_MAJOR << "." << PETSC_VERSION_MINOR << "." << PETSC_VERSION_SUBMINOR << "</PETSc>\n";
00361     output << "\t\t\t<Boost>" << BOOST_VERSION  / 100000 << "." << BOOST_VERSION / 100 % 1000 << "." << BOOST_VERSION % 100 << "</Boost>\n";
00362     output << "\t\t\t<HDF5>" << H5_VERS_MAJOR <<  "." << H5_VERS_MINOR << "." << H5_VERS_RELEASE << "</HDF5>\n";
00363     output << "\t\t\t<Parmetis>" << PARMETIS_MAJOR_VERSION << "." << PARMETIS_MINOR_VERSION;
00364 #ifdef PARMETIS_SUBMINOR_VERSION // they only added this in v4.? !!
00365     output << "." << PARMETIS_SUBMINOR_VERSION;
00366 #endif
00367     output << "</Parmetis>" << std::endl;
00368     output << "\t\t</CompiledIn>\n";
00369 
00370     output << "\t\t<Binaries>\n";
00371     output << "\t\t\t<XSD>" <<  ChasteBuildInfo::GetXsdVersion() << "</XSD>\n";
00372     output << "\t\t</Binaries>\n";
00373 
00374     output << "\t\t<Optional>\n";
00375 #ifdef CHASTE_VTK
00376     output << "\t\t\t<VTK>" << VTK_MAJOR_VERSION << "." << VTK_MINOR_VERSION << "</VTK>\n";
00377 #else
00378     output << "\t\t\t<VTK>no</VTK>\n";
00379 #endif
00380 
00381 #ifdef CHASTE_CVODE
00382     output << "\t\t\t<SUNDIALS>" << SUNDIALS_PACKAGE_VERSION << "</SUNDIALS> <!-- includes Cvode of a different version number --> \n";
00383 #else
00384     output << "\t\t\t<SUNDIALS>no</SUNDIALS>\n";
00385 #endif
00386     output << "\t\t</Optional>\n";
00387 
00388     output << "\t</Libraries>\n";
00389 
00390     output << "</ChasteBuildInfo>" << std::endl;
00391     rInfo = output.str();
00392 }
00393 
00394 void ExecutableSupport::StandardStartup(int* pArgc, char*** pArgv)
00395 {
00396     InitializePetsc(pArgc, pArgv);
00397     ShowCopyright();
00398     ShowParallelLaunching();
00399 }
00400 
00401 void ExecutableSupport::PrintError(const std::string& rMessage, bool masterOnly)
00402 {
00403     if (!masterOnly || PetscTools::AmMaster())
00404     {
00405         // Write the error message to stderr
00406         std::cerr << rMessage << std::endl;
00407     }
00408 
00409     // Write the error message to file
00410     if (!mOutputDirectory.IsPathSet())
00411     {
00412 #define COVERAGE_IGNORE
00413         //depends on order of calls.  Extract to method?
00414         mOutputDirectory.SetPath("", RelativeTo::ChasteTestOutput);
00415 #undef COVERAGE_IGNORE
00416     }
00417     OutputFileHandler out_file_handler(mOutputDirectory, false);
00418     out_stream out_file = out_file_handler.OpenOutputFile("chaste_errors_", PetscTools::GetMyRank(), ".txt", std::ios::out | std::ios::app);
00419     *out_file << rMessage << std::endl;
00420     out_file->close();
00421 }
00422 
00423 void ExecutableSupport::Print(const std::string& rMessage)
00424 {
00425     if (PetscTools::AmMaster())
00426     {
00427         // Write the error message to stdout
00428         std::cout << rMessage << std::endl << std::flush;
00429     }
00430 }
00431 
00432 void ExecutableSupport::FinalizePetsc()
00433 {
00434     // Causes memory failure (and seg fault) in PETSc 3.2 with MPICH-1
00435     PetscFinalize();
00436 }

Generated by  doxygen 1.6.2