LCOV - code coverage report
Current view: top level - ugbase/common - log.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 64.9 % 97 63
Test Date: 2025-09-21 23:31:46 Functions: 64.7 % 17 11

            Line data    Source code
       1              : /*
       2              :  * Copyright (c) 2010-2015:  G-CSC, Goethe University Frankfurt
       3              :  * Authors: Andreas Vogel, Sebastian Reiter
       4              :  * 
       5              :  * This file is part of UG4.
       6              :  * 
       7              :  * UG4 is free software: you can redistribute it and/or modify it under the
       8              :  * terms of the GNU Lesser General Public License version 3 (as published by the
       9              :  * Free Software Foundation) with the following additional attribution
      10              :  * requirements (according to LGPL/GPL v3 §7):
      11              :  * 
      12              :  * (1) The following notice must be displayed in the Appropriate Legal Notices
      13              :  * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
      14              :  * 
      15              :  * (2) The following notice must be displayed at a prominent place in the
      16              :  * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
      17              :  * 
      18              :  * (3) The following bibliography is recommended for citation and must be
      19              :  * preserved in all covered files:
      20              :  * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
      21              :  *   parallel geometric multigrid solver on hierarchically distributed grids.
      22              :  *   Computing and visualization in science 16, 4 (2013), 151-164"
      23              :  * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
      24              :  *   flexible software system for simulating pde based models on high performance
      25              :  *   computers. Computing and visualization in science 16, 4 (2013), 165-179"
      26              :  * 
      27              :  * This program is distributed in the hope that it will be useful,
      28              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      29              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      30              :  * GNU Lesser General Public License for more details.
      31              :  */
      32              : 
      33              : #include <iostream>
      34              : #include "common/log.h"
      35              : #include "common/profiler/profiler.h"
      36              : #include <cassert>
      37              : 
      38              : //      in order to support parallel logs, we're including pcl.h
      39              : #ifdef UG_PARALLEL
      40              :         #include "pcl/pcl_base.h"
      41              : #endif
      42              : 
      43              : 
      44              : using namespace std;
      45              : 
      46              : namespace ug{
      47              : 
      48              : // predefined standard DebugIDs. todo: move some of those in the appropriate modules,
      49              : // syntax for subgroups ?
      50              : DebugID MAIN("MAIN"),
      51              :                 APP("APP"),
      52              :                 LIB_GRID("LIB_GRID"),
      53              :                 LIB_GRID_REFINER("LIB_GRID_REFINER"),
      54              :                 LIB_DISC("LIB_DISC"),
      55              :                 LIB_DISC_ASSEMBLE("LIB_DISC_ASSEMBLE"),
      56              :                 LIB_DISC_D3F("LIB_DISC_D3F"),
      57              :                 LIB_DISC_MULTIGRID("LIB_DISC_MULTIGRID"),
      58              :                 LIB_DISC_NEWTON("LIB_DISC_NEWTON"),
      59              :                 LIB_DISC_LINKER("LIB_DISC_LINKER"),
      60              :                 LIB_DISC_TRANSFER("LIB_DISC_TRANSFER"),
      61              :                 LIB_DISC_DISCRETE_FUNCTION("LIB_DISC_DISCRETE_FUNCTION"),
      62              :                 LIB_DISC_OUTPUT("LIB_DISC_OUTPUT"),
      63              :                 LIB_DISC_OPERATOR_INVERSE("LIB_DISC_OPERATOR_INVERSE"),
      64              :                 LIB_ALG_LINEAR_OPERATOR("LIB_ALG_LINEAR_OPERATOR"),
      65              :                 LIB_ALG_LINEAR_SOLVER("LIB_ALG_LINEAR_SOLVER"),
      66              :                 LIB_ALG_VECTOR("LIB_ALG_VECTOR"),
      67              :                 LIB_ALG_MATRIX("LIB_ALG_MATRIX"),
      68              :                 LIB_ALG_AMG("LIB_ALG_AMG"),
      69              :                 LIB_PCL("LIB_PCL");
      70              : 
      71              : 
      72              : ///////////////////////////////////////////////////////////////////////////
      73              : 
      74            1 : LogAssistant::
      75            1 : LogAssistant() :
      76            1 :         m_terminalOutputEnabled(true),
      77            1 :         m_fileOutputEnabled(false),
      78            1 :         m_outputProc(0)
      79              : {
      80            1 : }
      81              : 
      82            0 : LogAssistant::LogAssistant(const LogAssistant&)
      83              : {
      84            0 : }
      85              : 
      86              : 
      87            1 : LogAssistant::~LogAssistant()
      88              : {
      89            1 :         flush();
      90            1 :         if(m_fileStream.is_open())
      91            1 :                 m_fileStream.close();
      92            1 : }
      93              : 
      94              : 
      95            1 : void LogAssistant::init()
      96              : {
      97              :         PROFILE_FUNC();
      98              : //      originally this was placed in the constructor.
      99              : //      However, an internal compiler error in MinGW (windows)
     100              : //      appears then. Having moved the stuff here into this init
     101              : //      method seems to have helped.
     102              :         set_debug_levels(-1); // 0 or -1 ?
     103            1 :         m_emptyBuf = &m_emptyBufInst;
     104            1 :         m_splitBuf = &m_splitBufInst;
     105            1 :         m_logBuf = cout.rdbuf();
     106            1 :         m_fileBuf = m_fileStream.rdbuf();
     107            1 :         m_splitBufInst.set_buffers(m_logBuf, m_fileBuf);
     108            1 :         update_ostream();
     109            1 : }
     110              : 
     111            3 : LogAssistant& LogAssistant::
     112              : instance()
     113              : {
     114            3 :         static LogAssistant log;
     115              :         
     116              : //      This special initialization is performed to avoid an internal compiler error
     117              : //      with MinGW. I don't know what causes that error, however using a init method
     118              : //      instead of the constructor seems to help.
     119              :         static bool initialized = false;
     120            3 :         if(!initialized){
     121            1 :                 initialized = true;
     122            1 :                 log.init();
     123              :         }
     124              :         
     125            3 :         return log;
     126              : }
     127              : 
     128            1 : void LogAssistant::flush()
     129              : {
     130            1 :         logger().flush();
     131            1 :         m_splitBufInst.flush();
     132            1 :         if(m_fileStream.is_open())
     133            1 :                 m_fileStream.flush();
     134            1 :         if(m_terminalOutputEnabled)
     135            0 :                 fflush(stdout);
     136            1 : }
     137              : 
     138              : 
     139            1 : bool LogAssistant::
     140              : enable_file_output(bool bEnable, const char* filename)
     141              : {
     142              :         PROFILE_FUNC();
     143            1 :         m_logFileName = filename;
     144            1 :         if(bEnable){
     145            1 :                 if(!open_logfile()){
     146            0 :                         update_ostream();
     147            0 :                         return false;
     148              :                 }
     149              :         }
     150              :         else
     151            0 :                 m_fileStream.close();
     152              : 
     153            1 :         m_fileOutputEnabled = bEnable;
     154            1 :         update_ostream();
     155            1 :         return true;
     156              : }
     157              : 
     158            0 : bool LogAssistant::
     159              : rename_log_file(const char * newname)
     160              : {
     161              :         PROFILE_FUNC();
     162            0 :         flush();
     163            0 :         if(m_fileStream.is_open()){
     164            0 :                 UG_LOG("Logfile '" << m_logFileName << "' renamed to '" << newname << "'" << std::endl);
     165            0 :                 rename(m_logFileName.c_str(), newname);
     166              :         }
     167            0 :         m_logFileName = newname;
     168            0 :         return true;
     169              : }
     170              : 
     171            1 : bool LogAssistant::
     172              : enable_terminal_output(bool bEnable)
     173              : {
     174              :         PROFILE_FUNC();
     175            1 :         m_terminalOutputEnabled = bEnable;
     176            1 :         update_ostream();
     177            1 :         return true;
     178              : }
     179              : 
     180            3 : void LogAssistant::
     181              : update_ostream()
     182              : {
     183            3 :         if(is_output_process()){
     184            3 :                 if(m_terminalOutputEnabled){
     185            1 :                         if(m_fileOutputEnabled){
     186              :                         //      make sure that the logfile is enabled
     187            0 :                                 if(open_logfile())
     188            0 :                                         cout.rdbuf(m_splitBuf);
     189              :                                 else
     190            0 :                                         cout.rdbuf(m_logBuf);
     191              :                         }
     192              :                         else
     193            1 :                                 cout.rdbuf(m_logBuf);
     194              :                 }
     195              :                 else{
     196            2 :                         if(m_fileOutputEnabled){
     197            1 :                                 if(open_logfile())
     198            1 :                                         cout.rdbuf(m_fileBuf);
     199              :                                 else
     200            0 :                                         cout.rdbuf(m_emptyBuf);
     201              :                         }
     202              :                         else{
     203            1 :                                 cout.rdbuf(m_emptyBuf);
     204              :                         }
     205              :                 }
     206              :         }
     207              :         else
     208            0 :                 cout.rdbuf(m_emptyBuf);
     209            3 : }
     210              : 
     211            2 : bool LogAssistant::
     212              : open_logfile()
     213              : {
     214              :         PROFILE_FUNC();
     215              :         // open log file only when output process
     216              :         // otherwise slowdown on > 1024 cores.
     217            2 :         if(!is_output_process())
     218              :                 return true;
     219            2 :         if(!m_fileStream.is_open()){
     220            1 :                 m_fileStream.open(m_logFileName.c_str());
     221            1 :                 if(!m_fileStream){
     222            0 :                         m_fileOutputEnabled = false;
     223              :                         UG_LOG("ERROR: LogAssistant::open_logfile failed: Couldn't open "
     224              :                                         << m_logFileName << endl);
     225            0 :                         return false;
     226              :                 }
     227              :         }
     228              :         return true;
     229              : }
     230              : 
     231              : 
     232            1 : void LogAssistant::
     233              : flush_error_log()
     234              : {
     235              :         string str = m_errStream.str();
     236            1 :         if(!str.empty()){
     237              :                 logger() << endl
     238              :                                 << "********************************************************************************\n"
     239              :                                 << "ERRORS OCCURED: " << endl << str << endl
     240            0 :                                 << "********************************************************************************\n";
     241            0 :                 m_errStream.clear();
     242              :         }
     243            1 : }
     244              : 
     245              : 
     246              : 
     247              : 
     248            0 : void LogAssistant::
     249              : set_output_process(int procRank)
     250              : {
     251            0 :         if(m_outputProc == procRank)
     252              :                 return;
     253              :         
     254              :         int numProcs = 1;
     255              :         #ifdef UG_PARALLEL
     256              :                 numProcs = pcl::NumProcs();
     257              :         #endif
     258              : 
     259            0 :         if(procRank < numProcs){
     260            0 :                 m_outputProc = procRank;
     261            0 :                 update_ostream();
     262              :         }
     263              :         else{
     264              :                 string strProc;
     265              :                 if(numProcs == 1)
     266              :                         strProc = " process is ";
     267              :                 else
     268              :                         strProc = " processes are ";
     269              : 
     270            0 :                 UG_LOG("WARNING: Won't change output process to " << procRank <<
     271              :                                 ", since only " << numProcs << strProc << "available. "
     272              :                                 "Output process is left at " << m_outputProc << "." << endl);
     273              :         }
     274              : }
     275              : 
     276            5 : bool LogAssistant::
     277              : is_output_process()
     278              : {
     279              :         #ifdef UG_PARALLEL
     280              :                 if((m_outputProc == pcl::ProcRank()) || (m_outputProc == -1))
     281              :                         return true;
     282              :                 else
     283              :                         return false;
     284              :         #endif
     285              : 
     286            5 :         return true;
     287              : }
     288              : 
     289            0 : int LogAssistant::
     290              : get_process_rank()
     291              : {
     292              :         #ifdef UG_PARALLEL
     293              :                 return pcl::ProcRank();
     294              :         #endif
     295              : 
     296            0 :         return 0;
     297              : }
     298              : 
     299            0 : int LogAssistant::get_debug_level_noninline(const char *debugID) const
     300              : {
     301            0 :         return GetDebugIDManager().get_debug_level(debugID);
     302              : }
     303              : 
     304            0 : bool LogAssistant::set_debug_level_noninline(const char* debugID, int level)
     305              : {
     306            0 :         return GetDebugIDManager().set_debug_level(debugID, level);
     307              : }
     308              : 
     309              : 
     310              : 
     311              : }//     end of namespace
        

Generated by: LCOV version 2.0-1