casa
$Rev:20696$
|
00001 //# LogSink.h: Distribute LogMessages to their destination(s) 00002 //# Copyright (C) 1996,2000,2001,2003 00003 //# Associated Universities, Inc. Washington DC, USA. 00004 //# 00005 //# This library is free software; you can redistribute it and/or modify it 00006 //# under the terms of the GNU Library General Public License as published by 00007 //# the Free Software Foundation; either version 2 of the License, or (at your 00008 //# option) any later version. 00009 //# 00010 //# This library is distributed in the hope that it will be useful, but WITHOUT 00011 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00012 //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 00013 //# License for more details. 00014 //# 00015 //# You should have received a copy of the GNU Library General Public License 00016 //# along with this library; if not, write to the Free Software Foundation, 00017 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. 00018 //# 00019 //# Correspondence concerning AIPS++ should be addressed as follows: 00020 //# Internet email: aips2-request@nrao.edu. 00021 //# Postal address: AIPS++ Project Office 00022 //# National Radio Astronomy Observatory 00023 //# 520 Edgemont Road 00024 //# Charlottesville, VA 22903-2475 USA 00025 //# 00026 //# 00027 //# $Id: LogSink.h 21051 2011-04-20 11:46:29Z gervandiepen $ 00028 00029 #ifndef CASA_LOGSINK_H 00030 #define CASA_LOGSINK_H 00031 00032 #include <casa/aips.h> 00033 #include <casa/Logging/LogSinkInterface.h> 00034 00035 #include <casa/Utilities/CountedPtr.h> 00036 #include <casa/Exceptions/Error.h> 00037 #include <casa/OS/Mutex.h> 00038 #include <casa/iosfwd.h> 00039 00040 namespace casa { //# NAMESPACE CASA - BEGIN 00041 00042 // <summary> 00043 // Distribute LogMessages to their destination(s) 00044 // </summary> 00045 00046 // <use visibility=export> 00047 00048 // <reviewed reviewer="wbrouw" date="1996/08/21" tests="tLogging.cc" demos="dLogging.cc"> 00049 // </reviewed> 00050 00051 // <prerequisite> 00052 // <li> <linkto class="LogMessage">LogMessage</linkto> 00053 // <li> <linkto class="LogSinkInterface">LogSinkInterface</linkto>, if you are 00054 // interested in extending the set of destinations a <src>LogMessage</src> can 00055 // be sent. 00056 // </prerequisite> 00057 // 00058 // <etymology> 00059 // Log as in "Log Book." Sink from its common usage ("source/sink") as a thing 00060 // which can accept some substance or energy. 00061 // </etymology> 00062 // 00063 // <synopsis> 00064 // The LogSink class supplies the destination for 00065 // <linkto class="LogMessage">LogMessage</linkto>s. There are two destinations 00066 // available through the <src>LogSink</src> 00067 // <ol> 00068 // <li> A <i>global</i> destination, which is shared by all LogSinks. The global 00069 // destination will typically be a GUI window or standard output. 00070 // <li> A <i>local</i> destination which is intended to log changes to 00071 // particular dataset(s). The local destination will typically be an 00072 // AIPS++ <linkto class="Table">Table</linkto>, but there is also 00073 // a local sink for temporary storage in memory. 00074 // </ol> 00075 // Normally the <src>post()</src> member function will be called which 00076 // sends the message to both the global and local destinations, however one or 00077 // the other may be chosen via <src>LogSink::postGlobally()</src> and 00078 // <src>postLocally()</src> member functions. 00079 // 00080 // The global sink will normally be set by system library code (it defaults to 00081 // using <src>cerr</src>. The type of local sink is defined at 00082 // construction time. Presently you can choose one of: 00083 // <ol> 00084 // <li> a <linkto class="NullLogSink">NullLogSink</linkto> which merely 00085 // discards the logging messages. 00086 // <li> a <linkto class="StreamLogSink">StreamLogSink</linkto> which sends 00087 // the log messages to an <src>ostream</src> (typically <src>cerr</src>) 00088 // <li> a <linkto class="TableLogSink">TableLogSink</linkto> which sends 00089 // the messages to an AIPS++ <linkto class=Table>Table</linkto>. 00090 // </ol> 00091 // 00092 // Every <src>LogSink</src> has an attached 00093 // <linkto class=LogFilterInterface>LogFilterInterface</linkto> 00094 // which is used to reject or pass messages. 00095 // The local and global sinks have their own filters, so they can 00096 // pass different message priorities (e.g., global <src>DEBUGGING</src> and 00097 // local <src>NORMAL</src>). Generally applications code shouldn't change the 00098 // global filter. 00099 // 00100 // </synopsis> 00101 // 00102 // <example> 00103 // <srcblock> 00104 // LogMessage logMessage(...); 00105 // LogSink logger(LogMessage::NORMAL, "logtable"); // log locally to a 'logtable' 00106 // logMessage.message("this is a message").line(__LINE__); 00107 // logger.post(logMessage); // local and global 00108 // </srcblock> 00109 // More complete examples are in <linkto file=Logging.h>Logging.h</linkto>. 00110 // </example> 00111 // 00112 // <h3>Advanced topics</h3> 00113 // All possible sinks are derived from an abstract base class: 00114 // <linkto class=LogSinkInterface>LogSinkInterface</linkto>. If you want to 00115 // allow for logging to a different type of sink (i.e. different from 00116 // a stream or Table) , you first need to derive a new class from 00117 // <src>LogSinkInterface</src>, and then add a new constructor to 00118 // <src>LogSink</src>. 00119 // 00120 // <src>LogSink</src> itself contains a reference to the actual object that 00121 // disposes of the messages. Several <src>LogSink</src>'s can share the same 00122 // actual sink via the copy constructor or assignment operator. 00123 // <srcblock> 00124 // LogSink logger1(LogMessage::NORMAL, "logtable"); 00125 // LogSink logger2(logger1); // logger2 references logger1 00126 // logger2.post(message); // ends up in "logtable" 00127 // </srcblock> 00128 // You can even have different <src>LogFilterInterface</src>'s 00129 // attached to the different <src>LogSink</src>s. 00130 // 00131 // <motivation> 00132 // Logging changes to data and informing users what the software is doing in 00133 // detail. 00134 // </motivation> 00135 // 00136 // <todo asof="1996/07/24"> 00137 // <li> More sink types - in particular to Glish. 00138 // <li> A "tee" Sink type might be useful. 00139 // </todo> 00140 00141 class LogSink : public LogSinkInterface 00142 { 00143 public: 00144 //#If you add more sink types, modify the <ol> in the synopsis as well. 00145 // Create a null local sink that throws all messages away or create 00146 // a memory local sink that holds the messages in memory. 00147 // If a filter isn't defined, default to <src>NORMAL</src>. 00148 // <group> 00149 explicit LogSink (LogMessage::Priority filter = LogMessage::NORMAL, 00150 Bool nullSink = True); 00151 explicit LogSink (const LogFilterInterface &filter, Bool nullSink = True); 00152 // </group> 00153 00154 // Log to an ostream. It is the responsiblity of the caller to ensure that 00155 // <src>os</src> will last as long as the <src>LogSink</src>s that use it. 00156 // Normally you would use <src>&cerr</src> as the argument. 00157 // <group> 00158 LogSink (LogMessage::Priority filter, ostream *os, 00159 Bool useGlobalSink = True); 00160 LogSink (const LogFilterInterface &filter, ostream *os, 00161 Bool useGlobalSink = True); 00162 // </group> 00163 00164 // Log to the given sink. 00165 // It is primarily intended to log to a 00166 // <linkto class=TableLogSink>TableLogSink</linkto>. 00167 LogSink (const LogFilterInterface &filter, 00168 const CountedPtr<LogSinkInterface>&); 00169 00170 // Make a referencing copy of <src>other</src>. That is, if you post a 00171 // message to the new object, it behaves as if you had posted it to the 00172 // old one (so long as their filters are the same). 00173 // <group> 00174 LogSink (const LogSink &other); 00175 LogSink &operator= (const LogSink &other); 00176 // </group> 00177 00178 // Temporary to avoid problem that the bool constructor is taken 00179 // if a char* is passed. 00180 // They are not implemented, so compiler should give warning. 00181 // The 3rd argument is added to make it different from current 00182 // version which is still in the system library. 00183 LogSink (const LogFilterInterface &filter, const String &fileName, Int n=0); 00184 LogSink (const LogFilterInterface &filter, const Char* fileName, Int n=0); 00185 LogSink (LogMessage::Priority, const String &fileName, Int n=0); 00186 LogSink (LogMessage::Priority, const Char* fileName, Int n=0); 00187 00188 ~LogSink(); 00189 00190 // Send <src>message</src> to both the local and global sink. Return 00191 // <src>True</src> if it passes either of them. 00192 Bool post (const LogMessage &message); 00193 00194 // Send <src>message</src> to the global sink only. Returns <src>True</src> 00195 // if it passes the filter. 00196 static Bool postGlobally (const LogMessage &message); 00197 // Send <src>message</src> to the local sink only. Returns <src>True</src> 00198 // if it passes the filter. 00199 virtual Bool postLocally (const LogMessage &message); 00200 00201 // Post <src>message</src> and then throw an <src>AipsError</src> exception 00202 // containing <src>message.toString()</src>. It is always posted as a 00203 // <src>SEVERE</src> priority message, no matter what 00204 // <src>message.priority()</src> says. 00205 // <group> 00206 template<typename EXC> void postThenThrow (const LogMessage &message, 00207 const EXC& exc) 00208 { preparePostThenThrow(message, exc); throw exc; } 00209 static void postGloballyThenThrow (const LogMessage &message); 00210 // </group> 00211 00212 // Get number of messages in local sink. 00213 virtual uInt nelements() const; 00214 00215 // Get given part of the i-th message from the local sink. 00216 // <group> 00217 virtual Double getTime (uInt i) const; 00218 virtual String getPriority (uInt i) const; 00219 virtual String getMessage (uInt i) const; 00220 virtual String getLocation (uInt i) const; 00221 virtual String getObjectID (uInt i) const; 00222 // </group> 00223 00224 // Write a message (usually from another logsink) into the local one. 00225 // The default implementation does nothing. 00226 virtual void writeLocally (Double time, const String& message, 00227 const String& priority, const String& location, 00228 const String& objectID); 00229 00230 // Clear the local sink (i.e. remove all messages from it). 00231 virtual void clearLocally(); 00232 00233 //# Bring out of LogSinkInterface only for documentation purposes 00234 // Get or set the filter of this particular <src>LogSink</src>. 00235 // <group> 00236 virtual const LogFilterInterface &filter() const; 00237 virtual LogSinkInterface &filter (const LogFilterInterface &filter); 00238 // </group> 00239 00240 // Change the sink that this <src>LogSink</src> actually uses. 00241 // <group> 00242 const LogSinkInterface &localSink() const; 00243 LogSinkInterface &localSink(); 00244 LogSink &localSink (LogSinkInterface *&fromNew); 00245 // </group> 00246 00247 // Get/set the global sink or check if the global sink is null. The global 00248 // sink defaults to using <src>cerr</src>. Generally applications code 00249 // shouldn't change the global sink. 00250 // <group> 00251 static LogSinkInterface &globalSink(); 00252 static void globalSink (LogSinkInterface *&fromNew); 00253 static Bool nullGlobalSink(); 00254 // </group> 00255 00256 // Write any pending output (by default also the global sink). 00257 virtual void flush (Bool global=True); 00258 00259 // Returns the id for this class... 00260 static String localId( ); 00261 // Returns the id of the LogSink in use... 00262 String id( ) const; 00263 00264 private: 00265 00266 // LsiIntermediate is a helper class to allow LogSinkInterface to implement 00267 // semantics that allow causing all classes accessing the log sink to be 00268 // aimed at a different sink object. This used to be done by using an 00269 // odd "replace" method in CountedPtr; however, this is functionality is 00270 // being removed to CountedPtr as it is modernized so this class was 00271 // created to serve this narrow purpose. 00272 00273 class LsiIntermediate { 00274 00275 public: 00276 00277 00278 LsiIntermediate () : logSinkInterface_p (0) {} 00279 LsiIntermediate (LogSinkInterface * lsi) : logSinkInterface_p (lsi) {} 00280 ~LsiIntermediate () { delete logSinkInterface_p;} 00281 00282 LogSinkInterface & operator* () { return * logSinkInterface_p;} 00283 LogSinkInterface * operator-> () { return logSinkInterface_p;} 00284 Bool operator! () const { return ! logSinkInterface_p;} 00285 00286 void replace (LogSinkInterface * newLsi) { delete logSinkInterface_p; logSinkInterface_p = newLsi;} 00287 00288 private: 00289 00290 // Copy ctor and op= are private and not defined to prevent double-delete. 00291 00292 LsiIntermediate (const LsiIntermediate &); 00293 LsiIntermediate & operator= (const LsiIntermediate &); 00294 00295 LogSinkInterface * logSinkInterface_p; 00296 00297 }; 00298 00299 // Prepare for postThenThrow function. 00300 void preparePostThenThrow(const LogMessage &message, const AipsError& x) ; 00301 00302 // Create the global sink (attached to cerr). 00303 static void createGlobalSink(); 00304 00305 //# Data members. 00306 CountedPtr<LogSinkInterface> local_sink_p; 00307 static CountedPtr<LsiIntermediate> * global_sink_p; 00308 static Mutex theirMutex; 00309 00310 // The following is a reference to the global sink. It is created to 00311 // ensure that the global sink is not destroyed before the last local 00312 // reference to it is destroyed. This can happen if you have a static 00313 // LogSink (or LogIO). 00314 CountedPtr<LsiIntermediate> local_ref_to_global_p; 00315 Bool useGlobalSink_p; 00316 }; 00317 00318 00319 00320 } //# NAMESPACE CASA - END 00321 00322 #endif