Files
itgmania212121/stepmania/src/RageLog.cpp
T

267 lines
6.6 KiB
C++
Raw Normal View History

2003-02-16 04:01:45 +00:00
#include "global.h"
2002-05-01 19:14:55 +00:00
/*
-----------------------------------------------------------------------------
Class: RageLog
Desc: See header.
2003-01-24 01:35:15 +00:00
Copyright (c) 2001-2003 by the person(s) listed below. All rights reserved.
2002-05-01 19:14:55 +00:00
Chris Danford
2003-01-24 01:35:15 +00:00
Glenn Maynard
2002-05-01 19:14:55 +00:00
-----------------------------------------------------------------------------
*/
2002-08-22 20:21:37 +00:00
#include "arch/ArchHooks/ArchHooks.h"
2002-05-01 19:14:55 +00:00
#include "RageLog.h"
#include "RageUtil.h"
#include "RageTimer.h"
#include "PrefsManager.h"
2002-05-01 19:14:55 +00:00
#include <fstream>
2003-02-14 07:18:00 +00:00
#include <time.h>
2002-06-14 22:25:22 +00:00
2002-05-01 19:14:55 +00:00
RageLog* LOG; // global and accessable from anywhere in the program
2003-01-24 01:35:15 +00:00
/* We have a couple log types and a couple logs.
*
* Traces are for very verbose debug information. Use them as much as you want.
*
* Warnings are for things that shouldn't happen, but can be dealt with. (If
* they can't be dealt with, use RageException::Throw, which will also send a
* warning.)
*
* Info is for important bits of information. These should be used selectively.
* Try to keep Info text dense; lots of information is fine, but try to keep
* it to a reasonable total length.
*
* log.txt receives all logs. This file can get rather large.
*
* info.txt receives warnings and infos. This file should be fairly small; small
* enough to be mailed without having to be edited or zipped, and small enough
* to be very easily read.
*
*/
2003-04-22 05:21:25 +00:00
/* Map data names to logged data.
*
* This lets us keep individual bits of changing information to be present
* in crash logs. For example, we want to know which file was being processed
* if we crash during a texture load. However, we don't want to log every
* load, since there are a huge number, even for log.txt. We only want to
* know the current one, if any.
*
* So, when a texture begins loading, we do:
* LOG->MapLog("TextureManager::Load", "Loading foo.png");
* and when it finishes loading without crashing,
* LOG->UnmapLog("TextureManager::Load");
*
* Each time a mapped log changes, we update a block of static text to be put
* in info.txt, so we see "Loading foo.png".
*
* The identifier is never displayed, so we can use a simple local object to
* map/unmap, using any mechanism to generate unique IDs. */
map<CString, CString> LogMaps;
2002-05-01 19:14:55 +00:00
// constants
#define LOG_FILE_NAME "log.txt"
2003-01-24 01:35:15 +00:00
#define INFO_FILE_NAME "info.txt"
2003-02-23 06:26:01 +00:00
#if defined(WIN32)
extern unsigned long version_num;
extern const char *version_time;
#endif
2003-01-24 01:35:15 +00:00
/* staticlog gets info.txt
* crashlog gets log.txt */
enum {
2003-02-17 06:34:43 +00:00
/* If this is set, the message will also be written to info.txt and
* will be flagged "important" when sent to HOOKS->Log. (info and warnings) */
WRITE_TO_INFO = 0x01,
/* Whether this line should be loud when written to log.txt (warnings). */
WRITE_LOUD = 0x02
2003-01-24 01:35:15 +00:00
};
2002-05-01 19:14:55 +00:00
RageLog::RageLog()
{
// delete old log files
2002-12-18 06:45:11 +00:00
remove( LOG_FILE_NAME );
2003-01-24 01:35:15 +00:00
remove( INFO_FILE_NAME );
2002-05-01 19:14:55 +00:00
// Open log file and leave it open.
2002-05-01 19:14:55 +00:00
m_fileLog = fopen( LOG_FILE_NAME, "w" );
2003-01-24 01:35:15 +00:00
m_fileInfo = fopen( INFO_FILE_NAME, "w" );
2002-05-01 19:14:55 +00:00
2002-11-16 09:12:55 +00:00
#if defined(_MSC_VER)
this->Trace( "Last compiled on %s.", __TIMESTAMP__ );
2002-11-16 09:12:55 +00:00
#endif
2003-02-14 07:18:00 +00:00
time_t cur_time;
time(&cur_time);
const struct tm *now = localtime(&cur_time);
this->Trace( "Log starting %.4d-%.2d-%.2d %.2d:%.2d:%.2d",
2003-02-14 07:18:00 +00:00
1900+now->tm_year, now->tm_mon, now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec );
2003-01-24 02:16:43 +00:00
this->Trace( "" );
2003-02-23 06:26:01 +00:00
#if defined(WIN32)
this->Info("Compiled %s (build %i)", version_time, version_num);
#endif
2002-05-01 19:14:55 +00:00
}
RageLog::~RageLog()
{
2003-04-22 05:21:25 +00:00
/* Add the mapped log data to info.txt. */
CString str;
for(map<CString, CString>::const_iterator i = LogMaps.begin(); i != LogMaps.end(); ++i)
str += ssprintf("%s\n", i->second.c_str());
fprintf( m_fileInfo, "%s", str.c_str() );
2003-05-27 00:49:05 +00:00
fprintf( m_fileLog, "\nStatics:\n%s", str.c_str() );
2003-04-22 05:21:25 +00:00
2002-05-01 19:14:55 +00:00
Flush();
2003-02-15 00:13:23 +00:00
HideConsole();
2003-01-24 01:35:15 +00:00
if(m_fileLog) fclose( m_fileLog );
if(m_fileInfo) fclose( m_fileInfo );
2002-05-01 19:14:55 +00:00
}
2002-05-29 09:47:24 +00:00
void RageLog::ShowConsole()
{
#if defined(WIN32) && !defined(_XBOX)
2002-05-29 09:47:24 +00:00
// create a new console window and attach standard handles
AllocConsole();
freopen("CONOUT$","wb",stdout);
freopen("CONOUT$","wb",stderr);
2003-01-24 01:35:15 +00:00
#endif
2002-05-29 09:47:24 +00:00
}
void RageLog::HideConsole()
{
#if defined(WIN32) && !defined(_XBOX)
2002-05-29 09:47:24 +00:00
FreeConsole();
2003-01-24 01:35:15 +00:00
#endif
2002-05-29 09:47:24 +00:00
}
void RageLog::Trace( const char *fmt, ...)
2002-05-01 19:14:55 +00:00
{
va_list va;
va_start(va, fmt);
CString sBuff = vssprintf( fmt, va );
va_end(va);
2002-05-01 19:14:55 +00:00
2003-01-24 01:35:15 +00:00
Write(0, sBuff);
2002-05-01 19:14:55 +00:00
}
2003-01-19 05:00:21 +00:00
/* Use this for more important information; it'll always be included
* in crash dumps. */
void RageLog::Info( const char *fmt, ...)
{
va_list va;
va_start(va, fmt);
CString sBuff = vssprintf( fmt, va );
va_end(va);
2003-01-24 01:35:15 +00:00
2003-02-17 06:34:43 +00:00
Write(WRITE_TO_INFO, sBuff);
2003-01-19 05:00:21 +00:00
}
void RageLog::Warn( const char *fmt, ...)
{
va_list va;
va_start(va, fmt);
CString sBuff = vssprintf( fmt, va );
va_end(va);
2003-04-25 00:01:35 +00:00
Write(WRITE_TO_INFO | WRITE_LOUD, ssprintf("WARNING: %s", sBuff.c_str()));
2003-01-24 01:35:15 +00:00
}
2003-02-17 06:34:43 +00:00
/* When */
2003-01-24 01:35:15 +00:00
void RageLog::Write( int where, CString str)
{
if( PREFSMAN && PREFSMAN->m_bTimestamping )
str = SecondsToTime(RageTimer::GetTimeSinceStart()) + ": " + str;
2003-02-17 06:34:43 +00:00
if( where&WRITE_TO_INFO && m_fileInfo )
2003-04-25 00:01:35 +00:00
fprintf(m_fileInfo, "%s\n", str.c_str() );
2003-01-24 23:24:14 +00:00
2003-02-17 06:34:43 +00:00
HOOKS->Log(str, where & WRITE_TO_INFO);
/* Only do this for log.txt and stdout. The other outputs are
* fairly quiet anyway, so the prepended "WARNING" makes them stand
* out well enough and this is just clutter. */
if( where & WRITE_LOUD )
{
str = ssprintf(
"/////////////////////////////////////////\n"
"%s\n"
"/////////////////////////////////////////",
2003-04-25 00:01:35 +00:00
str.c_str());
2003-02-17 06:34:43 +00:00
}
if( m_fileLog )
2003-04-25 00:01:35 +00:00
fprintf(m_fileLog, "%s\n", str.c_str() );
2003-01-24 01:35:15 +00:00
2003-04-25 00:01:35 +00:00
printf("%s\n", str.c_str() );
2003-01-24 01:35:15 +00:00
#ifdef DEBUG
Flush();
#else
2003-07-20 04:38:31 +00:00
if( (PREFSMAN && PREFSMAN->m_bDebugMode) || (where & WRITE_TO_INFO) )
2003-01-24 01:35:15 +00:00
Flush();
#endif
2002-05-01 19:14:55 +00:00
}
void RageLog::Flush()
{
fflush( m_fileLog );
2003-01-24 23:24:14 +00:00
fflush( m_fileInfo );
2002-05-01 19:14:55 +00:00
}
2003-04-22 05:21:25 +00:00
2003-07-22 05:05:39 +00:00
static char g_AdditionalLogStr[10240] = "";
static int g_AdditionalLogSize = 0;
2003-04-22 05:21:25 +00:00
void RageLog::UpdateMappedLog()
{
CString str;
for(map<CString, CString>::const_iterator i = LogMaps.begin(); i != LogMaps.end(); ++i)
str += ssprintf("%s\n", i->second.c_str());
2003-07-22 05:05:39 +00:00
g_AdditionalLogSize = min( sizeof(g_AdditionalLogStr), str.size() );
memcpy( g_AdditionalLogStr, str.c_str(), g_AdditionalLogSize );
/* XXX: deprecated */
2003-04-22 05:21:25 +00:00
HOOKS->AdditionalLog(str);
}
2003-07-22 05:05:39 +00:00
void RageLog::GetAdditionalLog( const char* &p, int &size )
{
p = g_AdditionalLogStr;
size = g_AdditionalLogSize;
}
2003-04-22 05:21:25 +00:00
void RageLog::MapLog(const CString &key, const char *fmt, ...)
{
va_list va;
va_start(va, fmt);
LogMaps[key] = vssprintf( fmt, va );
va_end(va);
}
void RageLog::UnmapLog(const CString &key)
{
LogMaps.erase(key);
}
2003-04-22 05:53:18 +00:00
2003-04-27 21:55:31 +00:00
Checkpoint_::Checkpoint_(CString key_, int n, const char *fmt, ...)
2003-04-22 05:53:18 +00:00
{
key = ssprintf("%s:%i", key_.c_str(), n);
va_list va;
va_start(va, fmt);
LOG->MapLog( key, vssprintf(fmt, va) );
va_end(va);
}
Checkpoint_::~Checkpoint_()
{
LOG->UnmapLog( key );
}