WvStreams
|
00001 /* 00002 * Worldvisions Weaver Software: 00003 * Copyright (C) 1997-2002 Net Integration Technologies, Inc. 00004 * 00005 * WvLogBuffer is a descendant of WvLogRcv that buffers log messages for 00006 * later use. It only keeps up to max_lines log entries for every 00007 * source/debug level, s.t. debug level <= max_level 00008 */ 00009 #include "wvlogbuffer.h" 00010 #include "strutils.h" 00011 #include <time.h> 00012 00013 WvLogBuffer::Msg::Msg(WvLog::LogLevel _level, WvStringParm _source, 00014 WvString _message) : level(_level), source(_source), message(_message) 00015 { 00016 time(×tamp); 00017 } 00018 00019 WvLogBuffer::Msg* WvLogBuffer::MsgCounter::add(WvLogBuffer::Msg* msg, int max) 00020 { 00021 list.append(msg, false); 00022 00023 // Check if we need to purge anything 00024 if (list.count() > (size_t)max) 00025 { 00026 Msg* killme = list.first(); 00027 list.unlink_first(); 00028 return killme; 00029 } 00030 else 00031 return NULL; 00032 } 00033 00034 00035 WvLogBuffer::WvLogBuffer(int _max_lines, WvLog::LogLevel _max_level) : 00036 WvLogRcv(_max_level), counters(25) 00037 { 00038 max_lines = _max_lines; 00039 } 00040 00041 00042 WvLogBuffer::~WvLogBuffer() 00043 { 00044 end_line(); 00045 } 00046 00047 00048 void WvLogBuffer::_mid_line(const char *str, size_t len) 00049 { 00050 current.put(str, len); 00051 } 00052 00053 void WvLogBuffer::handle_msg(Msg *lastmsg) 00054 { 00055 // Stick the msg in the list of all messages 00056 msgs.append(lastmsg, true); 00057 00058 // Check if we already have any messages of this source/level 00059 WvString type(WvString("%s:%s", last_source, last_level)); 00060 MsgCounter* msgcounter = counters[type]; 00061 // If not create a new tracking list for it 00062 if (!msgcounter) 00063 { 00064 msgcounter = new MsgCounter(type); 00065 counters.add(msgcounter, true); 00066 } 00067 // Now that we are sure the type exists, add the message to it 00068 Msg* killme = msgcounter->add(lastmsg, max_lines); 00069 00070 // Delete the extra messages if we need to 00071 if (killme) 00072 msgs.unlink(killme); 00073 } 00074 00075 void WvLogBuffer::_end_line() 00076 { 00077 if (last_level < WvLog::NUM_LOGLEVELS) 00078 { 00079 current.put('\0'); // terminating NULL 00080 Msg *lastmsg = new Msg(last_level, last_source, 00081 trim_string((char *)current.get(current.used()))); 00082 00083 handle_msg(lastmsg); 00084 } 00085 else 00086 current.zap(); 00087 } 00088 00089 void WvLogBuffer::feed_receiver(WvLogRcv& receiver) 00090 { 00091 WvLogBuffer::MsgList::Iter i(msgs); 00092 i.rewind(); 00093 while (i.next()) 00094 { 00095 WvLogBuffer::Msg &msg = *i; 00096 receiver.log(msg.source, msg.level, 00097 msg.message.cstr(), msg.message.len()); 00098 } 00099 } 00100 00101 00102 void WvLogBuffer::dump(WvStream &s) 00103 { 00104 MsgList::Iter i(messages()); 00105 00106 for (i.rewind(); i.next(); ) 00107 { 00108 Msg &m = *i; 00109 s.print("%s %s<%s>: %s+\n", 00110 m.timestamp, m.source, loglevels[m.level], m.message); 00111 } 00112 }