add log file writing
This commit is contained in:
parent
d897ac32b0
commit
51ea3cec2a
|
@ -23,6 +23,7 @@
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include "winStuff.h"
|
#include "winStuff.h"
|
||||||
#define CONFIG_FILE "\\furnace.cfg"
|
#define CONFIG_FILE "\\furnace.cfg"
|
||||||
|
#define LOG_FILE "\\furnace.log"
|
||||||
#else
|
#else
|
||||||
#ifdef __HAIKU__
|
#ifdef __HAIKU__
|
||||||
#include <support/SupportDefs.h>
|
#include <support/SupportDefs.h>
|
||||||
|
|
|
@ -4221,7 +4221,7 @@ bool DivEngine::deinitAudioBackend(bool dueToSwitchMaster) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DivEngine::init() {
|
void DivEngine::preInit() {
|
||||||
// register systems
|
// register systems
|
||||||
if (!systemsRegistered) registerSystems();
|
if (!systemsRegistered) registerSystems();
|
||||||
|
|
||||||
|
@ -4229,8 +4229,13 @@ bool DivEngine::init() {
|
||||||
initConfDir();
|
initConfDir();
|
||||||
logD("config path: %s",configPath.c_str());
|
logD("config path: %s",configPath.c_str());
|
||||||
|
|
||||||
loadConf();
|
String logPath=configPath+DIR_SEPARATOR_STR+"furnace.log";
|
||||||
|
startLogFile(logPath.c_str());
|
||||||
|
|
||||||
|
loadConf();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DivEngine::init() {
|
||||||
loadSampleROMs();
|
loadSampleROMs();
|
||||||
|
|
||||||
// set default system preset
|
// set default system preset
|
||||||
|
|
|
@ -1012,6 +1012,9 @@ class DivEngine {
|
||||||
// quit dispatch
|
// quit dispatch
|
||||||
void quitDispatch();
|
void quitDispatch();
|
||||||
|
|
||||||
|
// pre-initialize the engine.
|
||||||
|
void preInit();
|
||||||
|
|
||||||
// initialize the engine.
|
// initialize the engine.
|
||||||
bool init();
|
bool init();
|
||||||
|
|
||||||
|
|
121
src/log.cpp
121
src/log.cpp
|
@ -18,6 +18,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ta-log.h"
|
#include "ta-log.h"
|
||||||
|
#include <thread>
|
||||||
|
#include <condition_variable>
|
||||||
|
|
||||||
#ifdef IS_MOBILE
|
#ifdef IS_MOBILE
|
||||||
int logLevel=LOGLEVEL_TRACE;
|
int logLevel=LOGLEVEL_TRACE;
|
||||||
|
@ -25,11 +27,54 @@ int logLevel=LOGLEVEL_TRACE;
|
||||||
int logLevel=LOGLEVEL_INFO;
|
int logLevel=LOGLEVEL_INFO;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
FILE* logFile;
|
||||||
|
char* logFileBuf;
|
||||||
|
unsigned int logFilePosI=0;
|
||||||
|
unsigned int logFilePosO=0;
|
||||||
|
std::thread* logFileThread;
|
||||||
|
std::mutex logFileLock;
|
||||||
|
std::mutex logFileLockI;
|
||||||
|
std::condition_variable logFileNotify;
|
||||||
|
bool logFileAvail=false;
|
||||||
|
|
||||||
std::atomic<unsigned short> logPosition;
|
std::atomic<unsigned short> logPosition;
|
||||||
|
|
||||||
LogEntry logEntries[TA_LOG_SIZE];
|
LogEntry logEntries[TA_LOG_SIZE];
|
||||||
|
|
||||||
static constexpr unsigned int TA_LOG_MASK=TA_LOG_SIZE-1;
|
static constexpr unsigned int TA_LOG_MASK=TA_LOG_SIZE-1;
|
||||||
|
static constexpr unsigned int TA_LOGFILE_BUF_MASK=TA_LOGFILE_BUF_SIZE-1;
|
||||||
|
|
||||||
|
const char* logTypes[5]={
|
||||||
|
"ERROR",
|
||||||
|
"warning",
|
||||||
|
"info",
|
||||||
|
"debug",
|
||||||
|
"trace"
|
||||||
|
};
|
||||||
|
|
||||||
|
void appendLogBuf(const char* msg, size_t len) {
|
||||||
|
logFileLockI.lock();
|
||||||
|
|
||||||
|
int remaining=logFilePosO-logFilePosI;
|
||||||
|
if (remaining<=0) remaining+=TA_LOGFILE_BUF_SIZE;
|
||||||
|
|
||||||
|
if (len>=(unsigned int)remaining) {
|
||||||
|
printf("line too long to fit in log buffer!\n");
|
||||||
|
logFileLockI.unlock();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((logFilePosI+len)>=TA_LOGFILE_BUF_SIZE) {
|
||||||
|
size_t firstWrite=TA_LOGFILE_BUF_SIZE-logFilePosI;
|
||||||
|
memcpy(logFileBuf+logFilePosI,msg,firstWrite);
|
||||||
|
memcpy(logFileBuf,msg+firstWrite,len-firstWrite);
|
||||||
|
} else {
|
||||||
|
memcpy(logFileBuf+logFilePosI,msg,len);
|
||||||
|
}
|
||||||
|
|
||||||
|
logFilePosI=(logFilePosI+len)&TA_LOGFILE_BUF_MASK;
|
||||||
|
logFileLockI.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
int writeLog(int level, const char* msg, fmt::printf_args args) {
|
int writeLog(int level, const char* msg, fmt::printf_args args) {
|
||||||
time_t thisMakesNoSense=time(NULL);
|
time_t thisMakesNoSense=time(NULL);
|
||||||
|
@ -54,6 +99,20 @@ int writeLog(int level, const char* msg, fmt::printf_args args) {
|
||||||
logEntries[pos].loglevel=level;
|
logEntries[pos].loglevel=level;
|
||||||
logEntries[pos].ready=true;
|
logEntries[pos].ready=true;
|
||||||
|
|
||||||
|
// write to log file
|
||||||
|
if (logFileAvail) {
|
||||||
|
std::string toWrite=fmt::sprintf(
|
||||||
|
"%02d:%02d:%02d [%s] %s\n",
|
||||||
|
logEntries[pos].time.tm_hour,
|
||||||
|
logEntries[pos].time.tm_min,
|
||||||
|
logEntries[pos].time.tm_sec,
|
||||||
|
logTypes[logEntries[pos].loglevel],
|
||||||
|
logEntries[pos].text
|
||||||
|
);
|
||||||
|
appendLogBuf(toWrite.c_str(),toWrite.size());
|
||||||
|
logFileNotify.notify_one();
|
||||||
|
}
|
||||||
|
|
||||||
if (logLevel<level) return 0;
|
if (logLevel<level) return 0;
|
||||||
switch (level) {
|
switch (level) {
|
||||||
case LOGLEVEL_ERROR:
|
case LOGLEVEL_ERROR:
|
||||||
|
@ -71,8 +130,70 @@ int writeLog(int level, const char* msg, fmt::printf_args args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void initLog() {
|
void initLog() {
|
||||||
|
// initalize log buffer
|
||||||
logPosition=0;
|
logPosition=0;
|
||||||
for (int i=0; i<TA_LOG_SIZE; i++) {
|
for (int i=0; i<TA_LOG_SIZE; i++) {
|
||||||
logEntries[i].text.reserve(128);
|
logEntries[i].text.reserve(128);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// initialize log to file thread
|
||||||
|
logFileAvail=false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _logFileThread() {
|
||||||
|
std::unique_lock<std::mutex> lock(logFileLock);
|
||||||
|
while (true) {
|
||||||
|
unsigned int logFilePosICopy=logFilePosI;
|
||||||
|
if (logFilePosICopy!=logFilePosO) {
|
||||||
|
// write
|
||||||
|
if (logFilePosO>logFilePosICopy) {
|
||||||
|
fwrite(logFileBuf+logFilePosO,1,TA_LOGFILE_BUF_SIZE-logFilePosO,logFile);
|
||||||
|
logFilePosO=0;
|
||||||
|
} else {
|
||||||
|
fwrite(logFileBuf+logFilePosO,1,logFilePosICopy-logFilePosO,logFile);
|
||||||
|
logFilePosO=logFilePosICopy;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// wait
|
||||||
|
if (!logFileAvail) break;
|
||||||
|
fflush(logFile);
|
||||||
|
logFileNotify.wait(lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool startLogFile(const char* path) {
|
||||||
|
if (logFileAvail) return true;
|
||||||
|
|
||||||
|
// rotate log file if possible
|
||||||
|
|
||||||
|
// open log file
|
||||||
|
if ((logFile=fopen(path,"w+"))==NULL) {
|
||||||
|
logFileAvail=false;
|
||||||
|
logW("could not open log file! (%s)",strerror(errno));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
logFileBuf=new char[TA_LOGFILE_BUF_SIZE];
|
||||||
|
logFilePosI=0;
|
||||||
|
logFilePosO=0;
|
||||||
|
logFileAvail=true;
|
||||||
|
|
||||||
|
logFileThread=new std::thread(_logFileThread);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool finishLogFile() {
|
||||||
|
if (!logFileAvail) return false;
|
||||||
|
|
||||||
|
logFileAvail=false;
|
||||||
|
|
||||||
|
// flush
|
||||||
|
logFileLockI.lock();
|
||||||
|
logFileNotify.notify_one();
|
||||||
|
logFileThread->join();
|
||||||
|
logFileLockI.unlock();
|
||||||
|
|
||||||
|
fclose(logFile);
|
||||||
|
return true;
|
||||||
}
|
}
|
|
@ -416,7 +416,11 @@ int main(int argc, char** argv) {
|
||||||
logI("usage: %s file",argv[0]);
|
logI("usage: %s file",argv[0]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
logI("Furnace version " DIV_VERSION ".");
|
logI("Furnace version " DIV_VERSION ".");
|
||||||
|
|
||||||
|
e.preInit();
|
||||||
|
|
||||||
if (!fileName.empty()) {
|
if (!fileName.empty()) {
|
||||||
logI("loading module...");
|
logI("loading module...");
|
||||||
FILE* f=ps_fopen(fileName.c_str(),"rb");
|
FILE* f=ps_fopen(fileName.c_str(),"rb");
|
||||||
|
@ -584,6 +588,8 @@ int main(int argc, char** argv) {
|
||||||
logI("stopping engine.");
|
logI("stopping engine.");
|
||||||
e.quit();
|
e.quit();
|
||||||
|
|
||||||
|
finishLogFile();
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (coResult==S_OK || coResult==S_FALSE) {
|
if (coResult==S_OK || coResult==S_FALSE) {
|
||||||
CoUninitialize();
|
CoUninitialize();
|
||||||
|
|
|
@ -35,6 +35,9 @@
|
||||||
// this has to be a power of 2
|
// this has to be a power of 2
|
||||||
#define TA_LOG_SIZE 2048
|
#define TA_LOG_SIZE 2048
|
||||||
|
|
||||||
|
// this as well
|
||||||
|
#define TA_LOGFILE_BUF_SIZE 65536
|
||||||
|
|
||||||
extern int logLevel;
|
extern int logLevel;
|
||||||
|
|
||||||
extern std::atomic<unsigned short> logPosition;
|
extern std::atomic<unsigned short> logPosition;
|
||||||
|
@ -76,4 +79,6 @@ template<typename... T> int logE(const char* msg, const T&... args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void initLog();
|
void initLog();
|
||||||
|
bool startLogFile(const char* path);
|
||||||
|
bool finishLogFile();
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue