00001 //# LoggerHolder.h: Class holding a hierarchy of loggers 00002 //# Copyright (C) 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$ 00028 00029 #ifndef TABLES_LOGGERHOLDER_H 00030 #define TABLES_LOGGERHOLDER_H 00031 00032 //# Includes 00033 #include <casacore/casa/aips.h> 00034 #include <casacore/casa/Logging/LogIO.h> 00035 #include <casacore/casa/Containers/Block.h> 00036 #include <casacore/casa/Utilities/CountedPtr.h> 00037 00038 namespace casacore { //# NAMESPACE CASACORE - BEGIN 00039 00040 //# Forward Declarations 00041 class LoggerHolderRep; 00042 class LoggerHolderIterator; 00043 class TableLogSink; 00044 00045 // <summary> 00046 // Class holding a hierarchy of loggers. 00047 // </summary> 00048 00049 // <use visibility=export> 00050 00051 // <reviewed reviewer="" date="" tests="tLoggerHolder.cc" demos=""> 00052 // </reviewed> 00053 00054 // <prerequisite> 00055 // <li> <linkto class="LogIO">LogIO</linkto> <li> 00056 // </prerequisite> 00057 00058 // <synopsis> 00059 // The LoggerHolder class implements a hierarchy of loggers. 00060 // It has a log sink of its own and can have multiple parent LoggerHolder 00061 // objects representing the log info of parent objects. 00062 // It is used by class 00063 // <linkto class=ImageInterface>ImageInterface</linkto>, but could also 00064 // be used elsewhere. 00065 // 00066 // The sink of a LoggerHolder can be different depending on the type of image. 00067 // E.g. for a transient image it can be a 00068 // <linkto class=MemoryLogSink>MemoryLogSink</linkto>, while for a persistent 00069 // image it will be a <linkto class=TableLogSink>TableLogSink</linkto>. 00070 // <br>An important feature is that an LoggerHolder can have zero or more 00071 // parent LoggerHolder objects. In that way the log of the parent object 00072 // of an image object can be made part of the log of the image object itself, 00073 // without having to copy the log. 00074 // 00075 // To iterate through all messages in a LoggerHolder (including all parents), 00076 // the <linkto class=LoggerHolderIterator>LoggerHolderIterator</linkto> can 00077 // be used. This is an STL-style const_iterator object. 00078 // 00079 // LoggerHolder uses reference counting 00080 // (of class <linkto class=LoggerHolderRep>LoggerHolderRep</linkto>) 00081 // to be able to retain 00082 // the object after the (ImageInterface) object containing it is gone. 00083 // Otherwise classes like SubImage would lose their log info. 00084 // </synopsis> 00085 00086 // <example> 00087 // <srcblock> 00088 // LoggerHolder logger ("tLoggerHolder_tmp.log", True); 00089 // logger.logio() << "test1" << LogIO::POST; 00090 // logger.logio() << "test2" << LogIO::POST; 00091 // for (LoggerHolder::const_iterator iter = logger.begin(); 00092 // iter != logger.end(); 00093 // iter++) { 00094 // cout << iter->time() << ' ' << iter->message() << endl; 00095 // } 00096 // </srcblock> 00097 // This example shows the construction of an LoggerHolder with a 00098 // TableLogSink sink. Thereafter some messages are written. 00099 // The latter part shows how to iterate through all messages. 00100 // 00101 // <srcblock> 00102 // LoggerHolder logger (False); 00103 // logger.addParent (parent.logger()); 00104 // logger.logio() << "test1" << LogIO::POST; 00105 // logger.logio() << "test2" << LogIO::POST; 00106 // </srcblock> 00107 // This example shows the construction of an LoggerHolder with a 00108 // MemoryLogSink sink (e.g. for a SubImage). Thereafter the logger of 00109 // the parent image is added to it. 00110 // Finally some messages are written. 00111 // </example> 00112 00113 // <motivation> 00114 // This class simplifies and unifies all Image logging activities. 00115 // </motivation> 00116 00117 //# <todo asof="2001/06/14"> 00118 //# </todo> 00119 00120 class LoggerHolder 00121 { 00122 public: 00123 // Create with a NullSink or MemoryLogSink (default). 00124 explicit LoggerHolder (Bool nullSink = False); 00125 00126 // Create with a TableLogSink. 00127 LoggerHolder (const String& logTableName, Bool isWritable); 00128 00129 // Copy constructor (reference sematics). 00130 LoggerHolder (const LoggerHolder&); 00131 00132 ~LoggerHolder(); 00133 00134 // Assignment (reference semantics). 00135 LoggerHolder& operator= (const LoggerHolder&); 00136 00137 // Add a logger from a parent. 00138 void addParent (const LoggerHolder&); 00139 00140 // Append the entries of the other logger to this one. 00141 void append (const LoggerHolder& other); 00142 00143 // Reopen a readonly logtable for read/write (if needed). 00144 void reopenRW(); 00145 00146 // Reopen the log table if needed (after a tempClose). 00147 void reopen(); 00148 00149 // Temporarily close all log tables. 00150 // By default the possible parent log tables are also closed. 00151 void tempClose (Bool closeParents = True) const; 00152 00153 // Unlock the log table. 00154 void unlock(); 00155 00156 // Flush the log table. 00157 void flush(); 00158 00159 // Resync the log table (if needed). 00160 void resync(); 00161 00162 // Is the log table temporarily closed? 00163 Bool isTempClosed() const; 00164 00165 // Get access to the logger. 00166 // It assumes that it will be used to post a message, so it reopens 00167 // the log table for read/write if needed). 00168 LogIO& logio(); 00169 00170 // Get access to the log sink (reopen the log table if needed). 00171 // It is not assumed you want to write. If you want to do that, 00172 // you should first call reopenRW() to ensure you can write. 00173 // <group> 00174 LogSink& sink(); 00175 const LogSink& sink() const; 00176 // </group> 00177 00178 // Clear the log. 00179 // It removes the parents and removes all messages from the sink. 00180 void clear(); 00181 00182 // Remove all parents. 00183 void removeParents(); 00184 00185 // Return the block of parents. 00186 const Block<LoggerHolder>& parents() const; 00187 00188 // Define the STL-style iterators. 00189 // Only a const forward iterator is available. 00190 // It makes it possible to iterate through all messages in the logger. 00191 // <srcblock> 00192 // LoggerHolder logger("log.name", False) 00193 // for (LoggerHolder::const_iterator iter=arr.begin(); 00194 // iter!=arr.end(); iter++) { 00195 // cout << iter.message() << endl; 00196 // } 00197 // </srcblock> 00198 // <group name=STL-iterator> 00199 // STL-style typedefs. 00200 typedef LoggerHolderIterator const_iterator; 00201 // Get the begin and end iterator object. 00202 const_iterator begin() const; 00203 const_iterator end() const; 00204 // </group> 00205 00206 00207 private: 00208 CountedPtr<LoggerHolderRep> itsRep; 00209 }; 00210 00211 00212 00213 00214 // <summary> 00215 // Representation of the class holding a hierarchy of loggers. 00216 // </summary> 00217 00218 // <use visibility=local> 00219 00220 // <reviewed reviewer="" date="" tests="tLoggerHolder.cc" demos=""> 00221 // </reviewed> 00222 00223 // <prerequisite> 00224 // <li> <linkto class="LogIO">LogIO</linkto> <li> 00225 // </prerequisite> 00226 00227 // <synopsis> 00228 // The LoggerHolderRep class is the reference counted implementation 00229 // of <linkto class=LoggerHolder>LoggerHolder</linkto>. 00230 // See that class for more information. 00231 // </synopsis> 00232 00233 // <motivation> 00234 // Reference counting was needed to be able to keep a LoggerHolder 00235 // object after the (ImageInterface) object containing it is gone. 00236 // </motivation> 00237 00238 //# <todo asof="2001/06/14"> 00239 //# </todo> 00240 00241 class LoggerHolderRep 00242 { 00243 public: 00244 // Create with a NullSink or MemoryLogSink (default). 00245 LoggerHolderRep (Bool nullSink); 00246 00247 // Create with a TableLogSink. 00248 LoggerHolderRep (const String& logTableName, Bool isWritable); 00249 00250 // Copy constructor. 00251 LoggerHolderRep (const LoggerHolderRep&); 00252 00253 ~LoggerHolderRep(); 00254 00255 // Assignment. 00256 // It removes the current parents. 00257 LoggerHolderRep& operator= (const LoggerHolderRep&); 00258 00259 // Add a logger from a parent. 00260 void addParent (const LoggerHolder&); 00261 00262 // Append the entries of the other logger to this one. 00263 void append (const LoggerHolder& other); 00264 00265 // Reopen a readonly logtable for read/write (if needed). 00266 void reopenRW(); 00267 00268 // Reopen the log table if needed (after a tempClose). 00269 void reopen() 00270 { if (itsIsClosed) doReopen(); } 00271 00272 // Temporarily close all log tables. 00273 // By default the possible parent log tables are also closed. 00274 void tempClose (Bool closeParents = True); 00275 00276 // Unlock the log table. 00277 void unlock(); 00278 00279 // Flush the log table. 00280 void flush(); 00281 00282 // Resync the log table (if needed). 00283 void resync(); 00284 00285 // Is the log table temporarily closed? 00286 Bool isTempClosed() const 00287 { return itsIsClosed; } 00288 00289 // Get access to the logger. 00290 // It assumes that it will be used to post a message, so it reopens 00291 // the log table for read/write if needed). 00292 LogIO& logio(); 00293 00294 // Get access to the log sink (reopen the log table if needed). 00295 // It is not assumed you want to write. If you want to do that, 00296 // you should first call reopenRW() to ensure you can write. 00297 LogSink& sink(); 00298 00299 // Clear the log. 00300 // It removes the parents and removes all messages from the sink. 00301 void clear(); 00302 00303 // Remove all parents. 00304 void removeParents(); 00305 00306 // Return the block of parents. 00307 const Block<LoggerHolder>& parents() const 00308 { return itsParents; } 00309 00310 // Define the STL-style iterators. 00311 // Only a const forward iterator is available. 00312 // It makes it possible to iterate through all messages in the logger. 00313 // <srcblock> 00314 // LoggerHolder logger("log.name", False) 00315 // for (LoggerHolder::const_iterator iter=arr.begin(); 00316 // iter!=arr.end(); iter++) { 00317 // cout << iter.message() << endl; 00318 // } 00319 // </srcblock> 00320 // <group name=STL-iterator> 00321 // STL-style typedefs. 00322 typedef LoggerHolderIterator const_iterator; 00323 // Get the begin and end iterator object. 00324 const_iterator begin() const; 00325 const_iterator end() const; 00326 // </group> 00327 00328 00329 private: 00330 // Do the actual reopen. 00331 void doReopen(); 00332 00333 00334 Block<LoggerHolder> itsParents; 00335 LogSink itsSink; 00336 LogIO itsLogger; 00337 String itsTableName; 00338 TableLogSink* itsTablePtr; 00339 Bool itsIsWritable; 00340 Bool itsIsClosed; 00341 }; 00342 00343 00344 00345 00346 // <summary> 00347 // Class representing an entry in a LoggerHolder. 00348 // </summary> 00349 00350 // <use visibility=local> 00351 00352 // <reviewed reviewer="" date="" tests="tLoggerHolder.cc" demos=""> 00353 // </reviewed> 00354 00355 // <prerequisite> 00356 // <li> <linkto class="LoggerHolder">LoggerHolder</linkto> <li> 00357 // </prerequisite> 00358 00359 // <synopsis> 00360 // This class makes it possible to use the iterator in the STL-style. 00361 // It only contains a 'pointer' to the current entry in the current logger. 00362 // Function like <src>time()</src> can be used to retrieve the message parts. 00363 // </synopsis> 00364 00365 class LogHolderIterEntry 00366 { 00367 public: 00368 LogHolderIterEntry() 00369 : itsSink(0), itsIndex(0) {} 00370 00371 LogHolderIterEntry (const LogSink* sink, uInt index) 00372 : itsSink(sink), itsIndex(index) {} 00373 00374 LogHolderIterEntry (const LogHolderIterEntry& that) 00375 : itsSink(that.itsSink), itsIndex(that.itsIndex) {} 00376 00377 ~LogHolderIterEntry() 00378 {} 00379 00380 LogHolderIterEntry& operator= (const LogHolderIterEntry& that) 00381 { itsSink=that.itsSink; itsIndex=that.itsIndex; return *this; } 00382 00383 // Get the message parts. 00384 // <group> 00385 Double time() const 00386 { return itsSink->getTime(itsIndex); } 00387 String message() const 00388 { return itsSink->getMessage(itsIndex); } 00389 String priority() const 00390 { return itsSink->getPriority(itsIndex); } 00391 String location() const 00392 { return itsSink->getLocation(itsIndex); } 00393 String objectID() const 00394 { return itsSink->getObjectID(itsIndex); } 00395 // </group> 00396 00397 private: 00398 const LogSink* itsSink; 00399 uInt itsIndex; 00400 }; 00401 00402 00403 00404 00405 // <summary> 00406 // Class doing the actual iteration through an LoggerHolder. 00407 // </summary> 00408 00409 // <use visibility=local> 00410 00411 // <reviewed reviewer="" date="" tests="tLoggerHolder.cc" demos=""> 00412 // </reviewed> 00413 00414 // <prerequisite> 00415 // <li> <linkto class="LoggerHolder">LoggerHolder</linkto> <li> 00416 // </prerequisite> 00417 00418 // <synopsis> 00419 // This class makes it possible to use the iterator in the STL-style. 00420 // It is used by 00421 //<linkto class=LoggerHolderIterator>LoggerHolderIterator</linkto> 00422 // which is the class as seen by the user. 00423 // LogHolderIter makes it easier to make the first entry available on 00424 // construction of an LoggerHolderIterator. 00425 // </synopsis> 00426 00427 class LogHolderIter 00428 { 00429 public: 00430 // Construct the iterator on the given LoggerHolderRep. 00431 LogHolderIter (const LoggerHolder*); 00432 00433 ~LogHolderIter(); 00434 00435 // Increment to next message. 00436 // Returns False if at the end. 00437 Bool next(); 00438 00439 // Get the entry. 00440 const LogHolderIterEntry& getEntry() const 00441 { return itsEntry; } 00442 00443 const LoggerHolder& logger() const 00444 { return *itsLogger; } 00445 00446 private: 00447 // Copy constructor is not needed, thus forbidden. 00448 LogHolderIter (const LogHolderIter&); 00449 00450 // Assignment is not needed, thus forbidden. 00451 LogHolderIter& operator= (const LogHolderIter&); 00452 00453 00454 const LoggerHolder* itsLogger; 00455 Bool itsTempClosed; 00456 LogHolderIter* itsParentIter; 00457 uInt itsCounter; 00458 LogHolderIterEntry itsEntry; 00459 }; 00460 00461 00462 00463 // <summary> 00464 // Class to iterate through an LoggerHolder. 00465 // </summary> 00466 00467 // <use visibility=export> 00468 00469 // <reviewed reviewer="" date="" tests="tLoggerHolder.cc" demos=""> 00470 // </reviewed> 00471 00472 // <prerequisite> 00473 // <li> <linkto class="LoggerHolder">LoggerHolder</linkto> <li> 00474 // </prerequisite> 00475 00476 // <synopsis> 00477 // This class makes it possible to iterate in the STL-style through all 00478 // entries of an LoggerHolder object. If the logger has parent LoggerHolder 00479 // objects, it first iterates through all parents (recursively) and 00480 // finally through all entries in the LoggerHolder object itself. 00481 // </synopsis> 00482 00483 // <example> 00484 // <srcblock> 00485 // LoggerHolder logger ("tLoggerHolder_tmp.log", True); 00486 // logger.logio() << "test1" << LogIO::POST; 00487 // logger.logio() << "test2" << LogIO::POST; 00488 // for (LoggerHolder::const_iterator iter = logger.begin(); 00489 // iter != logger.end(); 00490 // iter++) { 00491 // cout << iter->time() << ' ' << iter->message() << endl; 00492 // } 00493 // </srcblock> 00494 // </example> 00495 00496 class LoggerHolderIterator 00497 { 00498 public: 00499 LoggerHolderIterator() 00500 : itsIter(0), itsNotAtEnd(False) {} 00501 00502 LoggerHolderIterator (const LoggerHolder*); 00503 00504 LoggerHolderIterator (const LoggerHolderIterator&); 00505 00506 ~LoggerHolderIterator() 00507 { delete itsIter; } 00508 00509 LoggerHolderIterator& operator= (const LoggerHolderIterator&); 00510 00511 // Increment to next message. 00512 // <group> 00513 void operator++() 00514 { next(); } 00515 void operator++ (int) 00516 { next(); } 00517 // </group> 00518 00519 // Is the iterator not at the end yet? 00520 Bool operator!= (const LoggerHolderIterator&) 00521 { return itsNotAtEnd; } 00522 00523 // Get the entry. 00524 // <group> 00525 const LogHolderIterEntry& operator*() const 00526 { return itsIter->getEntry(); } 00527 const LogHolderIterEntry* operator->() const 00528 { return &(itsIter->getEntry()); } 00529 // </group> 00530 00531 const LoggerHolder& logger() const 00532 { return itsIter->logger(); } 00533 00534 private: 00535 // Get the next entry (if available). 00536 void next() 00537 { itsNotAtEnd = itsIter->next(); } 00538 00539 00540 LogHolderIter* itsIter; 00541 Bool itsNotAtEnd; 00542 }; 00543 00544 00545 00546 inline void LoggerHolder::reopen() 00547 { 00548 itsRep->reopen(); 00549 } 00550 inline Bool LoggerHolder::isTempClosed() const 00551 { 00552 return itsRep->isTempClosed(); 00553 } 00554 inline LogIO& LoggerHolder::logio() 00555 { 00556 return itsRep->logio(); 00557 } 00558 inline LogSink& LoggerHolder::sink() 00559 { 00560 return itsRep->sink(); 00561 } 00562 inline const LogSink& LoggerHolder::sink() const 00563 { 00564 return itsRep->sink(); 00565 } 00566 inline const Block<LoggerHolder>& LoggerHolder::parents() const 00567 { 00568 return itsRep->parents(); 00569 } 00570 inline LoggerHolder::const_iterator LoggerHolder::begin() const 00571 { 00572 return LoggerHolderIterator (this); 00573 } 00574 inline LoggerHolder::const_iterator LoggerHolder::end() const 00575 { 00576 return LoggerHolderIterator(); 00577 } 00578 00579 00580 00581 00582 } //# NAMESPACE CASACORE - END 00583 00584 #endif