8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-23 06:03: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 TRACE_FILE = "fb" COMMON_FILE_PREFIX "_trace";
static const char* const USER_MAP_FILE = "fb" COMMON_FILE_PREFIX "_user_mapping"; 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 #ifdef UNIX
static const char* const INIT_FILE = "fb_init"; static const char* const INIT_FILE = "fb_init";

View File

@ -26,7 +26,10 @@
*/ */
#include "PluginLogWriter.h" #include "PluginLogWriter.h"
#include "../common/isc_proto.h"
#include "../common/classes/init.h" #include "../common/classes/init.h"
#include "../common/ThreadStart.h"
#include "../common/file_params.h"
#include "../common/classes/RefMutex.h" #include "../common/classes/RefMutex.h"
#include "../common/os/os_utils.h" #include "../common/os/os_utils.h"
@ -50,18 +53,36 @@ void strerror_r(int err, char* buf, size_t bufSize)
} }
#endif #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) : PluginLogWriter::PluginLogWriter(const char* fileName, size_t maxSize) :
m_fileName(*getDefaultMemoryPool()), m_fileName(*getDefaultMemoryPool()),
m_fileHandle(-1), m_fileHandle(-1),
m_maxSize(maxSize) m_maxSize(maxSize),
m_sharedMemory(NULL)
{ {
m_fileName = fileName; m_fileName = fileName;
#ifdef WIN_NT PathName logFile(fileName);
PathName mutexName("fb_mutex_"); PathName mapFile;
mutexName.append(m_fileName); 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); Guard guard(this);
#endif #endif
@ -75,10 +96,6 @@ PluginLogWriter::~PluginLogWriter()
if (m_fileHandle != -1) if (m_fileHandle != -1)
::close(m_fileHandle); ::close(m_fileHandle);
#ifdef WIN_NT
ISC_mutex_fini(&m_mutex);
#endif
} }
SINT64 PluginLogWriter::seekToEnd() SINT64 PluginLogWriter::seekToEnd()
@ -122,6 +139,8 @@ FB_SIZE_T PluginLogWriter::write(const void* buf, FB_SIZE_T size)
#ifdef WIN_NT #ifdef WIN_NT
Guard guard(this); Guard guard(this);
#else
Guard guard(m_maxSize ? this : 0);
#endif #endif
if (m_fileHandle < 0) 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)) if (m_maxSize && (fileSize > m_maxSize))
{ {
const TimeStamp stamp(TimeStamp::getCurrentTimeStamp());
struct tm times;
stamp.decode(&times);
PathName newName; 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); const TimeStamp stamp(TimeStamp::getCurrentTimeStamp());
PathName log_ext = m_fileName.substr(last_dot_pos + 1, m_fileName.length()); struct tm times;
newName.printf("%s.%04d-%02d-%02dT%02d-%02d-%02d.%s", log_name.c_str(), times.tm_year + 1900, int fractions;
times.tm_mon + 1, times.tm_mday, times.tm_hour, times.tm_min, times.tm_sec, log_ext.c_str()); stamp.decode(&times, &fractions);
}
else const FB_SIZE_T last_dot_pos = m_fileName.rfind(".");
{ if (last_dot_pos > 0)
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); 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 #ifdef WIN_NT
@ -221,31 +258,28 @@ void PluginLogWriter::checkErrno(const char* operation)
operation, m_fileName.c_str(), strErr); operation, m_fileName.c_str(), strErr);
} }
#ifdef WIN_NT void PluginLogWriter::mutexBug(int state, const TEXT* string)
void PluginLogWriter::checkMutex(const TEXT* string, int state)
{ {
if (state) TEXT msg[BUFFER_TINY];
{
TEXT msg[BUFFER_TINY];
sprintf(msg, "PluginLogWriter: mutex %s error, status = %d", string, state); sprintf(msg, "PluginLogWriter: mutex %s error, status = %d", string, state);
gds__log(msg); fb_utils::logAndDie(msg);
}
fprintf(stderr, "%s\n", msg); bool PluginLogWriter::initialize(SharedMemoryBase* sm, bool init)
exit(FINI_ERROR); {
} return true;
} }
void PluginLogWriter::lock() void PluginLogWriter::lock()
{ {
checkMutex("lock", ISC_mutex_lock(&m_mutex)); m_sharedMemory->mutexLock();
} }
void PluginLogWriter::unlock() void PluginLogWriter::unlock()
{ {
checkMutex("unlock", ISC_mutex_unlock(&m_mutex)); m_sharedMemory->mutexUnlock();
} }
#endif // WIN_NT
const unsigned int IDLE_TIMEOUT = 30; // seconds const unsigned int IDLE_TIMEOUT = 30; // seconds

View File

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