aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Buland <eichlan@xagasoft.com>2006-05-03 06:49:30 +0000
committerMike Buland <eichlan@xagasoft.com>2006-05-03 06:49:30 +0000
commit96b00553a0ffe6bb34af6ad15e1cfc2bed67bd75 (patch)
treea930fe51f01a7400fe97b46db2fcfcdc1f2712da
parent33fef4a17290e7872293d8cc173bec826f24001c (diff)
downloadlibbu++-96b00553a0ffe6bb34af6ad15e1cfc2bed67bd75.tar.gz
libbu++-96b00553a0ffe6bb34af6ad15e1cfc2bed67bd75.tar.bz2
libbu++-96b00553a0ffe6bb34af6ad15e1cfc2bed67bd75.tar.xz
libbu++-96b00553a0ffe6bb34af6ad15e1cfc2bed67bd75.zip
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.
Diffstat (limited to '')
-rw-r--r--Doxyfile2
-rw-r--r--src/connectionmanager.cpp32
-rw-r--r--src/connectionmanager.h2
-rw-r--r--src/hashtable.cpp1
-rw-r--r--src/multilog.cpp40
-rw-r--r--src/multilog.h31
-rw-r--r--src/multilogtext.cpp40
-rw-r--r--src/multilogtext.h2
-rw-r--r--src/programchain.cpp25
-rw-r--r--src/programchain.h2
-rw-r--r--src/singleton.h13
-rw-r--r--src/test/log.cpp33
12 files changed, 118 insertions, 105 deletions
diff --git a/Doxyfile b/Doxyfile
index 213c87b..c9ded4d 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -176,7 +176,7 @@ TREEVIEW_WIDTH = 250
176#--------------------------------------------------------------------------- 176#---------------------------------------------------------------------------
177# configuration options related to the LaTeX output 177# configuration options related to the LaTeX output
178#--------------------------------------------------------------------------- 178#---------------------------------------------------------------------------
179GENERATE_LATEX = YES 179GENERATE_LATEX = NO
180LATEX_OUTPUT = latex 180LATEX_OUTPUT = latex
181LATEX_CMD_NAME = latex 181LATEX_CMD_NAME = latex
182MAKEINDEX_CMD_NAME = makeindex 182MAKEINDEX_CMD_NAME = makeindex
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 @@
13#include "connectionmanager.h" 13#include "connectionmanager.h"
14#include <fcntl.h> 14#include <fcntl.h>
15 15
16ConnectionManager::ConnectionManager() 16ConnectionManager::ConnectionManager() :
17 xLog( MultiLog::getInstance() )
17{ 18{
18 pLog = MultiLog::getLog();
19 nMasterSocket = -1; 19 nMasterSocket = -1;
20 pMonitor = NULL; 20 pMonitor = NULL;
21} 21}
@@ -42,7 +42,7 @@ bool ConnectionManager::startServer( int nPort, int nInitPool )
42 nMasterSocket = socket (PF_INET, SOCK_STREAM, 0); 42 nMasterSocket = socket (PF_INET, SOCK_STREAM, 0);
43 if (nMasterSocket < 0) 43 if (nMasterSocket < 0)
44 { 44 {
45 pLog->LineLog( MultiLog::LError, "Couldn't create a listen socket."); 45 xLog.LineLog( MultiLog::LError, "Couldn't create a listen socket.");
46 return false; 46 return false;
47 } 47 }
48 48
@@ -59,13 +59,13 @@ bool ConnectionManager::startServer( int nPort, int nInitPool )
59 59
60 if (bind (nMasterSocket, (struct sockaddr *) &name, sizeof (name)) < 0) 60 if (bind (nMasterSocket, (struct sockaddr *) &name, sizeof (name)) < 0)
61 { 61 {
62 pLog->LineLog( MultiLog::LError, "Couldn't bind to the listen socket."); 62 xLog.LineLog( MultiLog::LError, "Couldn't bind to the listen socket.");
63 return false; 63 return false;
64 } 64 }
65 65
66 if (listen (nMasterSocket, 1) < 0) 66 if (listen (nMasterSocket, 1) < 0)
67 { 67 {
68 pLog->LineLog( MultiLog::LError, "Couldn't begin listening to the server socket."); 68 xLog.LineLog( MultiLog::LError, "Couldn't begin listening to the server socket.");
69 return false; 69 return false;
70 } 70 }
71 71
@@ -90,18 +90,18 @@ bool ConnectionManager::startServer( int nPort, int nInitPool, int nNumTries, in
90 90
91 for( int j = 0; j < nNumTries; j++ ) 91 for( int j = 0; j < nNumTries; j++ )
92 { 92 {
93 pLog->LineLog( MultiLog::LStatus, "Attempting to create server socket (attempt [%d/%d])...", j+1, nNumTries ); 93 xLog.LineLog( MultiLog::LStatus, "Attempting to create server socket (attempt [%d/%d])...", j+1, nNumTries );
94 if( startServer( nPort, nInitPool ) == true ) 94 if( startServer( nPort, nInitPool ) == true )
95 { 95 {
96 return true; 96 return true;
97 } 97 }
98 else if( j < nNumTries-1 ) 98 else if( j < nNumTries-1 )
99 { 99 {
100 pLog->LineLog( MultiLog::LStatus, "Waiting for %d secconds to allow port to clear...", nTimeout ); 100 xLog.LineLog( MultiLog::LStatus, "Waiting for %d secconds to allow port to clear...", nTimeout );
101 xTimeout.tv_sec = nTimeout; 101 xTimeout.tv_sec = nTimeout;
102 xTimeout.tv_usec = 0; 102 xTimeout.tv_usec = 0;
103 if (select(0, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0, &xTimeout) < 0) { 103 if (select(0, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0, &xTimeout) < 0) {
104 pLog->LineLog( MultiLog::LError, "Error using select to sleep for a while."); 104 xLog.LineLog( MultiLog::LError, "Error using select to sleep for a while.");
105 } 105 }
106 usleep( nTimeout ); 106 usleep( nTimeout );
107 } 107 }
@@ -127,7 +127,7 @@ bool ConnectionManager::scanConnections( int nTimeout, bool bForceTimeout )
127 // if there are ANY connections there... 127 // if there are ANY connections there...
128 if( TEMP_FAILURE_RETRY( select( FD_SETSIZE, &fdRead, (fd_set *)0/*&fdWrite*/, &fdException, &xTimeout ) ) < 0 ) 128 if( TEMP_FAILURE_RETRY( select( FD_SETSIZE, &fdRead, (fd_set *)0/*&fdWrite*/, &fdException, &xTimeout ) ) < 0 )
129 { 129 {
130 pLog->LineLog( MultiLog::LError, "Error attempting to scan open connections."); 130 xLog.LineLog( MultiLog::LError, "Error attempting to scan open connections.");
131 perror("ConnectionManager"); 131 perror("ConnectionManager");
132 return false; 132 return false;
133 } 133 }
@@ -137,7 +137,7 @@ bool ConnectionManager::scanConnections( int nTimeout, bool bForceTimeout )
137 if( bForceTimeout ) 137 if( bForceTimeout )
138 { 138 {
139 if (select(0, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0, &xTimeout) < 0) { 139 if (select(0, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0, &xTimeout) < 0) {
140 pLog->LineLog( MultiLog::LError, "Error using select to sleep for a while."); 140 xLog.LineLog( MultiLog::LError, "Error using select to sleep for a while.");
141 } 141 }
142 } 142 }
143 143
@@ -155,14 +155,14 @@ bool ConnectionManager::scanConnections( int nTimeout, bool bForceTimeout )
155 Connection *pCon = findActiveConnection( i ); 155 Connection *pCon = findActiveConnection( i );
156 if( pCon == NULL ) 156 if( pCon == NULL )
157 { 157 {
158 pLog->LineLog( MultiLog::LError, "A connection object was lost, or never created!"); 158 xLog.LineLog( MultiLog::LError, "A connection object was lost, or never created!");
159 return false; 159 return false;
160 } 160 }
161 161
162 /* Data arriving on an already-connected socket. */ 162 /* Data arriving on an already-connected socket. */
163 if( pCon->readInput() != true ) 163 if( pCon->readInput() != true )
164 { 164 {
165 pLog->LineLog( MultiLog::LStatus, "Closing connection due to disconnect."); 165 xLog.LineLog( MultiLog::LStatus, "Closing connection due to disconnect.");
166 close( i ); 166 close( i );
167 FD_CLR( i, &fdActive ); 167 FD_CLR( i, &fdActive );
168 pMonitor->onClosedConnection( pCon ); 168 pMonitor->onClosedConnection( pCon );
@@ -203,7 +203,7 @@ bool ConnectionManager::scanConnections( int nTimeout, bool bForceTimeout )
203 std::list<Connection *>::iterator l = i; 203 std::list<Connection *>::iterator l = i;
204 i--; 204 i--;
205 lActive.erase( l ); 205 lActive.erase( l );
206 pLog->LineLog( MultiLog::LStatus, "Closing connection due to server request."); 206 xLog.LineLog( MultiLog::LStatus, "Closing connection due to server request.");
207 } 207 }
208 } 208 }
209 209
@@ -269,13 +269,13 @@ bool ConnectionManager::addConnection()
269#endif 269#endif
270 if( newSocket < 0 ) 270 if( newSocket < 0 )
271 { 271 {
272 pLog->LineLog( MultiLog::LError, "Error accepting a new connection!" ); 272 xLog.LineLog( MultiLog::LError, "Error accepting a new connection!" );
273 return false; 273 return false;
274 } 274 }
275// char *tmpa = inet_ntoa(clientname.sin_addr); 275// char *tmpa = inet_ntoa(clientname.sin_addr);
276 char tmpa[20]; 276 char tmpa[20];
277 inet_ntop( AF_INET, (void *)&clientname.sin_addr, tmpa, 20 ); 277 inet_ntop( AF_INET, (void *)&clientname.sin_addr, tmpa, 20 );
278 pLog->LineLog( MultiLog::LStatus, "New connection from host %s, port %hd.", tmpa, ntohs (clientname.sin_port) ); 278 xLog.LineLog( MultiLog::LStatus, "New connection from host %s, port %hd.", tmpa, ntohs (clientname.sin_port) );
279/* 279/*
280 int nCnt = 0; 280 int nCnt = 0;
281 for( int j = 0; j < nPoolSize; j++ ) 281 for( int j = 0; j < nPoolSize; j++ )
@@ -285,7 +285,7 @@ bool ConnectionManager::addConnection()
285 nCnt++; 285 nCnt++;
286 } 286 }
287 } 287 }
288 pLog->LineLog( MultiLog::LStatus, "Connections %d/%d.", nCnt, nPoolSize ); 288 xLog.LineLog( MultiLog::LStatus, "Connections %d/%d.", nCnt, nPoolSize );
289 */ 289 */
290// free( tmpa ); 290// free( tmpa );
291 FD_SET( newSocket, &fdActive ); 291 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:
122 */ 122 */
123 Connection *getInactiveConnection(); 123 Connection *getInactiveConnection();
124 124
125 MultiLog *pLog; /**< A pointer to the active MultiLog */
126 int nMasterSocket; /**< The listening or server socket. */ 125 int nMasterSocket; /**< The listening or server socket. */
127 fd_set fdActive; /**< The active socket set. */ 126 fd_set fdActive; /**< The active socket set. */
128 fd_set fdRead; /**< The sockets ready for a read. */ 127 fd_set fdRead; /**< The sockets ready for a read. */
@@ -130,6 +129,7 @@ private:
130 fd_set fdException; /**< The sockets that have gotten errors. */ 129 fd_set fdException; /**< The sockets that have gotten errors. */
131 std::list<Connection *> lInactive; /**< The pool of inactive Connections */ 130 std::list<Connection *> lInactive; /**< The pool of inactive Connections */
132 std::list<Connection *> lActive; /**< The pool of active Connections */ 131 std::list<Connection *> lActive; /**< The pool of active Connections */
132 MultiLog &xLog; /**< A handle to the active multilog. */
133 133
134 /** The ConnectionMonitor to notify of new connections. */ 134 /** The ConnectionMonitor to notify of new connections. */
135 ConnectionMonitor *pMonitor; 135 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 )
347 if( nSkip == 0 ) 347 if( nSkip == 0 )
348 { 348 {
349 aTable[nPos].bDeleted = true; 349 aTable[nPos].bDeleted = true;
350// aTable[nPos].
351 nSize--; 350 nSize--;
352#ifdef HASH_DEBUG_VIS 351#ifdef HASH_DEBUG_VIS
353 printDebugLine( (const char *)id ); 352 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 @@
1/***************************************************************************
2 multilog.cpp - description
3 -------------------
4 begin : Sat Sep 6 2003
5 copyright : (C) 2003 by Mike Buland
6 email : eichlan@yf-soft.com
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18#include "multilog.h" 1#include "multilog.h"
19#include <stdio.h> 2#include <stdio.h>
20#include <time.h> 3#include <time.h>
@@ -23,28 +6,9 @@
23 6
24#include "multilogchannel.h" 7#include "multilogchannel.h"
25 8
26// This section is what we need to make this a singleton 9void testlog( const char *text )
27// this makes this class easy to use from anywhere, without
28// worrying about re-creating every output form and all of that crazy jazz
29MultiLog *MultiLog::singleLog = NULL;
30
31MultiLog *MultiLog::getLog()
32{
33 if( singleLog == NULL )
34 {
35 singleLog = new MultiLog;
36 atexit( cleanup );
37 }
38 return singleLog;
39}
40
41void MultiLog::cleanup()
42{ 10{
43 if( singleLog != NULL ) 11 MultiLineLog( 4, text );
44 {
45 delete singleLog;
46 singleLog = NULL;
47 }
48} 12}
49 13
50MultiLog::MultiLog() 14MultiLog::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 @@
7 7
8#include "ringlist.h" 8#include "ringlist.h"
9#include "linkedlist.h" 9#include "linkedlist.h"
10#include "singleton.h"
10 11
11/** 12/**
12 * Calls the DetailLog function but includes pre-processor macros to fill in 13 * Calls the DetailLog function but includes pre-processor macros to fill in
@@ -19,6 +20,8 @@
19 */ 20 */
20#define LineLog( LEVEL, FORMAT, ...) DetailLog( LEVEL, __FILE__, __LINE__, __PRETTY_FUNCTION__, FORMAT, ##__VA_ARGS__ ) 21#define LineLog( LEVEL, FORMAT, ...) DetailLog( LEVEL, __FILE__, __LINE__, __PRETTY_FUNCTION__, FORMAT, ##__VA_ARGS__ )
21 22
23#define MultiLineLog( LEVEL, FORMAT, ...) MultiLog::getInstance().DetailLog( LEVEL, __FILE__, __LINE__, __PRETTY_FUNCTION__, FORMAT, ##__VA_ARGS__ )
24
22/** MultiLog keeps track of logfile info in a myriad of varieties, and is 25/** MultiLog keeps track of logfile info in a myriad of varieties, and is
23 * easily configurable between them all. It allows output to the standard 26 * easily configurable between them all. It allows output to the standard
24 * output, error output, files, networks, and streams, which includes memory 27 * output, error output, files, networks, and streams, which includes memory
@@ -27,8 +30,9 @@
27 * the log. Instead of instantiating a new copy, call the getLog method. 30 * the log. Instead of instantiating a new copy, call the getLog method.
28 *@author Mike Buland 31 *@author Mike Buland
29 */ 32 */
30class MultiLog 33class MultiLog : public Singleton<MultiLog>
31{ 34{
35 friend class Singleton<MultiLog>;
32public: 36public:
33 /** 37 /**
34 * Keeps track of a single log entry, in a standard format, that can be 38 * Keeps track of a single log entry, in a standard format, that can be
@@ -46,16 +50,16 @@ public:
46 char *lpText; /**< The text content of this log entry. */ 50 char *lpText; /**< The text content of this log entry. */
47 } LogEntry; 51 } LogEntry;
48 52
49private: 53protected:
50 /** 54 /**
51 * Private constructor, this ensures that this is a singleton. 55 * Private constructor, this ensures that this is a singleton.
52 */ 56 */
53 MultiLog(); 57 MultiLog();
54 58
55 /** 59 /**
56 * The only instance of MultiLog ever. 60 * Destroy the multilog.
57 */ 61 */
58 static MultiLog *singleLog; 62 ~MultiLog();
59 63
60 /** 64 /**
61 * Append a new logentry to the log list, possibly pushing an old entry off. 65 * Append a new logentry to the log list, possibly pushing an old entry off.
@@ -79,11 +83,6 @@ private:
79 LinkedList *lChannel; 83 LinkedList *lChannel;
80 84
81public: 85public:
82 /**
83 * Destroy the multilog.
84 *@todo Why is this public? Does it need to be?
85 */
86 ~MultiLog();
87 86
88 /** Sends info to the logfile. 87 /** Sends info to the logfile.
89 *@param nLevel The type of data being logged (error, info, etc.) 88 *@param nLevel The type of data being logged (error, info, etc.)
@@ -106,20 +105,6 @@ public:
106 */ 105 */
107 void DetailLog( int nLevel, const char *lpFile, int nLine, const char *lpFunction, const char *lpFormat, ...); 106 void DetailLog( int nLevel, const char *lpFile, int nLine, const char *lpFunction, const char *lpFormat, ...);
108 107
109 /** Gets a pointer to the only instantion of the MultiLog that can exist.
110 * If there is no instantion in existance, it creates one, so it's
111 * foolproof.
112 *@returns A pointer to the only MultiLog instantion.
113 *@author Mike Buland
114 */
115 static MultiLog *getLog();
116
117 /** Performs standard cleanup and deletes the only instantiation of MultiLog
118 * that can exist. This is just the same as delete and will nicely close
119 * all open logs. always call this when you are done with your MultiLog.
120 */
121 static void cleanup();
122
123 /** 108 /**
124 * Adds a logging channel to the MultiLog channel chain. Every added 109 * Adds a logging channel to the MultiLog channel chain. Every added
125 * channel will automatically receive a complete log of everything that 110 * 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 @@
1
2#include <stdio.h> 1#include <stdio.h>
3#include <stdlib.h> 2#include <stdlib.h>
4#include <fcntl.h> 3#include <fcntl.h>
@@ -7,9 +6,46 @@
7#include <string.h> 6#include <string.h>
8#include "multilogtext.h" 7#include "multilogtext.h"
9 8
10MultiLogText::MultiLogText( const char *sFileName, const char *lpFormat ) 9bool fileexists( const char *sPath )
10{
11 int nFileDesc = open( sPath, O_RDONLY );
12 if( nFileDesc < 0 )
13 {
14 return false;
15 }
16 else
17 {
18 close( nFileDesc );
19 return true;
20 }
21}
22
23MultiLogText::MultiLogText( const char *sFileName, const char *lpFormat, bool bRotateLog, int nMaxLogs )
11{ 24{
12 this->lpFormat = NULL; 25 this->lpFormat = NULL;
26
27 if( bRotateLog )
28 {
29 if( fileexists( sFileName ) == false )
30 {
31 return;
32 }
33
34 int nLen = strlen( sFileName );
35 char *buf = new char[nLen+6];
36 sprintf( buf, "%s.", sFileName );
37
38 for( int j = 1; j < nMaxLogs; j++ )
39 {
40 sprintf( &buf[nLen+1], "%d", j );
41 if( !fileexists( buf ) )
42 {
43 rename( sFileName, buf );
44 break;
45 }
46 }
47 }
48
13 nFD = open( sFileName, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH ); 49 nFD = open( sFileName, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH );
14 setLogFormat( lpFormat ); 50 setLogFormat( lpFormat );
15} 51}
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:
34 *@param lpFormat The format using the above specifications to be used for 34 *@param lpFormat The format using the above specifications to be used for
35 * every log entry. 35 * every log entry.
36 */ 36 */
37 MultiLogText( const char *sFileName, const char *lpFormat ); 37 MultiLogText( const char *sFileName, const char *lpFormat, bool bRotateLog=false, int nMaxLogs=0 );
38 38
39 /** 39 /**
40 * Construct a MultiLogText object around a specific file and format. 40 * 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 @@
1/***************************************************************************
2 programchain.cpp - description
3 -------------------
4 begin : Sat Sep 6 2003
5 copyright : (C) 2003 by Mike Buland
6 email : eichlan@yf-soft.com
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18#include <stdlib.h> 1#include <stdlib.h>
19#include "programchain.h" 2#include "programchain.h"
20 3
21ProgramChain::ProgramChain() 4ProgramChain::ProgramChain() :
5 xLog( MultiLog::getInstance() )
22{ 6{
23 pLog = MultiLog::getLog(); 7 xLog.LineLog( MultiLog::LStatus, "Program Chain Initialized." );
24 pLog->LineLog( MultiLog::LStatus, "Program Chain Initialized." );
25} 8}
26 9
27ProgramChain::~ProgramChain() 10ProgramChain::~ProgramChain()
@@ -62,7 +45,7 @@ bool ProgramChain::execChainOnce()
62 { 45 {
63 if( ((ProgramLink *)lLink[j])->timeSlice() == false ) 46 if( ((ProgramLink *)lLink[j])->timeSlice() == false )
64 { 47 {
65 pLog->LineLog( MultiLog::LInfo, "Shutting down due to signal from link #%d", j ); 48 xLog.LineLog( MultiLog::LInfo, "Shutting down due to signal from link #%d", j );
66 emergencyShutdown(); 49 emergencyShutdown();
67 return false; 50 return false;
68 } 51 }
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:
81 * Shuts down all operation no matter what point in the operation we were. 81 * Shuts down all operation no matter what point in the operation we were.
82 */ 82 */
83 void emergencyShutdown(); 83 void emergencyShutdown();
84 MultiLog *pLog; /**< A pointer to a log. */ 84 MultiLog &xLog; /**< A reference to the log. */
85 LinkedList lLink; /**< The linked list that contains all of the links. */ 85 LinkedList lLink; /**< The linked list that contains all of the links. */
86}; 86};
87 87
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 T>
30class Singleton 30class Singleton
31{ 31{
32protected: 32protected:
33 /**
34 * Private constructor. This constructor is empty but has a body so that
35 * you can make your own override of it. Be sure that you're override is
36 * also protected.
37 */
33 Singleton() {}; 38 Singleton() {};
34 39
35private: 40private:
41 /**
42 * Copy constructor, defined so that you could write your own as well.
43 */
36 Singleton( const Singleton& ); 44 Singleton( const Singleton& );
37 45
38public: 46public:
47 /**
48 * Get a handle to the contained instance of the contained class. It is
49 * a reference.
50 *@returns A reference to the contained object.
51 */
39 static T &getInstance() 52 static T &getInstance()
40 { 53 {
41 static T i; 54 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 @@
1#include <stdio.h>
2#include <stdlib.h>
3#include <iostream>
4#include "multilog.h"
5#include "multilogtext.h"
6
7void testlog( const char *text );
8
9class Test
10{
11public:
12 Test()
13 {
14 MultiLineLog( 4, "Test init'd\n");
15 }
16};
17
18int main()
19{
20 MultiLog &xLog = MultiLog::getInstance();
21
22 xLog.LineLog( 2, "Hello again");
23
24 MultiLog::getInstance().addChannel(
25 new MultiLogText( STDOUT_FILENO, "%02y-%02m-%02d %02h:%02M:%02s: %t" )
26 );
27
28 MultiLineLog( MultiLog::LError, "Hi there!");
29 Test t;
30
31 testlog("external test");
32}
33