8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-22 23:23:02 +01:00

Merge pull request #6997 from red-soft-ru/master_trace_rotation_fix

Fixes for fbtrace log rotation
This commit is contained in:
Vlad Khorsun 2021-10-12 11:11:51 +03:00 committed by GitHub
commit 1550d5191b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 91 additions and 47 deletions

View File

@ -44,6 +44,7 @@ static const char* const SNAPSHOTS_FILE = "fb_snap_%s";
static const char* const TRACE_FILE = "fb" COMMON_FILE_PREFIX "_trace";
static const char* const USER_MAP_FILE = "fb" COMMON_FILE_PREFIX "_user_mapping";
static const char* const FB_TRACE_LOG_MUTEX = "fb_trace_log_mutex";
#ifdef UNIX
static const char* const INIT_FILE = "fb_init";

View File

@ -26,7 +26,10 @@
*/
#include "PluginLogWriter.h"
#include "../common/isc_proto.h"
#include "../common/classes/init.h"
#include "../common/ThreadStart.h"
#include "../common/file_params.h"
#include "../common/classes/RefMutex.h"
#include "../common/os/os_utils.h"
@ -50,18 +53,36 @@ void strerror_r(int err, char* buf, size_t bufSize)
}
#endif
void getMappedFileName(PathName& file, PathName& mapFile)
{
const ULONG hash = file.hash(0xFFFFFFFF);
mapFile.printf("%s_%08x", FB_TRACE_LOG_MUTEX, hash);
}
PluginLogWriter::PluginLogWriter(const char* fileName, size_t maxSize) :
m_fileName(*getDefaultMemoryPool()),
m_fileHandle(-1),
m_maxSize(maxSize)
m_maxSize(maxSize),
m_sharedMemory(NULL)
{
m_fileName = fileName;
#ifdef WIN_NT
PathName mutexName("fb_mutex_");
mutexName.append(m_fileName);
PathName logFile(fileName);
PathName mapFile;
getMappedFileName(logFile, mapFile);
checkMutex("init", ISC_mutex_init(&m_mutex, mutexName.c_str()));
try
{
m_sharedMemory.reset(FB_NEW_POOL(getPool())
SharedMemory<PluginLogWriterHeader>(mapFile.c_str(), sizeof(PluginLogWriterHeader), this));
}
catch (const Exception& ex)
{
iscLogException("PluginLogWriter: Cannot initialize the shared memory region", ex);
throw;
}
#ifdef WIN_NT
Guard guard(this);
#endif
@ -75,10 +96,6 @@ PluginLogWriter::~PluginLogWriter()
if (m_fileHandle != -1)
::close(m_fileHandle);
#ifdef WIN_NT
ISC_mutex_fini(&m_mutex);
#endif
}
SINT64 PluginLogWriter::seekToEnd()
@ -122,6 +139,8 @@ FB_SIZE_T PluginLogWriter::write(const void* buf, FB_SIZE_T size)
#ifdef WIN_NT
Guard guard(this);
#else
Guard guard(m_maxSize ? this : 0);
#endif
if (m_fileHandle < 0)
@ -136,23 +155,41 @@ FB_SIZE_T PluginLogWriter::write(const void* buf, FB_SIZE_T size)
if (m_maxSize && (fileSize > m_maxSize))
{
const TimeStamp stamp(TimeStamp::getCurrentTimeStamp());
struct tm times;
stamp.decode(&times);
PathName newName;
const FB_SIZE_T last_dot_pos = m_fileName.rfind(".");
if (last_dot_pos > 0)
while (true)
{
PathName log_name = m_fileName.substr(0, last_dot_pos);
PathName log_ext = m_fileName.substr(last_dot_pos + 1, m_fileName.length());
newName.printf("%s.%04d-%02d-%02dT%02d-%02d-%02d.%s", log_name.c_str(), times.tm_year + 1900,
times.tm_mon + 1, times.tm_mday, times.tm_hour, times.tm_min, times.tm_sec, log_ext.c_str());
}
else
{
newName.printf("%s.%04d-%02d-%02dT%02d-%02d-%02d", m_fileName.c_str(), times.tm_year + 1900,
times.tm_mon + 1, times.tm_mday, times.tm_hour, times.tm_min, times.tm_sec);
const TimeStamp stamp(TimeStamp::getCurrentTimeStamp());
struct tm times;
int fractions;
stamp.decode(&times, &fractions);
const FB_SIZE_T last_dot_pos = m_fileName.rfind(".");
if (last_dot_pos > 0)
{
PathName log_name = m_fileName.substr(0, last_dot_pos);
PathName log_ext = m_fileName.substr(last_dot_pos + 1, m_fileName.length());
newName.printf("%s.%04d-%02d-%02dT%02d-%02d-%02d.%04d.%s", log_name.c_str(), times.tm_year + 1900,
times.tm_mon + 1, times.tm_mday, times.tm_hour, times.tm_min, times.tm_sec, fractions, log_ext.c_str());
}
else
{
newName.printf("%s.%04d-%02d-%02dT%02d-%02d-%02d.%04d", m_fileName.c_str(), times.tm_year + 1900,
times.tm_mon + 1, times.tm_mday, times.tm_hour, times.tm_min, times.tm_sec, fractions);
}
// Check if the file with the given name exists. If it doesn't, break the loop.
struct stat st;
if (stat(newName.c_str(), &st))
{
// errno == ENOENT is expected here. But if it's another error, we can still
// break the loop and try to rename the file. For example, if there is a
// problem with permissions, it will be caught on MoveFile/rename call.
break;
}
Thread::sleep(10);
}
#ifdef WIN_NT
@ -221,31 +258,28 @@ void PluginLogWriter::checkErrno(const char* operation)
operation, m_fileName.c_str(), strErr);
}
#ifdef WIN_NT
void PluginLogWriter::checkMutex(const TEXT* string, int state)
void PluginLogWriter::mutexBug(int state, const TEXT* string)
{
if (state)
{
TEXT msg[BUFFER_TINY];
TEXT msg[BUFFER_TINY];
sprintf(msg, "PluginLogWriter: mutex %s error, status = %d", string, state);
gds__log(msg);
sprintf(msg, "PluginLogWriter: mutex %s error, status = %d", string, state);
fb_utils::logAndDie(msg);
}
fprintf(stderr, "%s\n", msg);
exit(FINI_ERROR);
}
bool PluginLogWriter::initialize(SharedMemoryBase* sm, bool init)
{
return true;
}
void PluginLogWriter::lock()
{
checkMutex("lock", ISC_mutex_lock(&m_mutex));
m_sharedMemory->mutexLock();
}
void PluginLogWriter::unlock()
{
checkMutex("unlock", ISC_mutex_unlock(&m_mutex));
m_sharedMemory->mutexUnlock();
}
#endif // WIN_NT
const unsigned int IDLE_TIMEOUT = 30; // seconds

