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:
commit
1550d5191b
@ -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";
|
||||||
|
@ -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(×);
|
|
||||||
|
|
||||||
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(×, &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
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user