From 96b00553a0ffe6bb34af6ad15e1cfc2bed67bd75 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Wed, 3 May 2006 06:49:30 +0000 Subject: Added a simple test for the log system, and switched the multilog to the new singleton system, which unfortunately changed it's API slightly. Now it's not a pointer from the singleton, but I did add a new macro to make most usage of it even easier. --- src/connectionmanager.cpp | 32 ++++++++++++++++---------------- src/connectionmanager.h | 2 +- src/hashtable.cpp | 1 - src/multilog.cpp | 40 ++-------------------------------------- src/multilog.h | 31 ++++++++----------------------- src/multilogtext.cpp | 40 ++++++++++++++++++++++++++++++++++++++-- src/multilogtext.h | 2 +- src/programchain.cpp | 25 ++++--------------------- src/programchain.h | 2 +- src/singleton.h | 13 +++++++++++++ src/test/log.cpp | 33 +++++++++++++++++++++++++++++++++ 11 files changed, 117 insertions(+), 104 deletions(-) create mode 100644 src/test/log.cpp (limited to 'src') diff --git a/src/connectionmanager.cpp b/src/connectionmanager.cpp index 36ff961..ded5aa4 100644 --- a/src/connectionmanager.cpp +++ b/src/connectionmanager.cpp @@ -13,9 +13,9 @@ #include "connectionmanager.h" #include -ConnectionManager::ConnectionManager() +ConnectionManager::ConnectionManager() : + xLog( MultiLog::getInstance() ) { - pLog = MultiLog::getLog(); nMasterSocket = -1; pMonitor = NULL; } @@ -42,7 +42,7 @@ bool ConnectionManager::startServer( int nPort, int nInitPool ) nMasterSocket = socket (PF_INET, SOCK_STREAM, 0); if (nMasterSocket < 0) { - pLog->LineLog( MultiLog::LError, "Couldn't create a listen socket."); + xLog.LineLog( MultiLog::LError, "Couldn't create a listen socket."); return false; } @@ -59,13 +59,13 @@ bool ConnectionManager::startServer( int nPort, int nInitPool ) if (bind (nMasterSocket, (struct sockaddr *) &name, sizeof (name)) < 0) { - pLog->LineLog( MultiLog::LError, "Couldn't bind to the listen socket."); + xLog.LineLog( MultiLog::LError, "Couldn't bind to the listen socket."); return false; } if (listen (nMasterSocket, 1) < 0) { - pLog->LineLog( MultiLog::LError, "Couldn't begin listening to the server socket."); + xLog.LineLog( MultiLog::LError, "Couldn't begin listening to the server socket."); return false; } @@ -90,18 +90,18 @@ bool ConnectionManager::startServer( int nPort, int nInitPool, int nNumTries, in for( int j = 0; j < nNumTries; j++ ) { - pLog->LineLog( MultiLog::LStatus, "Attempting to create server socket (attempt [%d/%d])...", j+1, nNumTries ); + xLog.LineLog( MultiLog::LStatus, "Attempting to create server socket (attempt [%d/%d])...", j+1, nNumTries ); if( startServer( nPort, nInitPool ) == true ) { return true; } else if( j < nNumTries-1 ) { - pLog->LineLog( MultiLog::LStatus, "Waiting for %d secconds to allow port to clear...", nTimeout ); + xLog.LineLog( MultiLog::LStatus, "Waiting for %d secconds to allow port to clear...", nTimeout ); xTimeout.tv_sec = nTimeout; xTimeout.tv_usec = 0; if (select(0, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0, &xTimeout) < 0) { - pLog->LineLog( MultiLog::LError, "Error using select to sleep for a while."); + xLog.LineLog( MultiLog::LError, "Error using select to sleep for a while."); } usleep( nTimeout ); } @@ -127,7 +127,7 @@ bool ConnectionManager::scanConnections( int nTimeout, bool bForceTimeout ) // if there are ANY connections there... if( TEMP_FAILURE_RETRY( select( FD_SETSIZE, &fdRead, (fd_set *)0/*&fdWrite*/, &fdException, &xTimeout ) ) < 0 ) { - pLog->LineLog( MultiLog::LError, "Error attempting to scan open connections."); + xLog.LineLog( MultiLog::LError, "Error attempting to scan open connections."); perror("ConnectionManager"); return false; } @@ -137,7 +137,7 @@ bool ConnectionManager::scanConnections( int nTimeout, bool bForceTimeout ) if( bForceTimeout ) { if (select(0, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0, &xTimeout) < 0) { - pLog->LineLog( MultiLog::LError, "Error using select to sleep for a while."); + xLog.LineLog( MultiLog::LError, "Error using select to sleep for a while."); } } @@ -155,14 +155,14 @@ bool ConnectionManager::scanConnections( int nTimeout, bool bForceTimeout ) Connection *pCon = findActiveConnection( i ); if( pCon == NULL ) { - pLog->LineLog( MultiLog::LError, "A connection object was lost, or never created!"); + xLog.LineLog( MultiLog::LError, "A connection object was lost, or never created!"); return false; } /* Data arriving on an already-connected socket. */ if( pCon->readInput() != true ) { - pLog->LineLog( MultiLog::LStatus, "Closing connection due to disconnect."); + xLog.LineLog( MultiLog::LStatus, "Closing connection due to disconnect."); close( i ); FD_CLR( i, &fdActive ); pMonitor->onClosedConnection( pCon ); @@ -203,7 +203,7 @@ bool ConnectionManager::scanConnections( int nTimeout, bool bForceTimeout ) std::list::iterator l = i; i--; lActive.erase( l ); - pLog->LineLog( MultiLog::LStatus, "Closing connection due to server request."); + xLog.LineLog( MultiLog::LStatus, "Closing connection due to server request."); } } @@ -269,13 +269,13 @@ bool ConnectionManager::addConnection() #endif if( newSocket < 0 ) { - pLog->LineLog( MultiLog::LError, "Error accepting a new connection!" ); + xLog.LineLog( MultiLog::LError, "Error accepting a new connection!" ); return false; } // char *tmpa = inet_ntoa(clientname.sin_addr); char tmpa[20]; inet_ntop( AF_INET, (void *)&clientname.sin_addr, tmpa, 20 ); - pLog->LineLog( MultiLog::LStatus, "New connection from host %s, port %hd.", tmpa, ntohs (clientname.sin_port) ); + xLog.LineLog( MultiLog::LStatus, "New connection from host %s, port %hd.", tmpa, ntohs (clientname.sin_port) ); /* int nCnt = 0; for( int j = 0; j < nPoolSize; j++ ) @@ -285,7 +285,7 @@ bool ConnectionManager::addConnection() nCnt++; } } - pLog->LineLog( MultiLog::LStatus, "Connections %d/%d.", nCnt, nPoolSize ); + xLog.LineLog( MultiLog::LStatus, "Connections %d/%d.", nCnt, nPoolSize ); */ // free( tmpa ); FD_SET( newSocket, &fdActive ); diff --git a/src/connectionmanager.h b/src/connectionmanager.h index 53249a7..669fcd5 100644 --- a/src/connectionmanager.h +++ b/src/connectionmanager.h @@ -122,7 +122,6 @@ private: */ Connection *getInactiveConnection(); - MultiLog *pLog; /**< A pointer to the active MultiLog */ int nMasterSocket; /**< The listening or server socket. */ fd_set fdActive; /**< The active socket set. */ fd_set fdRead; /**< The sockets ready for a read. */ @@ -130,6 +129,7 @@ private: fd_set fdException; /**< The sockets that have gotten errors. */ std::list lInactive; /**< The pool of inactive Connections */ std::list lActive; /**< The pool of active Connections */ + MultiLog &xLog; /**< A handle to the active multilog. */ /** The ConnectionMonitor to notify of new connections. */ ConnectionMonitor *pMonitor; diff --git a/src/hashtable.cpp b/src/hashtable.cpp index 49d9236..d3f9f26 100644 --- a/src/hashtable.cpp +++ b/src/hashtable.cpp @@ -347,7 +347,6 @@ bool HashTable::del( const void *id, int nSkip ) if( nSkip == 0 ) { aTable[nPos].bDeleted = true; -// aTable[nPos]. nSize--; #ifdef HASH_DEBUG_VIS printDebugLine( (const char *)id ); diff --git a/src/multilog.cpp b/src/multilog.cpp index 64ff967..3dfb8b6 100644 --- a/src/multilog.cpp +++ b/src/multilog.cpp @@ -1,20 +1,3 @@ -/*************************************************************************** - multilog.cpp - description - ------------------- - begin : Sat Sep 6 2003 - copyright : (C) 2003 by Mike Buland - email : eichlan@yf-soft.com - ***************************************************************************/ - -/*************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ - #include "multilog.h" #include #include @@ -23,28 +6,9 @@ #include "multilogchannel.h" -// This section is what we need to make this a singleton -// this makes this class easy to use from anywhere, without -// worrying about re-creating every output form and all of that crazy jazz -MultiLog *MultiLog::singleLog = NULL; - -MultiLog *MultiLog::getLog() -{ - if( singleLog == NULL ) - { - singleLog = new MultiLog; - atexit( cleanup ); - } - return singleLog; -} - -void MultiLog::cleanup() +void testlog( const char *text ) { - if( singleLog != NULL ) - { - delete singleLog; - singleLog = NULL; - } + MultiLineLog( 4, text ); } MultiLog::MultiLog() diff --git a/src/multilog.h b/src/multilog.h index 30ad8d7..7e4a357 100644 --- a/src/multilog.h +++ b/src/multilog.h @@ -7,6 +7,7 @@ #include "ringlist.h" #include "linkedlist.h" +#include "singleton.h" /** * Calls the DetailLog function but includes pre-processor macros to fill in @@ -19,6 +20,8 @@ */ #define LineLog( LEVEL, FORMAT, ...) DetailLog( LEVEL, __FILE__, __LINE__, __PRETTY_FUNCTION__, FORMAT, ##__VA_ARGS__ ) +#define MultiLineLog( LEVEL, FORMAT, ...) MultiLog::getInstance().DetailLog( LEVEL, __FILE__, __LINE__, __PRETTY_FUNCTION__, FORMAT, ##__VA_ARGS__ ) + /** MultiLog keeps track of logfile info in a myriad of varieties, and is * easily configurable between them all. It allows output to the standard * output, error output, files, networks, and streams, which includes memory @@ -27,8 +30,9 @@ * the log. Instead of instantiating a new copy, call the getLog method. *@author Mike Buland */ -class MultiLog +class MultiLog : public Singleton { + friend class Singleton; public: /** * Keeps track of a single log entry, in a standard format, that can be @@ -46,16 +50,16 @@ public: char *lpText; /**< The text content of this log entry. */ } LogEntry; -private: +protected: /** * Private constructor, this ensures that this is a singleton. */ MultiLog(); /** - * The only instance of MultiLog ever. + * Destroy the multilog. */ - static MultiLog *singleLog; + ~MultiLog(); /** * Append a new logentry to the log list, possibly pushing an old entry off. @@ -79,11 +83,6 @@ private: LinkedList *lChannel; public: - /** - * Destroy the multilog. - *@todo Why is this public? Does it need to be? - */ - ~MultiLog(); /** Sends info to the logfile. *@param nLevel The type of data being logged (error, info, etc.) @@ -106,20 +105,6 @@ public: */ void DetailLog( int nLevel, const char *lpFile, int nLine, const char *lpFunction, const char *lpFormat, ...); - /** Gets a pointer to the only instantion of the MultiLog that can exist. - * If there is no instantion in existance, it creates one, so it's - * foolproof. - *@returns A pointer to the only MultiLog instantion. - *@author Mike Buland - */ - static MultiLog *getLog(); - - /** Performs standard cleanup and deletes the only instantiation of MultiLog - * that can exist. This is just the same as delete and will nicely close - * all open logs. always call this when you are done with your MultiLog. - */ - static void cleanup(); - /** * Adds a logging channel to the MultiLog channel chain. Every added * channel will automatically receive a complete log of everything that diff --git a/src/multilogtext.cpp b/src/multilogtext.cpp index be64595..daad4c0 100644 --- a/src/multilogtext.cpp +++ b/src/multilogtext.cpp @@ -1,4 +1,3 @@ - #include #include #include @@ -7,9 +6,46 @@ #include #include "multilogtext.h" -MultiLogText::MultiLogText( const char *sFileName, const char *lpFormat ) +bool fileexists( const char *sPath ) +{ + int nFileDesc = open( sPath, O_RDONLY ); + if( nFileDesc < 0 ) + { + return false; + } + else + { + close( nFileDesc ); + return true; + } +} + +MultiLogText::MultiLogText( const char *sFileName, const char *lpFormat, bool bRotateLog, int nMaxLogs ) { this->lpFormat = NULL; + + if( bRotateLog ) + { + if( fileexists( sFileName ) == false ) + { + return; + } + + int nLen = strlen( sFileName ); + char *buf = new char[nLen+6]; + sprintf( buf, "%s.", sFileName ); + + for( int j = 1; j < nMaxLogs; j++ ) + { + sprintf( &buf[nLen+1], "%d", j ); + if( !fileexists( buf ) ) + { + rename( sFileName, buf ); + break; + } + } + } + nFD = open( sFileName, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH ); setLogFormat( lpFormat ); } diff --git a/src/multilogtext.h b/src/multilogtext.h index aa32405..8994b68 100644 --- a/src/multilogtext.h +++ b/src/multilogtext.h @@ -34,7 +34,7 @@ public: *@param lpFormat The format using the above specifications to be used for * every log entry. */ - MultiLogText( const char *sFileName, const char *lpFormat ); + MultiLogText( const char *sFileName, const char *lpFormat, bool bRotateLog=false, int nMaxLogs=0 ); /** * Construct a MultiLogText object around a specific file and format. diff --git a/src/programchain.cpp b/src/programchain.cpp index 4e53ac8..6120d58 100644 --- a/src/programchain.cpp +++ b/src/programchain.cpp @@ -1,27 +1,10 @@ -/*************************************************************************** - programchain.cpp - description - ------------------- - begin : Sat Sep 6 2003 - copyright : (C) 2003 by Mike Buland - email : eichlan@yf-soft.com - ***************************************************************************/ - -/*************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ - #include #include "programchain.h" -ProgramChain::ProgramChain() +ProgramChain::ProgramChain() : + xLog( MultiLog::getInstance() ) { - pLog = MultiLog::getLog(); - pLog->LineLog( MultiLog::LStatus, "Program Chain Initialized." ); + xLog.LineLog( MultiLog::LStatus, "Program Chain Initialized." ); } ProgramChain::~ProgramChain() @@ -62,7 +45,7 @@ bool ProgramChain::execChainOnce() { if( ((ProgramLink *)lLink[j])->timeSlice() == false ) { - pLog->LineLog( MultiLog::LInfo, "Shutting down due to signal from link #%d", j ); + xLog.LineLog( MultiLog::LInfo, "Shutting down due to signal from link #%d", j ); emergencyShutdown(); return false; } diff --git a/src/programchain.h b/src/programchain.h index 34f64f8..333c91b 100644 --- a/src/programchain.h +++ b/src/programchain.h @@ -81,7 +81,7 @@ private: * Shuts down all operation no matter what point in the operation we were. */ void emergencyShutdown(); - MultiLog *pLog; /**< A pointer to a log. */ + MultiLog &xLog; /**< A reference to the log. */ LinkedList lLink; /**< The linked list that contains all of the links. */ }; diff --git a/src/singleton.h b/src/singleton.h index c69e6f1..47adbd5 100644 --- a/src/singleton.h +++ b/src/singleton.h @@ -30,12 +30,25 @@ template class Singleton { protected: + /** + * Private constructor. This constructor is empty but has a body so that + * you can make your own override of it. Be sure that you're override is + * also protected. + */ Singleton() {}; private: + /** + * Copy constructor, defined so that you could write your own as well. + */ Singleton( const Singleton& ); public: + /** + * Get a handle to the contained instance of the contained class. It is + * a reference. + *@returns A reference to the contained object. + */ static T &getInstance() { static T i; diff --git a/src/test/log.cpp b/src/test/log.cpp new file mode 100644 index 0000000..0420e37 --- /dev/null +++ b/src/test/log.cpp @@ -0,0 +1,33 @@ +#include +#include +#include +#include "multilog.h" +#include "multilogtext.h" + +void testlog( const char *text ); + +class Test +{ +public: + Test() + { + MultiLineLog( 4, "Test init'd\n"); + } +}; + +int main() +{ + MultiLog &xLog = MultiLog::getInstance(); + + xLog.LineLog( 2, "Hello again"); + + MultiLog::getInstance().addChannel( + new MultiLogText( STDOUT_FILENO, "%02y-%02m-%02d %02h:%02M:%02s: %t" ) + ); + + MultiLineLog( MultiLog::LError, "Hi there!"); + Test t; + + testlog("external test"); +} + -- cgit v1.2.3