View File

@ -48,8 +48,14 @@
#include <sys/stat.h>
// Empty header. We need it to get shared mutex using SharedMemory
struct PluginLogWriterHeader : public Firebird::MemoryHeader
{
};
class PluginLogWriter FB_FINAL :
public Firebird::RefCntIface<Firebird::ITraceLogWriterImpl<PluginLogWriter, Firebird::CheckStatusWrapper> >
public Firebird::RefCntIface<Firebird::ITraceLogWriterImpl<PluginLogWriter, Firebird::CheckStatusWrapper> >,
public Firebird::IpcObject
{
public:
PluginLogWriter(const char* fileName, size_t maxSize);
@ -73,34 +79,37 @@ private:
// same file simultaneously, therefore we used our fastMutex for this
// purposes. On Posix's platforms we honour O_APPEND flag which works
// better as in this case syncronization is performed by OS kernel itself.
#ifdef WIN_NT
static void checkMutex(const TEXT*, int);
// Mutex on Posix is needed to rotate log file.
void mutexBug(int osErrorCode, const char* text);
bool initialize(Firebird::SharedMemoryBase*, bool);
void lock();
void unlock();
struct Firebird::mtx m_mutex;
class Guard
{
public:
explicit Guard(PluginLogWriter* log) : m_log(*log)
explicit Guard(PluginLogWriter* log) : m_log(log)
{
m_log.lock();
if (m_log)
m_log->lock();
}
~Guard()
{
m_log.unlock();
if (m_log)
m_log->unlock();
}
private:
PluginLogWriter& m_log;
PluginLogWriter* m_log;
};
#endif
Firebird::PathName m_fileName;
int m_fileHandle;
size_t m_maxSize;
Firebird::AutoPtr<Firebird::SharedMemory<PluginLogWriterHeader> > m_sharedMemory;
typedef Firebird::TimerImpl IdleTimer;
Firebird::RefPtr<IdleTimer> m_idleTimer;