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

Suspend trace session when log is full despite of log reader [in]activity.

This commit is contained in:
hvlad 2009-02-11 15:24:12 +00:00
parent 2c3d4018da
commit 22107f0ba3
4 changed files with 111 additions and 72 deletions

View File

@ -47,12 +47,10 @@ using namespace Firebird;
namespace Jrd {
/// TraceLogImpl
const size_t MAX_LOG_FILE_SIZE = 1024 * 1024;
const unsigned int MAX_FILE_NUM = (unsigned int) -1;
TraceLogImpl::TraceLogImpl(MemoryPool& pool, const PathName& fileName, bool reader) :
TraceLog::TraceLog(MemoryPool& pool, const PathName& fileName, bool reader) :
m_baseFileName(pool)
{
m_base = 0;
@ -64,7 +62,7 @@ TraceLogImpl::TraceLogImpl(MemoryPool& pool, const PathName& fileName, bool read
ISC_map_file(status, fileName.c_str(), initShMem, this, sizeof(ShMemHeader), &m_handle);
if (!m_base)
{
iscLogStatus("Cannot initialize the shared memory region", status);
iscLogStatus("TraceLog: cannot initialize the shared memory region", status);
status_exception::raise(status);
}
@ -79,7 +77,7 @@ TraceLogImpl::TraceLogImpl(MemoryPool& pool, const PathName& fileName, bool read
m_fileHandle = openFile(m_fileNum);
}
TraceLogImpl::~TraceLogImpl()
TraceLog::~TraceLog()
{
::close(m_fileHandle);
@ -105,7 +103,7 @@ TraceLogImpl::~TraceLogImpl()
}
}
int TraceLogImpl::openFile(int fileNum)
int TraceLog::openFile(int fileNum)
{
PathName fileName;
fileName.printf("%s.%07ld", m_baseFileName.c_str(), fileNum);
@ -122,14 +120,14 @@ int TraceLogImpl::openFile(int fileNum)
return file;
}
int TraceLogImpl::removeFile(int fileNum)
int TraceLog::removeFile(int fileNum)
{
PathName fileName;
fileName.printf("%s.%07ld", m_baseFileName.c_str(), fileNum);
return unlink(fileName.c_str());
}
size_t TraceLogImpl::read(void* buf, size_t size)
size_t TraceLog::read(void* buf, size_t size)
{
fb_assert(m_reader);
@ -141,6 +139,7 @@ size_t TraceLogImpl::read(void* buf, size_t size)
if (reads == 0)
{
// EOF reached, check the reason
const off_t len = lseek(m_fileHandle, 0, SEEK_CUR);
if (len >= MAX_LOG_FILE_SIZE)
{
@ -174,7 +173,7 @@ size_t TraceLogImpl::read(void* buf, size_t size)
return (size - readLeft);
}
size_t TraceLogImpl::write(const void* buf, size_t size)
size_t TraceLog::write(const void* buf, size_t size)
{
fb_assert(!m_reader);
@ -220,19 +219,19 @@ size_t TraceLogImpl::write(const void* buf, size_t size)
return size - writeLeft;
}
size_t TraceLogImpl::getApproxLogSize() const
size_t TraceLog::getApproxLogSize() const
{
return (m_base->writeFileNum - m_base->readFileNum + 1) *
(MAX_LOG_FILE_SIZE / (1024 * 1024));
}
void TraceLogImpl::checkMutex(const TEXT* string, int state)
void TraceLog::checkMutex(const TEXT* string, int state)
{
if (state)
{
TEXT msg[BUFFER_TINY];
sprintf(msg, "TRACE: mutex %s error, status = %d", string, state);
sprintf(msg, "TraceLog: mutex %s error, status = %d", string, state);
gds__log(msg);
fprintf(stderr, "%s\n", msg);
@ -240,9 +239,9 @@ void TraceLogImpl::checkMutex(const TEXT* string, int state)
}
}
void TraceLogImpl::initShMem(void* arg, SH_MEM_T* shmemData, bool initialize)
void TraceLog::initShMem(void* arg, SH_MEM_T* shmemData, bool initialize)
{
TraceLogImpl* log = (TraceLogImpl*) arg;
TraceLog* log = (TraceLog*) arg;
#ifdef WIN_NT
checkMutex("init", ISC_mutex_init(&log->m_mutex, shmemData->sh_mem_name));
@ -261,7 +260,7 @@ void TraceLogImpl::initShMem(void* arg, SH_MEM_T* shmemData, bool initialize)
}
}
void TraceLogImpl::lock()
void TraceLog::lock()
{
#ifdef WIN_NT
checkMutex("lock", ISC_mutex_lock(&m_mutex));
@ -270,7 +269,7 @@ void TraceLogImpl::lock()
#endif
}
void TraceLogImpl::unlock()
void TraceLog::unlock()
{
#ifdef WIN_NT
checkMutex("unlock", ISC_mutex_unlock(&m_mutex));

View File

@ -29,21 +29,18 @@
#define TRACE_LOG
#include "../../common/classes/fb_string.h"
#include "../../jrd/ntrace.h"
#include "../../jrd/isc.h"
namespace Jrd {
class TraceLogImpl : public TraceLogWriter
class TraceLog
{
public:
TraceLogImpl(Firebird::MemoryPool& pool, const Firebird::PathName& fileName, bool reader);
virtual ~TraceLogImpl();
TraceLog(Firebird::MemoryPool& pool, const Firebird::PathName& fileName, bool reader);
virtual ~TraceLog();
size_t read(void* buf, size_t size);
virtual size_t write(const void* buf, size_t size);
virtual void release()
{ delete this; }
size_t write(const void* buf, size_t size);
// returns approximate log size in MB
size_t getApproxLogSize() const;
@ -78,25 +75,22 @@ private:
int m_fileHandle;
bool m_reader;
friend class TraceLogGuard;
};
class TraceLogGuard
{
public:
explicit TraceLogGuard(TraceLogImpl* log) : m_log(*log)
class TraceLogGuard
{
m_log.lock();
}
public:
explicit TraceLogGuard(TraceLog* log) : m_log(*log)
{
m_log.lock();
}
~TraceLogGuard()
{
m_log.unlock();
}
~TraceLogGuard()
{
m_log.unlock();
}
private:
TraceLogImpl& m_log;
private:
TraceLog& m_log;
};
};

View File

@ -392,6 +392,64 @@ const char* TraceTriggerImpl::getRelationName()
}
/// TraceLogWriterImpl
class TraceLogWriterImpl : public TraceLogWriter
{
public:
TraceLogWriterImpl(MemoryPool& pool, const TraceSession& session) :
m_log(pool, session.ses_logfile, false),
m_sesId(session.ses_id)
{
m_maxSize = Config::getMaxUserTraceLogSize();
}
virtual size_t write(const void* buf, size_t size);
virtual void release()
{
delete this;
}
private:
TraceLog m_log;
ULONG m_sesId;
size_t m_maxSize;
};
size_t TraceLogWriterImpl::write(const void* buf, size_t size)
{
// comparison is in MB
if (m_log.getApproxLogSize() <= m_maxSize)
return m_log.write(buf, size);
ConfigStorage* storage = TraceManager::getStorage();
StorageGuard guard(storage);
TraceSession session(*getDefaultMemoryPool());
storage->restart();
while (storage->getNextSession(session))
{
if (session.ses_id == m_sesId)
{
if (!(session.ses_flags & trs_log_full))
{
// suspend session
session.ses_flags |= trs_log_full;
storage->updateSession(session);
string s;
s.printf("\n--- Session %d is suspended as its log is full ---\n", m_sesId);
m_log.write(s.c_str(), s.length());
}
break;
}
}
// report successful write
return size;
}
/// TraceInitInfoImpl
const char* TraceInitInfoImpl::getFirebirdRootDirectory()
@ -404,7 +462,7 @@ TraceLogWriter* TraceInitInfoImpl::getLogWriter()
if (!m_logWriter && !m_session.ses_logfile.empty())
{
MemoryPool &pool = *getDefaultMemoryPool();
m_logWriter = FB_NEW(pool) TraceLogImpl(pool, m_session.ses_logfile, false);
m_logWriter = FB_NEW(pool) TraceLogWriterImpl(pool, m_session);
}
return m_logWriter;
}

View File

@ -67,7 +67,7 @@ public:
private:
bool changeFlags(ULONG id, int setFlags, int clearFlags);
bool checkAlive(ULONG sesId);
bool checkAliveAndFlags(ULONG sesId, int& flags);
Service& m_svc;
string m_user;
@ -84,8 +84,7 @@ void TraceSvcJrd::setAttachInfo(const string& /*service_name*/, const string& us
void TraceSvcJrd::startSession(TraceSession& session, bool interactive)
{
TraceManager* mgr = m_svc.getTraceManager();
ConfigStorage* storage = mgr->getStorage();
ConfigStorage* storage = TraceManager::getStorage();
{ // scope
StorageGuard guard(storage);
@ -106,7 +105,6 @@ void TraceSvcJrd::startSession(TraceSession& session, bool interactive)
GuidToString(buff, &guid);
session.ses_logfile.insert(0, "fb_trace.");
// session.ses_logfile = TempFile::create("fb_trace_");
}
storage->addSession(session);
@ -122,7 +120,6 @@ void TraceSvcJrd::startSession(TraceSession& session, bool interactive)
StorageGuard guard(storage);
storage->removeSession(session.ses_id);
}
// unlink(session.ses_logfile.c_str());
}
else {
m_svc.printf("Trace session ID %ld started\n", session.ses_id);
@ -132,9 +129,8 @@ void TraceSvcJrd::startSession(TraceSession& session, bool interactive)
void TraceSvcJrd::stopSession(ULONG id)
{
m_svc.started();
TraceManager* mgr = m_svc.getTraceManager();
ConfigStorage* storage = mgr->getStorage();
ConfigStorage* storage = TraceManager::getStorage();
StorageGuard guard(storage);
storage->restart();
@ -177,10 +173,7 @@ void TraceSvcJrd::setActive(ULONG id, bool active)
bool TraceSvcJrd::changeFlags(ULONG id, int setFlags, int clearFlags)
{
m_svc.started();
TraceManager* mgr = m_svc.getTraceManager();
ConfigStorage* storage = mgr->getStorage();
ConfigStorage* storage = TraceManager::getStorage();
StorageGuard guard(storage);
storage->restart();
@ -193,10 +186,14 @@ bool TraceSvcJrd::changeFlags(ULONG id, int setFlags, int clearFlags)
if (m_admin || m_user == session.ses_user)
{
const int saveFlags = session.ses_flags;
session.ses_flags |= setFlags;
session.ses_flags &= ~clearFlags;
storage->updateSession(session);
if (saveFlags != session.ses_flags) {
storage->updateSession(session);
}
return true;
}
else
@ -214,9 +211,7 @@ void TraceSvcJrd::listSessions()
{
m_svc.started();
TraceManager* mgr = m_svc.getTraceManager();
ConfigStorage* storage = mgr->getStorage();
ConfigStorage* storage = TraceManager::getStorage();
StorageGuard guard(storage);
storage->restart();
@ -266,9 +261,6 @@ void TraceSvcJrd::listSessions()
void TraceSvcJrd::readSession(TraceSession& session)
{
// Unused, let's assume StorageGuard not needed.
//TraceManager* mgr = m_svc.getTraceManager();
//ConfigStorage* storage = mgr->getStorage();
const size_t maxLogSize = Config::getMaxUserTraceLogSize(); // in MB
if (session.ses_logfile.empty())
@ -278,16 +270,16 @@ void TraceSvcJrd::readSession(TraceSession& session)
}
MemoryPool& pool = *getDefaultMemoryPool();
AutoPtr<TraceLogImpl> log(FB_NEW(pool) TraceLogImpl(pool, session.ses_logfile, true));
AutoPtr<TraceLog> log(FB_NEW(pool) TraceLog(pool, session.ses_logfile, true));
bool logFull = false;
UCHAR buff[1024];
while (!m_svc.finished() && checkAlive(session.ses_id))
int flags = session.ses_flags;
while (!m_svc.finished() && checkAliveAndFlags(session.ses_id, flags))
{
size_t len = log->read(buff, sizeof(buff));
if (!len)
{
if (!checkAlive(session.ses_id))
if (!checkAliveAndFlags(session.ses_id, flags))
break;
THD_sleep(250);
@ -296,24 +288,19 @@ void TraceSvcJrd::readSession(TraceSession& session)
{
m_svc.putBytes(buff, len);
if (logFull && log->getApproxLogSize() <= maxLogSize)
const bool logFull = (flags & trs_log_full);
if (logFull && log->getApproxLogSize() <= maxLogSize)
{
// resume session
changeFlags(session.ses_id, 0, trs_log_full);
logFull = false;
}
else if (!logFull && log->getApproxLogSize() > maxLogSize)
{
changeFlags(session.ses_id, trs_log_full, 0);
logFull = true;
}
}
}
}
bool TraceSvcJrd::checkAlive(ULONG sesId)
bool TraceSvcJrd::checkAliveAndFlags(ULONG sesId, int& flags)
{
TraceManager* mgr = m_svc.getTraceManager();
ConfigStorage* storage = mgr->getStorage();
ConfigStorage* storage = TraceManager::getStorage();
bool alive = (m_chg_number == storage->getChangeNumber());
if (!alive)
@ -328,6 +315,7 @@ bool TraceSvcJrd::checkAlive(ULONG sesId)
if (readSession.ses_id == sesId)
{
alive = true;
flags = readSession.ses_flags;
break;
}
}