From 22107f0ba32aaa306ec6d23aaca6f74ec244a2c0 Mon Sep 17 00:00:00 2001 From: hvlad Date: Wed, 11 Feb 2009 15:24:12 +0000 Subject: [PATCH] Suspend trace session when log is full despite of log reader [in]activity. --- src/jrd/trace/TraceLog.cpp | 31 +++++++++--------- src/jrd/trace/TraceLog.h | 40 ++++++++++------------- src/jrd/trace/TraceObjects.cpp | 60 +++++++++++++++++++++++++++++++++- src/jrd/trace/TraceService.cpp | 52 ++++++++++++----------------- 4 files changed, 111 insertions(+), 72 deletions(-) diff --git a/src/jrd/trace/TraceLog.cpp b/src/jrd/trace/TraceLog.cpp index 92bee07c62..73b967e2eb 100644 --- a/src/jrd/trace/TraceLog.cpp +++ b/src/jrd/trace/TraceLog.cpp @@ -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)); diff --git a/src/jrd/trace/TraceLog.h b/src/jrd/trace/TraceLog.h index 1b218c166e..ca686c8423 100644 --- a/src/jrd/trace/TraceLog.h +++ b/src/jrd/trace/TraceLog.h @@ -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; + }; }; diff --git a/src/jrd/trace/TraceObjects.cpp b/src/jrd/trace/TraceObjects.cpp index 3c3210afed..6074812526 100644 --- a/src/jrd/trace/TraceObjects.cpp +++ b/src/jrd/trace/TraceObjects.cpp @@ -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; } diff --git a/src/jrd/trace/TraceService.cpp b/src/jrd/trace/TraceService.cpp index c0cc4fd406..187c26b440 100644 --- a/src/jrd/trace/TraceService.cpp +++ b/src/jrd/trace/TraceService.cpp @@ -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 log(FB_NEW(pool) TraceLogImpl(pool, session.ses_logfile, true)); + AutoPtr 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; } }