⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 log.cpp

📁 电信的97接口程序,用于把话单入库。这里是采用FTP方式采集话单
💻 CPP
字号:
/*+============================================================================
File:		 log.cpp
Description: It provides an uniform interface for logging.
History:
2000/05/29	V1.0 
	Start it by shencan@263.net
2000/06/01	V1.1
	Fix RadTrace output format (shencan@263.net)
	Add Size(), Empty() and Instance() method.
2000/06/20	V1.2
	We can use command "copy empty.log radius.log" to empty log file. (shencan@263.net)
2000/06/27	V1.3
	Support solaris platform (shencan@263.net)
2000/07/08	V1.4
	Fix a bug when log system exit, we set treace stream to cerr. (shencan@263.net)
2000/07/12	V1.5
	Add check size timer. (shencan@263.net)
2000/07/19	V1.6
	We separate log file when the size is exceed 10M. (shencan@263.net)
2000/07/25	V1.7
	Fix log file size limit bug. (shencan@263.net)
2000/08/11	V1.8
	Fix localtime() return NULL pointer bug. (shencan@263.net)
2000/08/25	V1.9
	Add log file maximum szie limit. (shencan@263.net)
2001/11/25	V1.10
	Fix string array bug, donot use [-1] to access array. (shencan@263.net)
===========================================================================+*/


//#include "ace/OS.h"
//#include "ace/Synch.h"
#include <ptlib.h>
#include <time.h>
#include "log.h"


// default maxium total log file size is 500M
#define DEFAULT_MAX_LOG_SIZE 500

// default maxium separate log file size is 5M
const int separateFileSize = 5000000L;
//const int separateFileSize = 50000L;



/////////////////////////////////////////////////////////////////////
// TRACE begin!
/////////////////////////////////////////////////////////////////////

static ostream * RadTraceStream = &cerr;
static unsigned RadTraceOptions = RadTrace::FileAndLine;
static unsigned RadTraceLevelThreshold = 0;
static int oldTraceLevel = 0;

PMutex		traceMutex;
//static  ACE_Mutex traceMutex;	// Lock of log file

RadLogFile * RadLogFile::m_instance = NULL;	// inital static member


void RadTrace::SetStream(ostream * s)
{
	RadTraceStream = s != NULL ? s : &cerr;
}


void RadTrace::SetOptions(unsigned options)
{
	RadTraceOptions |= options;
}


void RadTrace::ClearOptions(unsigned options)
{
	RadTraceOptions &= ~options;
}


unsigned RadTrace::GetOptions()
{
	return RadTraceOptions;
}


void RadTrace::SetLevel(unsigned level)
{
	RadTraceLevelThreshold = level;
}


unsigned RadTrace::GetLevel()
{
	return RadTraceLevelThreshold;
}


bool RadTrace::CanTrace(unsigned level)
{
	return level <= RadTraceLevelThreshold;
}


ostream & RadTrace::Begin(unsigned level, const char * fileName, int lineNum)
{
	//char msg[30];

	traceMutex.Wait();

	if ((RadTraceOptions&DateAndTime) != 0) {
		/*time_t      tm_sys;
		struct tm   tm_local_buf;
		struct tm * tm_local = &tm_local_buf;
		time(&tm_sys);
		tm_local = localtime(&tm_sys);
		if ( tm_local == NULL )
			sprintf ( msg, "00/00 00:00:00");
		else {
			sprintf ( msg, "%02d/%02d %02d:%02d:%02d",
				tm_local->tm_mon+1, tm_local->tm_mday,
				tm_local->tm_hour, tm_local->tm_min, tm_local->tm_sec);
		}

		*RadTraceStream << msg << " ";*/
		PTime now;
		*RadTraceStream << now.AsString("MM/dd hh:mm:ss ");
	}

	if ((RadTraceOptions&Thread) != 0) 
	{
		PThread * thread = PThread::Current();
		if (thread == NULL)
			*RadTraceStream << setw(23) << "<<SOCKETS RECIEVE>>";			
		else {
			PString name = thread->GetThreadName();
			if (name.GetLength() <= 23)
				*RadTraceStream << setw(23) << name;
			else
				*RadTraceStream << name.Left(10) << "..." << name.Right(10);
		}
		*RadTraceStream << '\t';
		//ACE_thread_t threadId = ACE_OS::thr_self ();
		//RadTraceStream->width(4);
		//*RadTraceStream  << threadId << " ";
	}

	if ((RadTraceOptions&TraceLevel) != 0)
		*RadTraceStream << level << '\t';

	if ((RadTraceOptions&FileAndLine) != 0 && fileName != NULL) {
		const char * file = strrchr(fileName, '/');
		if (file != NULL)
			file++;
		else {
			file = strrchr(fileName, '\\');
			if (file != NULL)
				file++;
			else
				file = fileName;
		}

		RadTraceStream->width(12);
		*RadTraceStream << file << '(' << lineNum << ")\t";
	}

	return *RadTraceStream;
}


