ExecutableSupport.cpp

00001 /*
00002 
00003 Copyright (c) 2005-2015, 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 "PetscSetupUtils.hpp"
00061 #include "PetscException.hpp"
00062 #include "ChasteSerialization.hpp"
00063 
00064 #ifdef CHASTE_VTK
00065 #define _BACKWARD_BACKWARD_WARNING_H 1 //Cut out the strstream deprecated warning for now (gcc4.3)
00066 #include <vtkVersion.h>
00067 #endif
00068 
00069 #ifdef CHASTE_CVODE
00070 #include <sundials/sundials_config.h>
00071 #endif
00072 
00073 // Note: the following are not a requirement for cell-based Chaste so may not be present!
00074 //#include <xsd/cxx/version.hxx>
00075 #ifdef CHASTE_XERCES
00076 #include <xercesc/util/XercesVersion.hpp>
00077 #endif
00078 
00079 // Check whether the version of ParMETIS being used is the one we wanted
00080 #ifdef CHASTE_PARMETIS_REQUIRED
00081 #  if PARMETIS_MAJOR_VERSION != CHASTE_PARMETIS_REQUIRED
00082 #    error "Wrong ParMETIS version found: " #CHASTE_PARMETIS_REQUIRED " requested but " #PARMETIS_MAJOR_VERSION " present"
00083 #  endif
00084 #endif
00085 
00086 FileFinder ExecutableSupport::mOutputDirectory;
00087 
00088 void ExecutableSupport::SetOutputDirectory(const std::string& rOutputDirectory)
00089 {
00090     if (FileFinder::IsAbsolutePath(rOutputDirectory))
00091     {
00092         mOutputDirectory.SetPath(rOutputDirectory, RelativeTo::Absolute);
00093     }
00094     else
00095     {
00096         mOutputDirectory.SetPath(rOutputDirectory, RelativeTo::ChasteTestOutput);
00097     }
00098 }
00099 
00100 void ExecutableSupport::InitializePetsc(int* pArgc, char*** pArgv)
00101 {
00102     // Store the arguments in case other code needs them
00103     CommandLineArguments::Instance()->p_argc = pArgc;
00104     CommandLineArguments::Instance()->p_argv = pArgv;
00105     // Initialise PETSc
00106     PETSCEXCEPT(PetscInitialize(pArgc, pArgv, PETSC_NULL, PETSC_NULL));
00107     // Set default output folder
00108     if (!mOutputDirectory.IsPathSet())
00109     {
00110 #define COVERAGE_IGNORE
00111         //depends on order of calls.  Extract to method?
00112         mOutputDirectory.SetPath("", RelativeTo::ChasteTestOutput);
00113 #undef COVERAGE_IGNORE
00114     }
00115 }
00116 
00117 void ExecutableSupport::ShowCopyright()
00118 {
00119     // Compilation information
00120     std::stringstream provenance_msg;
00121     provenance_msg << "This version of Chaste was compiled on:\n";
00122     provenance_msg << ChasteBuildInfo::GetBuildTime() << " by " << ChasteBuildInfo::GetBuilderUnameInfo() << " (uname)\n";
00123     provenance_msg << "from revision number " << ChasteBuildInfo::GetRevisionNumber() << " with build type " << ChasteBuildInfo::GetBuildInformation() << ".\n\n";
00124 
00125     // Only show one copy of copyright/header
00126     if (PetscTools::AmMaster())
00127     {
00128         std::cout << ChasteBuildInfo::GetLicenceText() << std::endl;
00129 
00130         // Write provenance information to stdout
00131         std::cout << provenance_msg.str() << std::flush;
00132     }
00133 }
00134 
00135 void ExecutableSupport::ShowParallelLaunching()
00136 {
00137     if (PetscTools::IsParallel())
00138     {
00139         // Information to show that Chaste is being run in parallel
00140         PetscTools::BeginRoundRobin();
00141         std::cout << "Chaste launched on process " << PetscTools::GetMyRank()
00142             << " of " << PetscTools::GetNumProcs() << "." << std::endl << std::flush;
00143         PetscTools::EndRoundRobin();
00144     }
00145 }
00146 
00147 void ExecutableSupport::WriteMachineInfoFile(std::string fileBaseName)
00148 {
00149     if (!mOutputDirectory.IsPathSet())
00150     {
00151 #define COVERAGE_IGNORE
00152         //depends on order of calls.  Extract to method?
00153         mOutputDirectory.SetPath("", RelativeTo::ChasteTestOutput);
00154 #undef COVERAGE_IGNORE
00155     }
00156     OutputFileHandler out_file_handler(mOutputDirectory, false);
00157     std::stringstream file_name;
00158     file_name << fileBaseName << "_" << PetscTools::GetMyRank() << ".txt";
00159     out_stream out_file = out_file_handler.OpenOutputFile(file_name.str());
00160     *out_file << "Process " << PetscTools::GetMyRank() << " of "
00161         << PetscTools::GetNumProcs() << "." << std::endl << std::flush;
00162 
00163 #ifdef _MSC_VER
00164     //use native windows equivalent of system info. from uname and /proc/cpuinfo
00165 
00166     //operating system and machine name
00167     *out_file << "uname sysname  = " << "Microsoft Windows" << std::endl;
00168     #define INFO_BUFFER_SIZE 32767
00169     TCHAR info_buffer[INFO_BUFFER_SIZE];
00170     DWORD buffer_char_count = INFO_BUFFER_SIZE;
00171     if(!GetComputerName(info_buffer, &buffer_char_count))
00172         *out_file << "uname nodename = " << "Windows machine name is unknown" << std::endl;
00173     else
00174         *out_file << "uname nodename = " << info_buffer << std::endl;
00175     //more detailed operating system version information
00176     OSVERSIONINFOEX os_info;
00177     ZeroMemory(&os_info, sizeof(OSVERSIONINFO));
00178     os_info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
00179     //copy os version info into the structure
00180     GetVersionEx((OSVERSIONINFO*) &os_info);
00181     //Pivot around Windows Vista (dwMajorVersion >= 6)
00182     //See http://msdn.microsoft.com/en-us/library/ms724834%28v=vs.85%29.aspx for details
00183     if(os_info.dwMajorVersion < 6)
00184     { //earlier than Windows Vista
00185         *out_file << "uname release  = " << "Microsoft Windows Server 2003 R2 (or earlier)" << std::endl;
00186     }
00187     else {
00188         //reverse chronological order (simply add newer OS version to the top)
00189         if(os_info.dwMajorVersion > 6)
00190         {
00191             *out_file << "uname release  = " << "Microsoft Windows (Later than Microsoft Windows 8)" << std::endl;
00192         }
00193         else  //os_info.dwMajorVersion == 6
00194         {
00195             if(os_info.dwMinorVersion == 2)
00196             {
00197                 if(os_info.wProductType == VER_NT_WORKSTATION)
00198                     *out_file << "uname release  = " << "Microsoft Windows 8" << std::endl;
00199                 else
00200                     *out_file << "uname release  = " << "Microsoft Windows Server 2012" << std::endl;
00201             }
00202             else if(os_info.dwMinorVersion == 1)
00203             {
00204                 if(os_info.wProductType == VER_NT_WORKSTATION)
00205                     *out_file << "uname release  = " << "Microsoft Windows 7" << std::endl;
00206                 else
00207                     *out_file << "uname release  = " << "Microsoft Windows Server 2008 R2" << std::endl;
00208             }
00209             else if(os_info.dwMinorVersion == 0)
00210             {
00211                 if(os_info.wProductType == VER_NT_WORKSTATION)
00212                     *out_file << "uname release  = " << "Microsoft Windows Server 2008" << std::endl;
00213                 else
00214                     *out_file << "uname release  = " << "Microsoft Windows Vista" << std::endl;
00215             }
00216         }
00217     }
00218     *out_file << "uname version  = " << os_info.dwMajorVersion << "." << os_info.dwMinorVersion << std::endl;
00219 
00220     //hardware information
00221     // See http://msdn.microsoft.com/en-us/library/ms724958%28v=vs.85%29.aspx for details of the SYSTEM_INFO structure
00222     SYSTEM_INFO sys_info;
00223     GetSystemInfo(&sys_info);
00224     switch (sys_info.wProcessorArchitecture)
00225     {
00226     case PROCESSOR_ARCHITECTURE_AMD64:
00227         *out_file << "uname machine  = " << "x64 (AMD or Intel)" << std::endl;
00228         break;
00229     case PROCESSOR_ARCHITECTURE_ARM:
00230         *out_file << "uname machine  = " << "ARM" << std::endl;
00231         break;
00232     case PROCESSOR_ARCHITECTURE_IA64:
00233         *out_file << "uname machine  = " << "Intel Itanium-based" << std::endl;
00234         break;
00235     case PROCESSOR_ARCHITECTURE_INTEL:
00236         *out_file << "uname machine  = " << "x86" << std::endl;
00237         break;
00238     case PROCESSOR_ARCHITECTURE_UNKNOWN:
00239         *out_file << "uname machine  = " << "Unknown Architecture" << std::endl;
00240         break;
00241     default:
00242         *out_file << "uname machine  = " << "Other Architecture. Code = " << sys_info.wProcessorArchitecture << std::endl;
00243         break;
00244     }
00245 
00246     *out_file << "\nInformation on number and type of processors:" << std::endl;
00247     *out_file << sys_info.dwNumberOfProcessors;
00248     *out_file << "\nInformation on processor caches, in the same order as above:" << std::endl;
00249     *out_file << "Unknown" << std::endl; 
00250 
00251     //get physical memory
00252     MEMORYSTATUSEX mem_status;
00253     mem_status.dwLength = sizeof (mem_status);
00254     GlobalMemoryStatusEx (&mem_status);
00255     *out_file << "\nInformation on system memory:" << std::endl;
00256     *out_file << mem_status.ullTotalPhys/1024 << " kB" << std::endl;
00257 #else
00258     struct utsname uts_info;
00259     uname(&uts_info);
00260 
00261     *out_file << "uname sysname  = " << uts_info.sysname << std::endl << std::flush;
00262     *out_file << "uname nodename = " << uts_info.nodename << std::endl << std::flush;
00263     *out_file << "uname release  = " << uts_info.release << std::endl << std::flush;
00264     *out_file << "uname version  = " << uts_info.version << std::endl << std::flush;
00265     *out_file << "uname machine  = " << uts_info.machine << std::endl << std::flush;
00266     char buffer[100];
00267     FILE* system_info;
00268 
00269 #ifdef __APPLE__
00270     *out_file << "\nInformation on number and type processors, and cache and memory sizes (in bytes)\n";
00271     system_info = popen("sysctl hw.ncpu hw.physicalcpu machdep.cpu.brand_string hw.l1icachesize hw.l1dcachesize hw.l2cachesize hw.l3cachesize hw.memsize", "r");
00272     while ( fgets(buffer, 100, system_info) != NULL )
00273     {
00274         *out_file << buffer;
00275     }
00276     fclose(system_info);
00277 #else
00278     //GNU
00279     *out_file << "\nInformation on number and type of processors:\n";
00280     system_info = popen("grep ^model.name /proc/cpuinfo", "r");
00281     while ( fgets(buffer, 100, system_info) != NULL )
00282     {
00283         *out_file << buffer;
00284     }
00285     fclose(system_info);
00286 
00287     *out_file << "\nInformation on processor caches, in the same order as above:\n";
00288     system_info = popen("grep ^cache.size /proc/cpuinfo", "r");
00289     while ( fgets(buffer, 100, system_info) != NULL )
00290     {
00291         *out_file << buffer;
00292     }
00293     fclose(system_info);
00294 
00295     *out_file << "\nInformation on system memory:\n";
00296     system_info = popen("grep ^MemTotal /proc/meminfo", "r");
00297     while ( fgets(buffer, 100, system_info) != NULL )
00298     {
00299         *out_file << buffer;
00300     }
00301     fclose(system_info);
00302 #endif //end of __APPLE__ not defined
00303 #endif //end of _MSC_VER not defined
00304 
00305     out_file->close();
00306 }
00307 
00308 void ExecutableSupport::WriteProvenanceInfoFile()
00309 {
00310     if (!mOutputDirectory.IsPathSet())
00311     {
00312 #define COVERAGE_IGNORE
00313         //depends on order of calls.  Extract to method?
00314         mOutputDirectory.SetPath("", RelativeTo::ChasteTestOutput);
00315 #undef COVERAGE_IGNORE
00316     }
00317     OutputFileHandler out_file_handler(mOutputDirectory, false);
00318     out_stream out_file = out_file_handler.OpenOutputFile("provenance_info_", PetscTools::GetMyRank(), ".txt");
00319 
00320     // Compilation information
00321     std::stringstream provenance_msg;
00322     provenance_msg << "This version of Chaste was compiled on:\n";
00323     provenance_msg << ChasteBuildInfo::GetBuildTime() << " by " << ChasteBuildInfo::GetBuilderUnameInfo() << " (uname)\n";
00324     provenance_msg << "from revision number " << ChasteBuildInfo::GetRevisionNumber() << " with build type " << ChasteBuildInfo::GetBuildInformation() << ".\n\n";
00325     *out_file << provenance_msg.str();
00326 
00327     std::string output;
00328     GetBuildInfo(output);
00329     *out_file << output;
00330 
00331     out_file->close();
00332 }
00333 
00334 void ExecutableSupport::GetBuildInfo(std::string& rInfo)
00335 {
00336     std::stringstream output;
00337     output << "<ChasteBuildInfo>\n";
00338 
00339     output << "\t<ProvenanceInfo>\n";
00340     output << "\t\t<VersionString>"<< ChasteBuildInfo::GetVersionString() << "</VersionString> <!-- build specific -->\n";
00341     output << "\t\t<IsWorkingCopyModified>"<< ChasteBuildInfo::IsWorkingCopyModified() << "</IsWorkingCopyModified>\n";
00342     output << "\t\t<BuildInformation>"<< ChasteBuildInfo::GetBuildInformation() << "</BuildInformation>\n";
00343     output << "\t\t<BuildTime>"<< ChasteBuildInfo::GetBuildTime() << "</BuildTime>\n";
00344     output << "\t\t<CurrentTime>"<< ChasteGetCurrentTime() << "</CurrentTime>\n";
00345     output << "\t\t<BuilderUnameInfo>"<< ChasteBuildInfo::GetBuilderUnameInfo() << "</BuilderUnameInfo>\n";
00346     output << "\t\t<Projects>\n";
00347     BOOST_FOREACH(const StringPair& r_project_version, ChasteBuildInfo::rGetProjectVersions())
00348     {
00349 #define COVERAGE_IGNORE
00350         // No projects are checked out for continuous builds normally!
00351         output<< "\t\t\t<Name>" << r_project_version.first << "</Name><Version>"
00352                  << r_project_version.second << "</Version>\n";
00353 #undef COVERAGE_IGNORE
00354     }
00355     output << "\t\t</Projects>\n";
00356     output << "\t</ProvenanceInfo>\n";
00357 
00358     output << "\t<Compiler>\n";
00359     output << "\t\t<NameAndVersion>" << ChasteBuildInfo::GetCompilerType() << ", version " << ChasteBuildInfo::GetCompilerVersion() << "</NameAndVersion>\n" ;
00360     output << "\t\t<Flags>" << ChasteBuildInfo::GetCompilerFlags() << "</Flags>\n" ;
00361     output << "\t</Compiler>\n";
00362 
00363     output << "\t<Libraries>\n";
00364 
00365     output << "\t\t<CompiledIn>\n";
00366     output << "\t\t\t<PETSc>" << PETSC_VERSION_MAJOR << "." << PETSC_VERSION_MINOR << "." << PETSC_VERSION_SUBMINOR << "</PETSc>\n";
00367     output << "\t\t\t<Boost>" << BOOST_VERSION  / 100000 << "." << BOOST_VERSION / 100 % 1000 << "." << BOOST_VERSION % 100 << "</Boost>\n";
00368     output << "\t\t\t<HDF5>" << H5_VERS_MAJOR <<  "." << H5_VERS_MINOR << "." << H5_VERS_RELEASE << "</HDF5>\n";
00369     output << "\t\t\t<Parmetis>" << PARMETIS_MAJOR_VERSION << "." << PARMETIS_MINOR_VERSION;
00370 #ifdef PARMETIS_SUBMINOR_VERSION // they only added this in v4.? !!
00371     output << "." << PARMETIS_SUBMINOR_VERSION;
00372 #endif
00373     output << "</Parmetis>" << std::endl;
00374     output << "\t\t</CompiledIn>\n";
00375 
00376     output << "\t\t<Binaries>\n";
00377     output << "\t\t\t<XSD>" <<  ChasteBuildInfo::GetXsdVersion() << "</XSD>\n";
00378     output << "\t\t</Binaries>\n";
00379 
00380     output << "\t\t<Optional>\n";
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 #ifdef CHASTE_VTK
00387     output << "\t\t\t<VTK>" << VTK_MAJOR_VERSION << "." << VTK_MINOR_VERSION << "</VTK>\n";
00388 #else
00389     output << "\t\t\t<VTK>no</VTK>\n";
00390 #endif
00391 #ifdef CHASTE_XERCES
00392     output << "\t\t\t<Xerces>" << XERCES_FULLVERSIONDOT << "</Xerces>\n"; // Note: not a requirement for cell-based so may not be present!
00393 #else
00394     output << "\t\t\t<Xerces>no</Xerces>\n";
00395 #endif
00396     output << "\t\t</Optional>\n";
00397 
00398     output << "\t</Libraries>\n";
00399 
00400     output << "</ChasteBuildInfo>" << std::endl;
00401     rInfo = output.str();
00402 }
00403 
00404 void ExecutableSupport::StandardStartup(int* pArgc, char*** pArgv)
00405 {
00406     InitializePetsc(pArgc, pArgv);
00407     ShowCopyright();
00408     ShowParallelLaunching();
00409 }
00410 
00411 void ExecutableSupport::PrintError(const std::string& rMessage, bool masterOnly)
00412 {
00413     if (!masterOnly || PetscTools::AmMaster())
00414     {
00415         // Write the error message to stderr
00416         std::cerr << rMessage << std::endl;
00417     }
00418 
00419     // Write the error message to file
00420     if (!mOutputDirectory.IsPathSet())
00421     {
00422 #define COVERAGE_IGNORE
00423         //depends on order of calls.  Extract to method?
00424         mOutputDirectory.SetPath("", RelativeTo::ChasteTestOutput);
00425 #undef COVERAGE_IGNORE
00426     }
00427     OutputFileHandler out_file_handler(mOutputDirectory, false);
00428     out_stream out_file = out_file_handler.OpenOutputFile("chaste_errors_", PetscTools::GetMyRank(), ".txt", std::ios::out | std::ios::app);
00429     *out_file << rMessage << std::endl;
00430     out_file->close();
00431 }
00432 
00433 void ExecutableSupport::Print(const std::string& rMessage)
00434 {
00435     if (PetscTools::AmMaster())
00436     {
00437         // Write the error message to stdout
00438         std::cout << rMessage << std::endl << std::flush;
00439     }
00440 }
00441 
00442 void ExecutableSupport::FinalizePetsc()
00443 {
00444     // Causes memory failure (and seg fault) in PETSc 3.2 with MPICH-1
00445     PetscSetupUtils::CommonFinalize();
00446 }

Generated by  doxygen 1.6.2