Commit 8a390c1d authored by Pavel Vainerman's avatar Pavel Vainerman

(Log): добавил LogAgregator для возможности "агрегировать" сразу

несколько DebugStream-ов и (например) подключать их к одному LogServer-у. (Log): добавил в DebugStream возможность задать "название" лога. Для возможности дальнейшего использования при управлении логами.. - добавил возможность задавать команду для конкретного лога (logreader) - сделал, чтобы лог в LogAgregator на экран не выводился
parent d1f6eb74
...@@ -55,12 +55,13 @@ int main( int argc, char* argv[], char* envp[] ) ...@@ -55,12 +55,13 @@ int main( int argc, char* argv[], char* envp[] )
case 0: case 0:
{ {
/* Child. */ /* Child. */
close(1); /* Close current stdout. */ close(cp[0]);
dup(cp[1]); /* Make stdout go to write end of pipe. */
// close(0); /* Close current stdin. */ close( fileno(stderr) ); //close stderr
// dup( pc[0]); /* Make stdin come from read end of pipe. */ dup2(fileno(stdout),fileno(stderr));
close( cp[0]);
close(fileno(stdout)); /* Close current stdout. */
dup2(cp[1],fileno(stdout)); /* Make stdout go to write end of pipe. */
execvpe(argv[3], argv + 3, envp); execvpe(argv[3], argv + 3, envp);
perror("No exec"); perror("No exec");
...@@ -89,6 +90,7 @@ int main( int argc, char* argv[], char* envp[] ) ...@@ -89,6 +90,7 @@ int main( int argc, char* argv[], char* envp[] )
ssize_t r = read(cp[0], &buf, sizeof(buf)-1 ); ssize_t r = read(cp[0], &buf, sizeof(buf)-1 );
if( r > 0 ) if( r > 0 )
{ {
cout << "***READ**" << endl;
buf[r] = '\0'; buf[r] = '\0';
zlog << buf; zlog << buf;
} }
......
...@@ -21,6 +21,8 @@ static struct option longopts[] = { ...@@ -21,6 +21,8 @@ static struct option longopts[] = {
{ "off", required_argument, 0, 'o' }, { "off", required_argument, 0, 'o' },
{ "on", required_argument, 0, 'n' }, { "on", required_argument, 0, 'n' },
{ "rotate", required_argument, 0, 'r' }, { "rotate", required_argument, 0, 'r' },
{ "logname", required_argument, 0, 'l' },
{ "command-only", no_argument, 0, 'b' },
{ NULL, 0, 0, 0 } { NULL, 0, 0, 0 }
}; };
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
...@@ -28,8 +30,11 @@ static void print_help() ...@@ -28,8 +30,11 @@ static void print_help()
{ {
printf("-h, --help - this message\n"); printf("-h, --help - this message\n");
printf("-v, --verbose - Print all messages to stdout\n"); printf("-v, --verbose - Print all messages to stdout\n");
printf("[-i|--iaddr] addr - ULogServer ip or hostname.\n"); printf("[-i|--iaddr] addr - LogServer ip or hostname.\n");
printf("[-p|--port] port - ULogServer port.\n"); printf("[-p|--port] port - LogServer port.\n");
printf("[-l|--logname] name - Send command only for 'logname'.\n");
printf("[-b|--command-only] - Send command and break. (No read logs).\n");
printf("\n"); printf("\n");
printf("Commands:\n"); printf("Commands:\n");
...@@ -52,10 +57,12 @@ int main( int argc, char **argv ) ...@@ -52,10 +57,12 @@ int main( int argc, char **argv )
int cmd = LogServerTypes::cmdNOP; int cmd = LogServerTypes::cmdNOP;
int data = 0; int data = 0;
string sdata(""); string sdata("");
int cmdonly = 0;
string logname("");
try try
{ {
while( (opt = getopt_long(argc, argv, "hva:p:i:d:s:onr",longopts,&optindex)) != -1 ) while( (opt = getopt_long(argc, argv, "hva:p:i:d:s:l:onrb",longopts,&optindex)) != -1 )
{ {
switch (opt) switch (opt)
{ {
...@@ -95,6 +102,14 @@ int main( int argc, char **argv ) ...@@ -95,6 +102,14 @@ int main( int argc, char **argv )
addr = string(optarg); addr = string(optarg);
break; break;
case 'l':
logname = string(optarg);
break;
case 'b':
cmdonly = 1;
break;
case 'p': case 'p':
port = uni_atoi(optarg); port = uni_atoi(optarg);
break; break;
...@@ -118,6 +133,7 @@ int main( int argc, char **argv ) ...@@ -118,6 +133,7 @@ int main( int argc, char **argv )
} }
LogReader lr; LogReader lr;
lr.setCommandOnlyMode(cmdonly);
if( !sdata.empty() ) if( !sdata.empty() )
{ {
...@@ -127,7 +143,7 @@ int main( int argc, char **argv ) ...@@ -127,7 +143,7 @@ int main( int argc, char **argv )
cout << "SEND COMMAND: '" << (LogServerTypes::Command)cmd << " data='" << sdata << "'" << endl; cout << "SEND COMMAND: '" << (LogServerTypes::Command)cmd << " data='" << sdata << "'" << endl;
} }
lr.readlogs( addr, port, (LogServerTypes::Command)cmd, data, verb ); lr.readlogs( addr, port, (LogServerTypes::Command)cmd, data, logname, verb );
} }
catch( SystemError& err ) catch( SystemError& err )
{ {
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "UniSetTypes.h" #include "UniSetTypes.h"
#include "Exceptions.h" #include "Exceptions.h"
#include "LogServer.h" #include "LogServer.h"
#include "LogAgregator.h"
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
using namespace UniSetTypes; using namespace UniSetTypes;
using namespace std; using namespace std;
...@@ -36,7 +37,6 @@ int main( int argc, char **argv ) ...@@ -36,7 +37,6 @@ int main( int argc, char **argv )
string addr("localhost"); string addr("localhost");
int port = 3333; int port = 3333;
int tout = 2000; int tout = 2000;
DebugStream dlog;
timeout_t delay = 5000; timeout_t delay = 5000;
try try
...@@ -78,21 +78,37 @@ int main( int argc, char **argv ) ...@@ -78,21 +78,37 @@ int main( int argc, char **argv )
// << " timeout=" << tout << " msec " // << " timeout=" << tout << " msec "
<< endl; << endl;
dlog.addLevel( Debug::type(Debug::CRIT | Debug::WARN | Debug::INFO) ); // dlog.addLevel( Debug::type(Debug::CRIT | Debug::WARN | Debug::INFO) );
} }
LogServer ls(dlog);
DebugStream dlog;
dlog.setLogName("dlog");
DebugStream dlog2;
dlog2.setLogName("dlog2");
LogAgregator la;
la.add(dlog);
la.add(dlog2);
LogServer ls(la);
// LogServer ls(cout); // LogServer ls(cout);
dlog.addLevel(Debug::ANY); dlog.addLevel(Debug::ANY);
dlog2.addLevel(Debug::ANY);
ls.run( addr, port, true ); ls.run( addr, port, true );
unsigned int i=0; unsigned int i=0;
while( true ) while( true )
{ {
dlog << "[" << ++i << "] Test message for log" << endl; dlog << "[" << ++i << "] Test message for log" << endl;
dlog.info() << ": INFO message" << endl; dlog.info() << ": dlog : INFO message" << endl;
dlog.warn() << ": WARN message" << endl; dlog.warn() << ": dlog : WARN message" << endl;
dlog.crit() << ": CRIT message" << endl; dlog.crit() << ": dlog : CRIT message" << endl;
dlog2.info() << ": dlog2: INFO message" << endl;
dlog2.warn() << ": dlog2: WARN message" << endl;
dlog2.crit() << ": dlog2: CRIT message" << endl;
msleep(delay); msleep(delay);
} }
......
...@@ -32,8 +32,7 @@ ...@@ -32,8 +32,7 @@
</Services> </Services>
</UniSet> </UniSet>
<dlog name="dlog"/> <dlog name="dlog"/>
<LogServer name="dlog" port="3333" host="localhost" /> <LogServer name="smplus" port="3333" host="localhost" />
<LogServer name="ulog" port="3335" host="localhost" />
<settings> <settings>
<TestProc name="TestProc1" <TestProc name="TestProc1"
......
...@@ -228,7 +228,7 @@ AC_CONFIG_FILES([Makefile ...@@ -228,7 +228,7 @@ AC_CONFIG_FILES([Makefile
src/Services/Makefile src/Services/Makefile
src/Timers/Makefile src/Timers/Makefile
src/Various/Makefile src/Various/Makefile
src/LogServer/Makefile src/Log/Makefile
src/Makefile src/Makefile
include/Makefile include/Makefile
include/modbus/Makefile include/modbus/Makefile
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#ifdef UNISET_ENABLE_IO #ifdef UNISET_ENABLE_IO
#include "IOControl.h" #include "IOControl.h"
#endif #endif
#include "LogAgregator.h"
#include "LogServer.h" #include "LogServer.h"
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
using namespace std; using namespace std;
...@@ -186,15 +187,13 @@ int main( int argc, const char **argv ) ...@@ -186,15 +187,13 @@ int main( int argc, const char **argv )
(*it)->start(); (*it)->start();
#endif #endif
if( run_logserver("ulog",ulog) == 0 ) LogAgregator la;
{ la.add(ulog);
ulog.crit() << "(smemory-plus): run logserver for 'ulog' FAILED" << endl; la.add(dlog);
return 1;
}
if( run_logserver("dlog",dlog) == 0 ) if( run_logserver("smplus",la) == 0 )
{ {
dlog.crit() << "(smemory-plus): run logserver for 'dlog' FAILED" << endl; cerr << "(smemory-plus): run logserver for 'smplus' FAILED" << endl;
return 1; return 1;
} }
......
...@@ -4,7 +4,6 @@ ulimit -Sc 10000000 ...@@ -4,7 +4,6 @@ ulimit -Sc 10000000
START=uniset2-start.sh START=uniset2-start.sh
${START} -f ./uniset2-smemory-plus --smemory-id SharedMemory --confile test.xml \ ${START} -f ./uniset2-smemory-plus --smemory-id SharedMemory --confile test.xml \
--dlog-add-levels any \
--io-name IOControl \ --io-name IOControl \
--io-polltime 100 \ --io-polltime 100 \
--io-s-filter-field io \ --io-s-filter-field io \
...@@ -31,7 +30,8 @@ ${START} -f ./uniset2-smemory-plus --smemory-id SharedMemory --confile test.xml ...@@ -31,7 +30,8 @@ ${START} -f ./uniset2-smemory-plus --smemory-id SharedMemory --confile test.xml
--mbtcp2-gateway-port 2049 \ --mbtcp2-gateway-port 2049 \
--mbtcp2-recv-timeout 200 \ --mbtcp2-recv-timeout 200 \
--mbtcp2-force-out 1 \ --mbtcp2-force-out 1 \
$* # --dlog-add-levels any \
# $*
# --add-rtu \ # --add-rtu \
# --rs-dev /dev/cbsideA1 \ # --rs-dev /dev/cbsideA1 \
# --rs-id RTUExchange \ # --rs-id RTUExchange \
......
...@@ -92,7 +92,7 @@ public: ...@@ -92,7 +92,7 @@ public:
DebugStream(char const * f, Debug::type t = Debug::NONE); DebugStream(char const * f, Debug::type t = Debug::NONE);
/// ///
~DebugStream(); virtual ~DebugStream();
typedef sigc::signal<void,const std::string&> StreamEvent_Signal; typedef sigc::signal<void,const std::string&> StreamEvent_Signal;
StreamEvent_Signal signal_stream_event(); StreamEvent_Signal signal_stream_event();
...@@ -118,7 +118,7 @@ public: ...@@ -118,7 +118,7 @@ public:
} }
/// Sets the debugstreams' logfile to f. /// Sets the debugstreams' logfile to f.
void logFile( const std::string& f ); virtual void logFile( const std::string& f );
inline std::string getLogFile(){ return fname; } inline std::string getLogFile(){ return fname; }
...@@ -199,24 +199,27 @@ public: ...@@ -199,24 +199,27 @@ public:
std::ostream& pos(int x, int y); std::ostream& pos(int x, int y);
const DebugStream &operator=(const DebugStream& r); const DebugStream &operator=(const DebugStream& r);
inline void setLogName( const std::string& n ){ logname = n; }
inline std::string getLogName(){ return logname; }
protected: protected:
void sbuf_overflow( const std::string& s ); void sbuf_overflow( const std::string& s );
private: // private:
/// The current debug level /// The current debug level
Debug::type dt; Debug::type dt;
/// The no-op stream. /// The no-op stream.
std::ostream nullstream; std::ostream nullstream;
/// ///
struct debugstream_internal; struct debugstream_internal;
struct debugstream_sbuf;
/// ///
debugstream_internal * internal; debugstream_internal * internal;
debugstream_sbuf * internal_sbuf;
bool show_datetime; bool show_datetime;
std::string fname; std::string fname;
StreamEvent_Signal s_stream; StreamEvent_Signal s_stream;
std::string logname;
}; };
#endif #endif
#ifndef LogAgregator_H_
#define LogAgregator_H_
// -------------------------------------------------------------------------
#include <string>
#include <list>
#include "DebugStream.h"
#include "LogServerTypes.h"
// -------------------------------------------------------------------------
class LogAgregator:
public DebugStream
{
public:
explicit LogAgregator( Debug::type t = Debug::NONE );
explicit LogAgregator( char const * f, Debug::type t = Debug::NONE );
virtual ~LogAgregator();
virtual void logFile( const std::string& f );
void add( DebugStream& log );
// Управление "подчинёнными" логами
void addLevel( const std::string& logname, Debug::type t );
void delLevel( const std::string& logname, Debug::type t );
void level( const std::string& logname, Debug::type t );
DebugStream* getLog( const std::string& logname );
protected:
void logOnEvent( const std::string& s );
private:
typedef std::list<DebugStream*> LogList;
LogList llst;
};
// -------------------------------------------------------------------------
#endif // LogAgregator_H_
// -------------------------------------------------------------------------
...@@ -15,10 +15,18 @@ class LogReader ...@@ -15,10 +15,18 @@ class LogReader
LogReader(); LogReader();
~LogReader(); ~LogReader();
void readlogs( const std::string& addr, ost::tpport_t port, LogServerTypes::Command c, int data, bool verbose = false ); void readlogs( const std::string& addr, ost::tpport_t port,
LogServerTypes::Command c = LogServerTypes::cmdNOP,
int data = 0,
const std::string& logname="",
bool verbose = false );
void readlogs( const std::string& addr, ost::tpport_t port, LogServerTypes::lsMessage& m, bool verbose = false );
bool isConnection(); bool isConnection();
inline void setCommandOnlyMode( bool s ){ cmdonly = s; }
protected: protected:
void connect( const std::string& addr, ost::tpport_t port, timeout_t tout=TIMEOUT_INF ); void connect( const std::string& addr, ost::tpport_t port, timeout_t tout=TIMEOUT_INF );
...@@ -29,6 +37,7 @@ class LogReader ...@@ -29,6 +37,7 @@ class LogReader
UTCPStream* tcp; UTCPStream* tcp;
std::string iaddr; std::string iaddr;
ost::tpport_t port; ost::tpport_t port;
bool cmdonly;
DebugStream rlog; DebugStream rlog;
}; };
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#define LogServerTypes_H_ #define LogServerTypes_H_
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
#include <ostream> #include <ostream>
#include <cstring>
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
namespace LogServerTypes namespace LogServerTypes
{ {
...@@ -23,14 +24,19 @@ namespace LogServerTypes ...@@ -23,14 +24,19 @@ namespace LogServerTypes
struct lsMessage struct lsMessage
{ {
lsMessage():magic(MAGICNUM),cmd(cmdNOP),data(0){} lsMessage():magic(MAGICNUM),cmd(cmdNOP),data(0){ std::memset(logname,0,sizeof(logname)); }
unsigned int magic; unsigned int magic;
Command cmd; Command cmd;
unsigned int data; unsigned int data;
static const size_t MAXLOGNAME = 20;
char logname[MAXLOGNAME+1]; // +1 reserverd for '\0'
void setLogName( const std::string& name );
// для команды 'cmdSetLogFile' // для команды 'cmdSetLogFile'
// static const short MAXLOGFILENAME = 100; // static const size_t MAXLOGFILENAME = 200;
// char logname[MAXLOGFILENAME]; // char logfile[MAXLOGFILENAME];
}__attribute__((packed)); }__attribute__((packed));
std::ostream& operator<<(std::ostream& os, lsMessage& m ); std::ostream& operator<<(std::ostream& os, lsMessage& m );
......
...@@ -22,4 +22,4 @@ libUniSet2_la_LIBADD = -lm \ ...@@ -22,4 +22,4 @@ libUniSet2_la_LIBADD = -lm \
$(top_builddir)/src/Services/libServices.la \ $(top_builddir)/src/Services/libServices.la \
$(top_builddir)/src/Timers/libTimers.la \ $(top_builddir)/src/Timers/libTimers.la \
$(top_builddir)/src/Various/libVarious.la \ $(top_builddir)/src/Various/libVarious.la \
$(top_builddir)/src/LogServer/libLogServer.la $(top_builddir)/src/Log/libLog.la
#ifndef DEBUGEXTBUF_H
#define DEBUGEXTBUF_H
// Created by Lars Gullik Bj�nnes // Created by Lars Gullik Bj�nnes
// Copyright 1999 Lars Gullik Bj�nnes (larsbj@lyx.org) // Copyright 1999 Lars Gullik Bj�nnes (larsbj@lyx.org)
// Released into the public domain. // Released into the public domain.
...@@ -30,7 +33,6 @@ ...@@ -30,7 +33,6 @@
#include <iomanip> #include <iomanip>
#include <time.h> #include <time.h>
#include <iomanip> #include <iomanip>
#include <sstream>
using std::ostream; using std::ostream;
using std::streambuf; using std::streambuf;
...@@ -238,7 +240,11 @@ public: ...@@ -238,7 +240,11 @@ public:
~stringsigbuf() ~stringsigbuf()
{ {
if( sb )
{
delete sb; delete sb;
sb = 0;
}
} }
/// ///
...@@ -304,267 +310,13 @@ private: ...@@ -304,267 +310,13 @@ private:
stringbuf* sb; stringbuf* sb;
UniSetTypes::uniset_rwmutex mut; UniSetTypes::uniset_rwmutex mut;
}; };
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
/// So that public parts of DebugStream does not need to know about filebuf /// So that public parts of DebugStream does not need to know about filebuf
struct DebugStream::debugstream_internal { struct DebugStream::debugstream_internal {
/// Used when logging to file. /// Used when logging to file.
filebuf fbuf; filebuf fbuf;
};
//--------------------------------------------------------------------------
struct DebugStream::debugstream_sbuf {
/// Used when logging to file.
stringsigbuf sbuf; stringsigbuf sbuf;
nullbuf nbuf;
}; };
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
/// Constructor, sets the debug level to t.
DebugStream::DebugStream(Debug::type t)
: ostream(new debugbuf(cerr.rdbuf())),
dt(t), nullstream(new nullbuf), internal(0),internal_sbuf(new debugstream_sbuf),
show_datetime(true),
fname("")
{
delete rdbuf(new teebuf(cerr.rdbuf(),&internal_sbuf->sbuf));
internal_sbuf->sbuf.signal_overflow().connect(sigc::mem_fun(*this, &DebugStream::sbuf_overflow));
}
//--------------------------------------------------------------------------
/// Constructor, sets the log file to f, and the debug level to t.
DebugStream::DebugStream(char const * f, Debug::type t)
: ostream(new debugbuf(cerr.rdbuf())),
dt(t), nullstream(new nullbuf),
internal(new debugstream_internal),internal_sbuf(new debugstream_sbuf),
show_datetime(true),
fname("")
{
internal->fbuf.open(f, ios::out|ios::app);
delete rdbuf(new threebuf(cerr.rdbuf(),
&internal->fbuf,&internal_sbuf->sbuf));
internal_sbuf->sbuf.signal_overflow().connect(sigc::mem_fun(*this, &DebugStream::sbuf_overflow));
}
//--------------------------------------------------------------------------
void DebugStream::sbuf_overflow( const std::string& s )
{
s_stream.emit(s);
}
//--------------------------------------------------------------------------
DebugStream::~DebugStream()
{
delete nullstream.rdbuf(0); // Without this we leak
delete rdbuf(0); // Without this we leak
delete internal;
delete internal_sbuf;
}
//--------------------------------------------------------------------------
const DebugStream& DebugStream::operator=( const DebugStream& r )
{
if( r == *this )
return *this;
dt = r.dt;
show_datetime = r.show_datetime;
fname = r.fname;
if( !r.fname.empty() )
logFile(fname);
return *this;
}
//--------------------------------------------------------------------------
/// Sets the debugstreams' logfile to f.
void DebugStream::logFile( const std::string& f )
{
fname = f;
if (internal) {
internal->fbuf.close();
} else {
internal = new debugstream_internal;
}
if( !internal_sbuf ) {
internal_sbuf = new debugstream_sbuf;
}
if( !f.empty() )
{
internal->fbuf.open(f.c_str(), ios::out|ios::app);
delete rdbuf(new threebuf(cerr.rdbuf(),
&internal->fbuf,&internal_sbuf->sbuf));
}
else
delete rdbuf(new teebuf(cerr.rdbuf(),&internal_sbuf->sbuf));
}
//--------------------------------------------------------------------------
std::ostream & DebugStream::debug(Debug::type t)
{
if(dt & t)
{
if( show_datetime )
printDateTime(t);
*this << "(" << std::setfill(' ') << std::setw(6) << t << "): "; // "):\t";
return *this;
}
return nullstream;
}
//--------------------------------------------------------------------------
std::ostream& DebugStream::operator()(Debug::type t)
{
if(dt & t)
return *this;
return nullstream;
}
//--------------------------------------------------------------------------
std::ostream& DebugStream::printDate(Debug::type t, char brk)
{
if(dt && t)
{
time_t GMTime = time(NULL);
struct tm *tms = localtime(&GMTime);
return *this << std::setw(2) << std::setfill('0') << tms->tm_mday << brk
<< std::setw(2) << std::setfill('0') << tms->tm_mon+1 << brk
<< std::setw(4) << std::setfill('0') << tms->tm_year+1900;
}
return nullstream;
}
//--------------------------------------------------------------------------
std::ostream& DebugStream::printTime(Debug::type t, char brk)
{
if(dt && t)
{
time_t GMTime = time(NULL);
struct tm *tms = localtime(&GMTime);
return *this << std::setw(2) << std::setfill('0') << tms->tm_hour << brk
<< std::setw(2) << std::setfill('0') << tms->tm_min << brk
<< std::setw(2) << std::setfill('0') << tms->tm_sec;
}
return nullstream;
}
//--------------------------------------------------------------------------
std::ostream& DebugStream::printDateTime(Debug::type t)
{
if(dt & t)
{
time_t GMTime = time(NULL);
struct tm *tms = localtime(&GMTime);
return *this << std::setw(2) << std::setfill('0') << tms->tm_mday << "/"
<< std::setw(2) << std::setfill('0') << tms->tm_mon+1 << "/"
<< std::setw(4) << std::setfill('0') << tms->tm_year+1900 << " "
<< std::setw(2) << std::setfill('0') << tms->tm_hour << ":"
<< std::setw(2) << std::setfill('0') << tms->tm_min << ":"
<< std::setw(2) << std::setfill('0') << tms->tm_sec;
}
return nullstream;
}
//--------------------------------------------------------------------------
std::ostream& DebugStream::pos(int x, int y)
{
if( !dt )
return nullstream;
return *this << "\033[" << y << ";" << x << "f";
}
//--------------------------------------------------------------------------
DebugStream::StreamEvent_Signal DebugStream::signal_stream_event()
{
return s_stream;
}
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
#ifdef TEST_DEBUGSTREAM
// Example debug stream
DebugStream debugstream;
int main(int, char **)
{
/**
I have been running some tests on this to see how much overhead
this kind of permanent debug code has. My conclusion is: not
much. In all, but the most time critical code, this will have
close to no impact at all.
In the tests that I have run the use of
if (debugstream.debugging(DebugStream::INFO))
debugstream << "some debug\n";
has close to no overhead when the debug level is not
DebugStream::INFO.
The overhead for
debugstream.debug(DebugStream::INFO) << "some debug\n";
is also very small when the debug level is not
DebugStream::INFO. However the overhead for this will increase
if complex debugging information is output.
The overhead when the debug level is DebugStream::INFO can be
significant, but since we then are running in debug mode it is
of no concern.
Why should we use this instead of the class Error that we already
have? First of all it uses C++ iostream and constructs, secondly
it will be a lot easier to output the debug info that we need
without a lot of manual conversions, thirdly we can now use
iomanipulators and the complete iostream formatting functions.
pluss it will work for all types that have a operator<<
defined, and can be used in functors that take a ostream & as
parameter. And there should be less need for temporary objects.
And one nice bonus is that we get a log file almost for
free.
Some of the names are of course open to modifications. I will try
to use the names we already use in LyX.
*/
// Just a few simple debugs to show how it can work.
debugstream << "Debug level set to Debug::NONE\n";
if (debugstream.debugging()) {
debugstream << "Something must be debugged\n";
}
debugstream.debug(Debug::WARN) << "more debug(WARN)\n";
debugstream.debug(Debug::INFO) << "even more debug(INFO)\n";
debugstream.debug(Debug::CRIT) << "even more debug(CRIT)\n";
debugstream.level(Debug::value("INFO"));
debugstream << "Setting debug level to Debug::INFO\n";
if (debugstream.debugging()) {
debugstream << "Something must be debugged\n";
}
debugstream.debug(Debug::WARN) << "more debug(WARN)\n";
debugstream.debug(Debug::INFO) << "even more debug(INFO)\n";
debugstream.debug(Debug::CRIT) << "even more debug(CRIT)\n";
debugstream.addLevel(Debug::type(Debug::CRIT |
Debug::WARN));
debugstream << "Adding Debug::CRIT and Debug::WARN\n";
debugstream[Debug::WARN] << "more debug(WARN)\n";
debugstream[Debug::INFO] << "even more debug(INFO)\n";
debugstream[Debug::CRIT] << "even more debug(CRIT)\n";
debugstream.delLevel(Debug::INFO);
debugstream << "Removing Debug::INFO\n";
debugstream[Debug::WARN] << "more debug(WARN)\n";
debugstream[Debug::INFO] << "even more debug(INFO)\n";
debugstream[Debug::CRIT] << "even more debug(CRIT)\n";
debugstream.logFile("logfile");
debugstream << "Setting logfile to \"logfile\"\n";
debugstream << "Value: " << 123 << " " << "12\n";
int i = 0;
int * p = new int;
// note: the (void*) is needed on g++ 2.7.x since it does not
// support partial specialization. In egcs this should not be
// needed.
debugstream << "automatic " << &i
<< ", free store " << p << endl;
delete p;
/*
for (int j = 0; j < 200000; ++j) {
DebugStream tmp;
tmp << "Test" << endl;
}
*/
}
#endif #endif
\ No newline at end of file
// Created by Lars Gullik Bj�nnes
// Copyright 1999 Lars Gullik Bj�nnes (larsbj@lyx.org)
// Released into the public domain.
// Primarily developed for use in the LyX Project http://www.lyx.org/
// but should be adaptable to any project.
// (c) 2002 adapted for UniSet by Lav, GNU GPL license
//#define TEST_DEBUGSTREAM
#ifdef __GNUG__
#pragma implementation
#endif
//#include "DebugStream.h"
#include "Debug.h"
#include "Mutex.h"
//�Since the current C++ lib in egcs does not have a standard implementation
// of basic_streambuf and basic_filebuf we don't have to include this
// header.
//#define MODERN_STL_STREAMS
#ifdef MODERN_STL_STREAMS
#include <fstream>
#endif
#include <iostream>
#include <sstream>
#include <iomanip>
#include <time.h>
#include <iomanip>
#include "DebugExtBuf.h"
using std::ostream;
using std::streambuf;
using std::streamsize;
using std::filebuf;
using std::stringbuf;
using std::cerr;
using std::ios;
//--------------------------------------------------------------------------
/// Constructor, sets the debug level to t.
DebugStream::DebugStream(Debug::type t)
: ostream(new debugbuf(cerr.rdbuf())),
dt(t), nullstream(new nullbuf), internal(new debugstream_internal),
show_datetime(true),
fname(""),
logname("")
{
delete rdbuf(new teebuf(cerr.rdbuf(),&internal->sbuf));
internal->sbuf.signal_overflow().connect(sigc::mem_fun(*this, &DebugStream::sbuf_overflow));
}
//--------------------------------------------------------------------------
/// Constructor, sets the log file to f, and the debug level to t.
DebugStream::DebugStream(char const * f, Debug::type t)
: ostream(new debugbuf(cerr.rdbuf())),
dt(t), nullstream(new nullbuf),
internal(new debugstream_internal),
show_datetime(true),
fname(""),
logname("")
{
internal->fbuf.open(f, ios::out|ios::app);
delete rdbuf(new threebuf(cerr.rdbuf(),
&internal->fbuf,&internal->sbuf));
internal->sbuf.signal_overflow().connect(sigc::mem_fun(*this, &DebugStream::sbuf_overflow));
}
//--------------------------------------------------------------------------
void DebugStream::sbuf_overflow( const std::string& s )
{
s_stream.emit(s);
}
//--------------------------------------------------------------------------
DebugStream::~DebugStream()
{
delete nullstream.rdbuf(0); // Without this we leak
delete rdbuf(0); // Without this we leak
delete internal;
}
//--------------------------------------------------------------------------
const DebugStream& DebugStream::operator=( const DebugStream& r )
{
if( r == *this )
return *this;
dt = r.dt;
show_datetime = r.show_datetime;
fname = r.fname;
if( !r.fname.empty() )
logFile(fname);
// s_stream = r.s_stream;
return *this;
}
//--------------------------------------------------------------------------
/// Sets the debugstreams' logfile to f.
void DebugStream::logFile( const std::string& f )
{
fname = f;
if( internal ) {
internal->fbuf.close();
} else {
internal = new debugstream_internal;
}
if( !f.empty() )
{
internal->fbuf.open(f.c_str(), ios::out|ios::app);
delete rdbuf(new threebuf(cerr.rdbuf(),
&internal->fbuf,&internal->sbuf));
}
else
delete rdbuf(new teebuf(cerr.rdbuf(),&internal->sbuf));
}
//--------------------------------------------------------------------------
std::ostream & DebugStream::debug(Debug::type t)
{
if(dt & t)
{
if( show_datetime )
printDateTime(t);
*this << "(" << std::setfill(' ') << std::setw(6) << t << "): "; // "):\t";
return *this;
}
return nullstream;
}
//--------------------------------------------------------------------------
std::ostream& DebugStream::operator()(Debug::type t)
{
if(dt & t)
return *this;
return nullstream;
}
//--------------------------------------------------------------------------
std::ostream& DebugStream::printDate(Debug::type t, char brk)
{
if(dt && t)
{
time_t GMTime = time(NULL);
struct tm *tms = localtime(&GMTime);
return *this << std::setw(2) << std::setfill('0') << tms->tm_mday << brk
<< std::setw(2) << std::setfill('0') << tms->tm_mon+1 << brk
<< std::setw(4) << std::setfill('0') << tms->tm_year+1900;
}
return nullstream;
}
//--------------------------------------------------------------------------
std::ostream& DebugStream::printTime(Debug::type t, char brk)
{
if(dt && t)
{
time_t GMTime = time(NULL);
struct tm *tms = localtime(&GMTime);
return *this << std::setw(2) << std::setfill('0') << tms->tm_hour << brk
<< std::setw(2) << std::setfill('0') << tms->tm_min << brk
<< std::setw(2) << std::setfill('0') << tms->tm_sec;
}
return nullstream;
}
//--------------------------------------------------------------------------
std::ostream& DebugStream::printDateTime(Debug::type t)
{
if(dt & t)
{
time_t GMTime = time(NULL);
struct tm *tms = localtime(&GMTime);
return *this << std::setw(2) << std::setfill('0') << tms->tm_mday << "/"
<< std::setw(2) << std::setfill('0') << tms->tm_mon+1 << "/"
<< std::setw(4) << std::setfill('0') << tms->tm_year+1900 << " "
<< std::setw(2) << std::setfill('0') << tms->tm_hour << ":"
<< std::setw(2) << std::setfill('0') << tms->tm_min << ":"
<< std::setw(2) << std::setfill('0') << tms->tm_sec;
}
return nullstream;
}
//--------------------------------------------------------------------------
std::ostream& DebugStream::pos(int x, int y)
{
if( !dt )
return nullstream;
return *this << "\033[" << y << ";" << x << "f";
}
//--------------------------------------------------------------------------
DebugStream::StreamEvent_Signal DebugStream::signal_stream_event()
{
return s_stream;
}
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
#ifdef TEST_DEBUGSTREAM
// Example debug stream
DebugStream debugstream;
int main(int, char **)
{
/**
I have been running some tests on this to see how much overhead
this kind of permanent debug code has. My conclusion is: not
much. In all, but the most time critical code, this will have
close to no impact at all.
In the tests that I have run the use of
if (debugstream.debugging(DebugStream::INFO))
debugstream << "some debug\n";
has close to no overhead when the debug level is not
DebugStream::INFO.
The overhead for
debugstream.debug(DebugStream::INFO) << "some debug\n";
is also very small when the debug level is not
DebugStream::INFO. However the overhead for this will increase
if complex debugging information is output.
The overhead when the debug level is DebugStream::INFO can be
significant, but since we then are running in debug mode it is
of no concern.
Why should we use this instead of the class Error that we already
have? First of all it uses C++ iostream and constructs, secondly
it will be a lot easier to output the debug info that we need
without a lot of manual conversions, thirdly we can now use
iomanipulators and the complete iostream formatting functions.
pluss it will work for all types that have a operator<<
defined, and can be used in functors that take a ostream & as
parameter. And there should be less need for temporary objects.
And one nice bonus is that we get a log file almost for
free.
Some of the names are of course open to modifications. I will try
to use the names we already use in LyX.
*/
// Just a few simple debugs to show how it can work.
debugstream << "Debug level set to Debug::NONE\n";
if (debugstream.debugging()) {
debugstream << "Something must be debugged\n";
}
debugstream.debug(Debug::WARN) << "more debug(WARN)\n";
debugstream.debug(Debug::INFO) << "even more debug(INFO)\n";
debugstream.debug(Debug::CRIT) << "even more debug(CRIT)\n";
debugstream.level(Debug::value("INFO"));
debugstream << "Setting debug level to Debug::INFO\n";
if (debugstream.debugging()) {
debugstream << "Something must be debugged\n";
}
debugstream.debug(Debug::WARN) << "more debug(WARN)\n";
debugstream.debug(Debug::INFO) << "even more debug(INFO)\n";
debugstream.debug(Debug::CRIT) << "even more debug(CRIT)\n";
debugstream.addLevel(Debug::type(Debug::CRIT |
Debug::WARN));
debugstream << "Adding Debug::CRIT and Debug::WARN\n";
debugstream[Debug::WARN] << "more debug(WARN)\n";
debugstream[Debug::INFO] << "even more debug(INFO)\n";
debugstream[Debug::CRIT] << "even more debug(CRIT)\n";
debugstream.delLevel(Debug::INFO);
debugstream << "Removing Debug::INFO\n";
debugstream[Debug::WARN] << "more debug(WARN)\n";
debugstream[Debug::INFO] << "even more debug(INFO)\n";
debugstream[Debug::CRIT] << "even more debug(CRIT)\n";
debugstream.logFile("logfile");
debugstream << "Setting logfile to \"logfile\"\n";
debugstream << "Value: " << 123 << " " << "12\n";
int i = 0;
int * p = new int;
// note: the (void*) is needed on g++ 2.7.x since it does not
// support partial specialization. In egcs this should not be
// needed.
debugstream << "automatic " << &i
<< ", free store " << p << endl;
delete p;
/*
for (int j = 0; j < 200000; ++j) {
DebugStream tmp;
tmp << "Test" << endl;
}
*/
}
#endif
#include "DebugExtBuf.h"
#include "LogAgregator.h"
// -------------------------------------------------------------------------
LogAgregator::LogAgregator( char const * f, Debug::type t ):
DebugStream(f,t)
{
delete rdbuf(new teebuf(&internal->fbuf,&internal->sbuf));
}
// -------------------------------------------------------------------------
LogAgregator::LogAgregator( Debug::type t ):
DebugStream(t)
{
delete rdbuf(new teebuf(&internal->nbuf,&internal->sbuf));
}
// -------------------------------------------------------------------------
void LogAgregator::logFile( const std::string& f )
{
DebugStream::logFile(f);
if( f.empty() )
delete rdbuf(new teebuf(&internal->fbuf,&internal->sbuf));
else
delete rdbuf(new teebuf(&internal->nbuf,&internal->sbuf));
}
// -------------------------------------------------------------------------
LogAgregator::~LogAgregator()
{
}
// -------------------------------------------------------------------------
void LogAgregator::logOnEvent( const std::string& s )
{
(*this) << s;
}
// -------------------------------------------------------------------------
void LogAgregator::add( DebugStream& l )
{
l.signal_stream_event().connect( sigc::mem_fun(this, &LogAgregator::logOnEvent) );
for( LogList::iterator i=llst.begin(); i!=llst.end(); i++ )
{
if( &l == (*i) )
return;
}
llst.push_back(&l);
}
// -------------------------------------------------------------------------
void LogAgregator::addLevel( const std::string& logname, Debug::type t )
{
for( auto& i: llst )
{
if( i->getLogName() == logname )
{
i->addLevel(t);
break;
}
}
}
// -------------------------------------------------------------------------
void LogAgregator::delLevel( const std::string& logname, Debug::type t )
{
for( auto& i: llst )
{
if( i->getLogName() == logname )
{
i->delLevel(t);
break;
}
}
}
// -------------------------------------------------------------------------
void LogAgregator::level( const std::string& logname, Debug::type t )
{
for( auto& i: llst )
{
if( i->getLogName() == logname )
{
i->level(t);
break;
}
}
}
// -------------------------------------------------------------------------
DebugStream* LogAgregator::getLog( const std::string& logname )
{
if( logname.empty() )
return 0;
for( auto& i: llst )
{
if( i->getLogName() == logname )
return i;
}
return 0;
}
// -------------------------------------------------------------------------
\ No newline at end of file
...@@ -11,7 +11,8 @@ using namespace UniSetTypes; ...@@ -11,7 +11,8 @@ using namespace UniSetTypes;
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
LogReader::LogReader(): LogReader::LogReader():
tcp(0), tcp(0),
iaddr("") iaddr(""),
cmdonly(false)
{ {
} }
...@@ -102,7 +103,16 @@ bool LogReader::isConnection() ...@@ -102,7 +103,16 @@ bool LogReader::isConnection()
return tcp && tcp->isConnected(); return tcp && tcp->isConnected();
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void LogReader::readlogs( const std::string& _addr, ost::tpport_t _port, LogServerTypes::Command cmd, int data, bool verbose ) void LogReader::readlogs( const std::string& _addr, ost::tpport_t _port, LogServerTypes::Command cmd, int data, const std::string& logname, bool verbose )
{
LogServerTypes::lsMessage msg;
msg.cmd = cmd;
msg.data = data;
msg.setLogName(logname);
readlogs(_addr,_port,msg,verbose );
}
// -------------------------------------------------------------------------
void LogReader::readlogs( const std::string& _addr, ost::tpport_t _port, LogServerTypes::lsMessage& msg, bool verbose )
{ {
timeout_t inTimeout = 10000; timeout_t inTimeout = 10000;
timeout_t outTimeout = 6000; timeout_t outTimeout = 6000;
...@@ -126,15 +136,15 @@ void LogReader::readlogs( const std::string& _addr, ost::tpport_t _port, LogServ ...@@ -126,15 +136,15 @@ void LogReader::readlogs( const std::string& _addr, ost::tpport_t _port, LogServ
continue; continue;
} }
if( !send_ok && cmd != LogServerTypes::cmdNOP ) if( !send_ok && msg.cmd != LogServerTypes::cmdNOP )
{ {
if( tcp->isPending(ost::Socket::pendingOutput,outTimeout) ) if( tcp->isPending(ost::Socket::pendingOutput,outTimeout) )
{ {
rlog.info() << "** send command: '" << cmd << "' data='" << data << "'" << endl; rlog.info() << "** send command: logname='" << msg.logname << "' cmd='" << msg.cmd << "' data='" << msg.data << "'" << endl;
LogServerTypes::lsMessage msg; // LogServerTypes::lsMessage msg;
msg.cmd = cmd; // msg.cmd = cmd;
msg.data = data; // msg.data = data;
for( size_t i=0; i<sizeof(msg); i++ ) for( size_t i=0; i<sizeof(msg); i++ )
(*tcp) << ((unsigned char*)(&msg))[i]; (*tcp) << ((unsigned char*)(&msg))[i];
...@@ -142,10 +152,13 @@ void LogReader::readlogs( const std::string& _addr, ost::tpport_t _port, LogServ ...@@ -142,10 +152,13 @@ void LogReader::readlogs( const std::string& _addr, ost::tpport_t _port, LogServ
send_ok = true; send_ok = true;
} }
else else
rlog.warn() << "**** SEND COMMAND ('" << cmd << "' FAILED!" << endl; rlog.warn() << "**** SEND COMMAND ('" << msg.cmd << "' FAILED!" << endl;
if( cmdonly )
return;
} }
while( tcp->isPending(ost::Socket::pendingInput,inTimeout) ) while( !cmdonly && tcp->isPending(ost::Socket::pendingInput,inTimeout) )
{ {
int n = tcp->peek( buf,sizeof(buf)-1 ); int n = tcp->peek( buf,sizeof(buf)-1 );
if( n > 0 ) if( n > 0 )
......
...@@ -37,3 +37,10 @@ std::ostream& LogServerTypes::operator<<(std::ostream& os, LogServerTypes::lsMes ...@@ -37,3 +37,10 @@ std::ostream& LogServerTypes::operator<<(std::ostream& os, LogServerTypes::lsMes
return os << " magic=" << m.magic << " cmd=" << m.cmd << " data=" << m.data; return os << " magic=" << m.magic << " cmd=" << m.cmd << " data=" << m.data;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void LogServerTypes::lsMessage::setLogName( const std::string& name )
{
size_t s = name.size()> MAXLOGNAME ? MAXLOGNAME : name.size();
memcpy( &logname, name.c_str(), s );
logname[s] = '\0';
}
// -------------------------------------------------------------------------
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "LogSession.h" #include "LogSession.h"
#include "UniSetTypes.h" #include "UniSetTypes.h"
#include "LogServerTypes.h" #include "LogServerTypes.h"
#include "LogAgregator.h"
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
using namespace std; using namespace std;
using namespace UniSetTypes; using namespace UniSetTypes;
...@@ -82,40 +83,52 @@ void LogSession::run() ...@@ -82,40 +83,52 @@ void LogSession::run()
{ {
slog.info() << peername << "(run): receive command: '" << msg.cmd << "'" << endl; slog.info() << peername << "(run): receive command: '" << msg.cmd << "'" << endl;
string cmdLogName(msg.logname);
DebugStream* cmdlog = 0;
if( !cmdLogName.empty () )
{
LogAgregator* lag = dynamic_cast<LogAgregator*>(log);
cmdlog = lag ? lag->getLog( cmdLogName ) : log;
}
// обрабатываем команды только если нашли log
if( cmdlog )
{
// Обработка команд.. // Обработка команд..
// \warning Работа с логом ведётся без mutex-а, хотя он разделяется отдельными потоками // \warning Работа с логом ведётся без mutex-а, хотя он разделяется отдельными потоками
switch( msg.cmd ) switch( msg.cmd )
{ {
case LogServerTypes::cmdSetLevel: case LogServerTypes::cmdSetLevel:
log->level( (Debug::type)msg.data ); cmdlog->level( (Debug::type)msg.data );
break; break;
case LogServerTypes::cmdAddLevel: case LogServerTypes::cmdAddLevel:
log->addLevel((Debug::type)msg.data ); cmdlog->addLevel((Debug::type)msg.data );
break; break;
case LogServerTypes::cmdDelLevel: case LogServerTypes::cmdDelLevel:
log->delLevel( (Debug::type)msg.data ); cmdlog->delLevel( (Debug::type)msg.data );
break; break;
case LogServerTypes::cmdRotate: case LogServerTypes::cmdRotate:
{ {
string lfile( log->getLogFile() ); string lfile( cmdlog->getLogFile() );
if( !lfile.empty() ) if( !lfile.empty() )
log->logFile(lfile); cmdlog->logFile(lfile);
} }
break; break;
case LogServerTypes::cmdOffLogFile: case LogServerTypes::cmdOffLogFile:
{ {
string lfile( log->getLogFile() ); string lfile( cmdlog->getLogFile() );
if( !lfile.empty() ) if( !lfile.empty() )
log->logFile(""); cmdlog->logFile("");
} }
break; break;
case LogServerTypes::cmdOnLogFile: case LogServerTypes::cmdOnLogFile:
{ {
if( !oldLogFile.empty() && oldLogFile != log->getLogFile() ) if( !oldLogFile.empty() && oldLogFile != cmdlog->getLogFile() )
log->logFile(oldLogFile); cmdlog->logFile(oldLogFile);
} }
break; break;
...@@ -126,6 +139,7 @@ void LogSession::run() ...@@ -126,6 +139,7 @@ void LogSession::run()
} }
} }
} }
}
cancelled = false; cancelled = false;
while( !cancelled && !ptSessionTimeout.checkTime() ) while( !cancelled && !ptSessionTimeout.checkTime() )
......
############################################################################
# This file is part of the UniSet library #
############################################################################
noinst_LTLIBRARIES = libLog.la
libLog_la_CPPFLAGS = $(SIGC_CFLAGS) $(COMCPP_CFLAGS)
libLog_la_LIBADD = $(SIGC_LIBS) $(COMCPP_LIBS)
libLog_la_SOURCES = DebugStream.cc Debug.cc LogServerTypes.cc LogServer.cc LogSession.cc LogReader.cc LogAgregator.cc
############################################################################
# This file is part of the UniSet library #
############################################################################
noinst_LTLIBRARIES = libLogServer.la
libLogServer_la_CPPFLAGS = $(SIGC_CFLAGS) $(COMCPP_CFLAGS)
libLogServer_la_LIBADD = $(SIGC_LIBS) $(COMCPP_LIBS)
libLogServer_la_SOURCES = LogServerTypes.cc LogServer.cc LogSession.cc LogReader.cc
...@@ -2,5 +2,5 @@ ...@@ -2,5 +2,5 @@
# This file is part of the UniSet library # # This file is part of the UniSet library #
############################################################################ ############################################################################
SUBDIRS=ObjectRepository Processes Interfaces Timers Services Various Communications LogServer SUBDIRS=ObjectRepository Processes Interfaces Timers Services Various Communications Log
...@@ -701,7 +701,10 @@ xmlNode* Configuration::initDebug( DebugStream& deb, const string& _debname ) ...@@ -701,7 +701,10 @@ xmlNode* Configuration::initDebug( DebugStream& deb, const string& _debname )
else else
{ {
if( !getProp(dnode,"name").empty() ) if( !getProp(dnode,"name").empty() )
{
debname = getProp(dnode,"name"); debname = getProp(dnode,"name");
deb.setLogName(debname);
}
} }
string no_deb("--"+debname+"-no-debug"); string no_deb("--"+debname+"-no-debug");
...@@ -978,6 +981,7 @@ UniversalIO::IOType Configuration::getIOType( const std::string& name ) ...@@ -978,6 +981,7 @@ UniversalIO::IOType Configuration::getIOType( const std::string& name )
void uniset_init( int argc, const char* const* argv, const std::string& xmlfile ) void uniset_init( int argc, const char* const* argv, const std::string& xmlfile )
{ {
string confile = UniSetTypes::getArgParam( "--confile", argc, argv, xmlfile ); string confile = UniSetTypes::getArgParam( "--confile", argc, argv, xmlfile );
ulog.setLogName("ulog");
UniSetTypes::conf = new Configuration(argc, argv, confile); UniSetTypes::conf = new Configuration(argc, argv, confile);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
noinst_LTLIBRARIES = libVarious.la noinst_LTLIBRARIES = libVarious.la
libVarious_la_CPPFLAGS = $(SIGC_CFLAGS) $(COMCPP_CFLAGS) libVarious_la_CPPFLAGS = $(SIGC_CFLAGS) $(COMCPP_CFLAGS)
libVarious_la_LIBADD = $(SIGC_LIBS) $(COMCPP_LIBS) libVarious_la_LIBADD = $(SIGC_LIBS) $(COMCPP_LIBS)
libVarious_la_SOURCES = DebugStream.cc Debug.cc UniXML.cc MessageType.cc Configuration.cc \ libVarious_la_SOURCES = UniXML.cc MessageType.cc Configuration.cc \
Restorer_XML.cc RunLock.cc Mutex.cc SViewer.cc SMonitor.cc LT_Object.cc WDTInterface.cc Restorer_XML.cc RunLock.cc Mutex.cc SViewer.cc SMonitor.cc LT_Object.cc WDTInterface.cc
local-clean: local-clean:
......
#include <time.h> #include <time.h>
#include "Debug.h" #include "Debug.h"
#include "UniSetTypes.h" #include "UniSetTypes.h"
#include "LogAgregator.h"
using namespace std; using namespace std;
using namespace UniSetTypes; using namespace UniSetTypes;
std::ostringstream ss; std::ostringstream ss;
std::ostringstream ss1;
void check_log_signal( const string& s ) void check_log_signal( const string& s )
{ {
ss << s; ss << s;
} }
void check_alog_signal( const string& s )
{
ss1 << s;
}
int main( int argc, const char **argv ) int main( int argc, const char **argv )
{ {
DebugStream tlog; DebugStream tlog;
...@@ -30,9 +37,31 @@ int main( int argc, const char **argv ) ...@@ -30,9 +37,31 @@ int main( int argc, const char **argv )
if( tlog.is_level1() ) if( tlog.is_level1() )
tlog.level1() << ": is level1..." << endl; tlog.level1() << ": is level1..." << endl;
cout << "==================" << endl; cout << "===== Test 1 =====" << endl;
cout << ss.str(); cout << ss.str();
cout << "==================" << endl; cout << "==================" << endl;
DebugStream log1;
log1.setLogName("log1");
DebugStream log2;
log2.setLogName("log2");
LogAgregator la;
la.signal_stream_event().connect(&check_alog_signal);
la.add(log1);
la.add(log2);
log1 << "log1: test message..." << endl;
log2 << "log2: test message..." << endl;
la << "la: test message.." << endl;
cout << "===== Test 2 =====" << endl;
cout << ss1.str();
cout << "==================" << endl;
DebugStream* l = la.getLog("log1");
if( l != &log1 )
cout << "**** TEST FAILED: LogAgregator::getLog() " << endl;
return 0; return 0;
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment