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
|