ostream & RadTrace::End(ostream & s)
{
	s.flush();
	s << endl;

	traceMutex.Signal();
	
	return s;
}



/////////////////////////////////////////////////////////////////////
// RadLogFile begin!
/////////////////////////////////////////////////////////////////////

// if (fOption==e_oneFile), use only one file.
// if (fOption==e_separateFile), 5M is the upper size of log file

int RadLogFile::Init(int level, char * msgLog, char * controlFileName,
					 int maxSize, RadTrace::FileOption fOption)
{
	m_option = fOption;
	oldTraceLevel = level;

	// Set log file name
	memcpy(m_fileName, msgLog, FILE_NAME_LENGTH+1);
	m_fileName[FILE_NAME_LENGTH] = 0;

	// Set control file name
	memcpy(m_controlFile, controlFileName, FILE_NAME_LENGTH+1);
	m_controlFile[FILE_NAME_LENGTH] = 0;

	if ( maxSize >= 0 )
		m_maxLogSize = maxSize;
	else
		m_maxLogSize = DEFAULT_MAX_LOG_SIZE;
	m_totalLogFile = m_maxLogSize * 1000 / (separateFileSize/1000);
	if ( m_totalLogFile < 2 )
		m_totalLogFile = 2;

	// Get start log file number
	m_alterNumber = GetNumber();
	if ( m_alterNumber < 0 )
		m_alterNumber = 1;

	RadTrace::SetOptions(RadTrace::DateAndTime);
	RadTrace::SetOptions(RadTrace::Thread);
	

#ifdef ACE_WIN32
#ifdef NDEBUG
	RadTrace::ClearOptions(RadTrace::FileAndLine);
#endif
#else
	// On Unix, we donot print file name and line number!
	RadTrace::ClearOptions(RadTrace::FileAndLine);
#endif

	RadTrace::SetLevel( level );
	
	if ( fOption == RadTrace::e_separateFile )
	{
		InitOpenFile();
	}
	else {

#ifndef ACE_WIN32
		outputPtrace.open(msgLog, ios::out | ios::app);
#else
		// "filebuf::sh_read||filebuf::sh_write" make file can be changed by other process.
		outputPtrace.open(msgLog, ios::out | ios::app,
			filebuf::sh_read || filebuf::sh_write );
#endif

		if(outputPtrace.bad() || !outputPtrace.good() ) {
			cout << "open log file fail!\n";
			return(-1);
		}
	}

	outputPtrace << "\n\n\n\n\n - - - - - - - - - - - - - - - - - - - - - - - - - -\n";
	RadTrace::SetStream(&outputPtrace);

	RTRACE(1, "Trace logging started.");

	// start logger timer
	timeLogger.SetNotifier(PCREATE_NOTIFIER(CheckTimer));
	timeLogger.RunContinuous(5000);

	return 1;
}


int RadLogFile::Close()
{
	traceMutex.Wait();
	outputPtrace.close();
	traceMutex.Signal();
	RadTrace::SetStream(&cerr);
	return 1;
}


RadLogFile::RadLogFile()
{

	m_instance = this;

}


RadLogFile::~RadLogFile()
{
	m_instance = NULL;
}


// get size of log file
long RadLogFile::Size() 
{
	traceMutex.Wait();
	outputPtrace.seekp(0, ios::end); // End of file
	long s = outputPtrace.tellp(); // Size of file
	traceMutex.Signal();
	return s;
} 


// empty this log file
bool RadLogFile::Empty()
{
	traceMutex.Wait();
	outputPtrace.close();
	outputPtrace.open(m_fileName, ios::out | ios::trunc );

	if(outputPtrace.bad() || !outputPtrace.good() ) {
		cout << "error, empty log file fail!\n";
		traceMutex.Signal();
		return(false);
	}

	RTRACE(1, "Empty the logging file");

	//RadTraceStream->seekp(0, ios::beg); // Start of file
	//*RadTraceStream << EOF << flush;
	traceMutex.Signal();
	return true; 
}


//return -1 means fail, return value > 1 means success.
int RadLogFile::GetNumber()
{
	int ret;
	m_controlStream.open(m_controlFile, ios::in);
	if( m_controlStream.fail() || m_controlStream.bad() || !m_controlStream.good() ) 
		return -1;
	else
		m_controlStream >> ret;

	m_controlStream.close();
	return ret;
}


int RadLogFile::SaveNumber(int num)
{
	m_controlStream.clear();
	m_controlStream.open(m_controlFile, ios::out | ios::trunc);
	
	if( m_controlStream.bad() || !m_controlStream.good() ) 
	{
		outputPtrace << "save log file number fail";
		return -1;
	}

	m_controlStream << num << endl;
	m_controlStream.close();
	return 0;
}


// When program inital, call this function to open log file.
// get another name of log file, if the old name is X.Y, the new name is :
// "X1.Y", "X2.Y" or "X3.Y", 
// return 0 if success, return -1 if fail
int RadLogFile::InitOpenFile()
{
	int i, j, len;

	// check m_alterNumber value
	if ( m_alterNumber > m_totalLogFile  )
		m_alterNumber = 1;

	len = strlen(m_fileName);
	for ( j=len-1; j>=0; j--)
	{
		// get the last directory separate symbol
		if ( m_fileName[j] == '\\' || m_fileName[j] == '/' )
			break;
	}

	if(j == -1 )  j = 0; // fix a bug
	
	for ( i=j; i < FILE_NAME_LENGTH && m_fileName[i] != 0; i++)
		if ( m_fileName[i] == '.' )
			break;
		
	if ( i > FILE_NAME_LENGTH-9 )
		return -1;

	strncpy( m_alterFileName, m_fileName, i);
	sprintf( m_alterFileName+i, "%d", m_alterNumber);

	if ( m_fileName[i] != 0 ) 
		strcat(m_alterFileName, m_fileName+i);
	
#ifndef ACE_WIN32
	outputPtrace.open(m_alterFileName, ios::out | ios::app);
#else
	outputPtrace.open(m_alterFileName, ios::out | ios::app,
		filebuf::sh_read || filebuf::sh_write );
#endif

	if(outputPtrace.bad() || !outputPtrace.good() ) 
	{
		cout << "open alternate log file fail!\n";
		return(-1);
	}

	if ( m_option == RadTrace::e_separateFile && Size() >= separateFileSize )
	{
		// we try to open another log file.
		outputPtrace << "This log file is full, we open next file";
		RunningOpenFile();
	}
	else
		SaveNumber(m_alterNumber);

	return 0;
} 


// When program is running, call this function to open log file.
// get another name of log file, if the old name is X.Y, the new name is :
// "X1.Y", "X2.Y" or "X3.Y", 
// return 0 if success, return -1 if fail
int RadLogFile::RunningOpenFile() 
{
	int i, j, len;

	outputPtrace.close();

	m_alterNumber++;
	if ( m_alterNumber > m_totalLogFile )
		m_alterNumber = 1;

	len = strlen(m_fileName);
	for ( j=len-1; j>=0; j--)
	{
		// get the last directory separate symbol
		if ( m_fileName[j] == '\\' || m_fileName[j] == '/' )
			break;
	}

	if(j == -1 )  j = 0; // fix a bug
	
	for ( i=j; i < FILE_NAME_LENGTH && m_fileName[i] != 0; i++)
		if ( m_fileName[i] == '.' )
			break;

	if ( i > FILE_NAME_LENGTH-9 )
		return -1;

	strncpy( m_alterFileName, m_fileName, i);
	sprintf( m_alterFileName+i, "%d", m_alterNumber);

	if ( m_fileName[i] != 0 ) 
		strcat(m_alterFileName, m_fileName+i);

#ifndef ACE_WIN32
	outputPtrace.open(m_alterFileName, ios::out | ios::trunc );
#else
	outputPtrace.open(m_alterFileName, ios::out | ios::trunc,
		filebuf::sh_read || filebuf::sh_write );
#endif

	if(outputPtrace.bad() || !outputPtrace.good() )
	{
		cout << "open alternate log file fail!\n";
		return(-1);
	}

	SaveNumber(m_alterNumber);
	return 0;
} 



///////////////////////////////////////////////////////////////////////
//  class  CLogTimer
///////////////////////////////////////////////////////////////////////



//int CLogTimer::handle_timeout( const ACE_Time_Value & tv, const void * arg){
void RadLogFile::CheckTimer(PTimer &, INT)
{
	long size;
	RTRACE(6, "Enter log timer");

	switch ( RadLogFile::Instance()->m_option ) {
	case RadTrace::e_oneFile:
		{
			size = RadLogFile::Instance()->Size();
			int level = RadTrace::GetLevel();

			RTRACE(4, "Log file size = " << size << "\tlevel = " << level );
			if ( size > WARN_SIZE5 ) {
				if ( level > 0 )
					RadTrace::SetLevel(0);
			}
			else if ( size > WARN_SIZE4 ) {
				if ( level > 1 )
					RadTrace::SetLevel(1);
			}
			else if ( size > WARN_SIZE3 ) {
				if ( level > 2 )
					RadTrace::SetLevel(2);
			}
			else if ( size > WARN_SIZE2 ) {
				if ( level > 3 )
					RadTrace::SetLevel(3);
			}
			else if ( size > WARN_SIZE1 ) {
				if ( level > 4 )
					RadTrace::SetLevel(4);
			}
			else {
				RadTrace::SetLevel(oldTraceLevel);
			}
		}
		break;

	case RadTrace::e_separateFile:
		size = RadLogFile::Instance()->Size();
		if ( size >= separateFileSize ) 
		{
			// we try to open another log file.
			traceMutex.Wait();
			RadLogFile::Instance()->RunningOpenFile();
			traceMutex.Signal();
		}

		break;

	default:
		break;
	}

	//return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -