mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 20:43:02 +01:00
Detach idle worker attachments after 60 seconds of inactivity to free system resources and metadata locks.
Also, publish worker attachments for monitoring.
This commit is contained in:
parent
25ddf6750d
commit
889ff29299
@ -27,7 +27,6 @@
|
||||
|
||||
#include "../../common/classes/TimerImpl.h"
|
||||
#include "../../common/StatusHolder.h"
|
||||
#include "../../common/ThreadStart.h"
|
||||
#include "../../common/utils_proto.h"
|
||||
|
||||
namespace Firebird {
|
||||
@ -36,7 +35,7 @@ void TimerImpl::handler()
|
||||
{
|
||||
{
|
||||
MutexLockGuard guard(m_mutex, FB_FUNCTION);
|
||||
fb_assert(!m_inHandler);
|
||||
fb_assert(!m_handlerTid);
|
||||
|
||||
m_fireTime = 0;
|
||||
if (!m_expTime) // Timer was reset to zero or stopped, do nothing
|
||||
@ -54,7 +53,7 @@ void TimerImpl::handler()
|
||||
m_expTime = 0;
|
||||
|
||||
if (m_onTimer)
|
||||
m_inHandler = true;
|
||||
m_handlerTid = Thread::getId();
|
||||
}
|
||||
|
||||
if (!m_onTimer)
|
||||
@ -63,7 +62,7 @@ void TimerImpl::handler()
|
||||
m_onTimer(this);
|
||||
|
||||
MutexLockGuard guard(m_mutex, FB_FUNCTION);
|
||||
m_inHandler = false;
|
||||
m_handlerTid = 0;
|
||||
}
|
||||
|
||||
void TimerImpl::reset(unsigned int timeout)
|
||||
@ -108,8 +107,12 @@ void TimerImpl::stop()
|
||||
{
|
||||
MutexLockGuard guard(m_mutex, FB_FUNCTION);
|
||||
|
||||
// Allow handler() to call stop()
|
||||
if (m_handlerTid == Thread::getId())
|
||||
return;
|
||||
|
||||
// hvlad: it could be replaced by condition variable when we have good one for Windows
|
||||
while (m_inHandler)
|
||||
while (m_handlerTid)
|
||||
{
|
||||
MutexUnlockGuard unlock(m_mutex, FB_FUNCTION);
|
||||
Thread::sleep(10);
|
||||
|
@ -32,6 +32,7 @@
|
||||
|
||||
#include "../../common/classes/ImplementHelper.h"
|
||||
#include "../../common/classes/locks.h"
|
||||
#include "../../common/ThreadStart.h"
|
||||
|
||||
namespace Firebird {
|
||||
|
||||
@ -51,7 +52,7 @@ public:
|
||||
TimerImpl() :
|
||||
m_fireTime(0),
|
||||
m_expTime(0),
|
||||
m_inHandler(false)
|
||||
m_handlerTid(0)
|
||||
{ }
|
||||
|
||||
// ITimer implementation
|
||||
@ -82,9 +83,9 @@ public:
|
||||
private:
|
||||
Mutex m_mutex;
|
||||
SINT64 m_fireTime; // when ITimer will fire, could be less than m_expTime
|
||||
SINT64 m_expTime; // when actual idle timeout will expire
|
||||
SINT64 m_expTime; // when actual timeout will expire
|
||||
std::function<OnTimerFunc> m_onTimer;
|
||||
bool m_inHandler;
|
||||
ThreadId m_handlerTid; // ID of handler thread, if handler is running
|
||||
};
|
||||
|
||||
|
||||
|
@ -1036,7 +1036,7 @@ void StableAttachmentPart::manualAsyncUnlock(ULONG& flags)
|
||||
}
|
||||
}
|
||||
|
||||
void StableAttachmentPart::onIdleTimer(TimerImpl*)
|
||||
void StableAttachmentPart::doOnIdleTimer(TimerImpl*)
|
||||
{
|
||||
// Ensure attachment is still alive and still idle
|
||||
|
||||
@ -1075,8 +1075,11 @@ void Attachment::setupIdleTimer(bool clear)
|
||||
{
|
||||
if (!att_idle_timer)
|
||||
{
|
||||
att_idle_timer = FB_NEW IdleTimer(getStable());
|
||||
att_idle_timer->setOnTimer(&StableAttachmentPart::onIdleTimer);
|
||||
using IdleTimer = TimerWithRef<StableAttachmentPart>;
|
||||
|
||||
auto idleTimer = FB_NEW IdleTimer(getStable());
|
||||
idleTimer->setOnTimer(&StableAttachmentPart::onIdleTimer);
|
||||
att_idle_timer = idleTimer;
|
||||
}
|
||||
|
||||
att_idle_timer->reset(timeout);
|
||||
|
@ -374,7 +374,13 @@ public:
|
||||
return shutError;
|
||||
}
|
||||
|
||||
void onIdleTimer(Firebird::TimerImpl*);
|
||||
void onIdleTimer(Firebird::TimerImpl* timer)
|
||||
{
|
||||
doOnIdleTimer(timer);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void doOnIdleTimer(Firebird::TimerImpl* timer);
|
||||
|
||||
private:
|
||||
Attachment* att;
|
||||
@ -809,9 +815,7 @@ private:
|
||||
|
||||
unsigned int att_idle_timeout; // seconds
|
||||
unsigned int att_stmt_timeout; // milliseconds
|
||||
|
||||
typedef Firebird::TimerWithRef<StableAttachmentPart> IdleTimer;
|
||||
Firebird::RefPtr<IdleTimer> att_idle_timer;
|
||||
Firebird::RefPtr<Firebird::TimerImpl> att_idle_timer;
|
||||
|
||||
Firebird::Array<JBatch*> att_batches;
|
||||
InitialOptions att_initial_options; // Initial session options
|
||||
|
@ -45,6 +45,8 @@ using namespace Firebird;
|
||||
namespace Jrd {
|
||||
|
||||
|
||||
const unsigned WORKER_IDLE_TIMEOUT = 60; // 1 minute
|
||||
|
||||
/// class WorkerStableAttachment
|
||||
|
||||
WorkerStableAttachment::WorkerStableAttachment(FbStatusVector* status, Jrd::Attachment* attachment) :
|
||||
@ -65,6 +67,7 @@ WorkerStableAttachment::WorkerStableAttachment(FbStatusVector* status, Jrd::Atta
|
||||
PAG_header(tdbb, true);
|
||||
PAG_attachment_id(tdbb);
|
||||
TRA_init(attachment);
|
||||
Monitoring::publishAttachment(tdbb);
|
||||
|
||||
initDone();
|
||||
}
|
||||
@ -97,6 +100,11 @@ WorkerStableAttachment* WorkerStableAttachment::create(FbStatusVector* status, J
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void WorkerStableAttachment::doOnIdleTimer(Firebird::TimerImpl* timer)
|
||||
{
|
||||
WorkerAttachment::detachIdle(this);
|
||||
}
|
||||
|
||||
void WorkerStableAttachment::fini()
|
||||
{
|
||||
Attachment* attachment = NULL;
|
||||
@ -232,7 +240,19 @@ void WorkerAttachment::shutdownDbb(Database* dbb)
|
||||
|
||||
StableAttachmentPart* WorkerAttachment::getAttachment(FbStatusVector* status, Database* dbb)
|
||||
{
|
||||
//?? Database::Checkout cout(dbb);
|
||||
// There should be no locked attachment.
|
||||
#ifdef _DEBUG
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
if (tdbb)
|
||||
{
|
||||
Attachment* att = tdbb->getAttachment();
|
||||
if (att)
|
||||
{
|
||||
const StableAttachmentPart::Sync* sync = att->getStable()->getSync();
|
||||
fb_assert(!sync || !sync->locked());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
Arg::Gds(isc_shutdown).copyTo(status);
|
||||
|
||||
@ -245,7 +265,6 @@ StableAttachmentPart* WorkerAttachment::getAttachment(FbStatusVector* status, Da
|
||||
if (m_shutdown)
|
||||
return NULL;
|
||||
|
||||
|
||||
FB_SIZE_T maxWorkers = Config::getMaxParallelWorkers();
|
||||
if (maxWorkers <= 0)
|
||||
maxWorkers = MAX_ULONG;
|
||||
@ -298,7 +317,10 @@ StableAttachmentPart* WorkerAttachment::getAttachment(FbStatusVector* status, Da
|
||||
fb_assert(!att || (att->att_flags & ATT_worker));
|
||||
|
||||
if (att)
|
||||
{
|
||||
att->att_use_count++;
|
||||
att->setupIdleTimer(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (att)
|
||||
@ -319,10 +341,12 @@ void WorkerAttachment::releaseAttachment(FbStatusVector* status, StableAttachmen
|
||||
return;
|
||||
|
||||
att->att_use_count--;
|
||||
att->setupIdleTimer(false);
|
||||
|
||||
item = getByName(att->att_database->dbb_filename);
|
||||
}
|
||||
|
||||
bool detach = (m_shutdown || (item == NULL));
|
||||
const bool detach = (m_shutdown || (item == NULL));
|
||||
bool tryClear = false;
|
||||
|
||||
if (item)
|
||||
@ -372,6 +396,36 @@ void WorkerAttachment::clear(bool checkRefs)
|
||||
}
|
||||
}
|
||||
|
||||
bool WorkerAttachment::detachIdle(StableAttachmentPart* sAtt)
|
||||
{
|
||||
WorkerAttachment* item = NULL;
|
||||
{ // scope
|
||||
AttSyncLockGuard attGuard(sAtt->getSync(), FB_FUNCTION);
|
||||
|
||||
Attachment* att = sAtt->getHandle();
|
||||
if (!att || att->att_use_count > 0)
|
||||
return false;
|
||||
|
||||
item = getByName(att->att_database->dbb_filename);
|
||||
}
|
||||
|
||||
if (item)
|
||||
{
|
||||
MutexLockGuard guard(item->m_mutex, FB_FUNCTION);
|
||||
|
||||
FB_SIZE_T pos;
|
||||
if (item->m_idleAtts.find(sAtt, pos))
|
||||
item->m_idleAtts.remove(pos);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
FbLocalStatus status;
|
||||
doDetach(&status, sAtt);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
StableAttachmentPart* WorkerAttachment::doAttach(FbStatusVector* status, Database* dbb)
|
||||
{
|
||||
StableAttachmentPart* sAtt = NULL;
|
||||
@ -396,7 +450,10 @@ StableAttachmentPart* WorkerAttachment::doAttach(FbStatusVector* status, Databas
|
||||
}
|
||||
|
||||
if (sAtt)
|
||||
{
|
||||
sAtt->addRef(); // !!
|
||||
sAtt->getHandle()->setIdleTimeout(WORKER_IDLE_TIMEOUT);
|
||||
}
|
||||
|
||||
return sAtt;
|
||||
}
|
||||
@ -415,7 +472,6 @@ void WorkerAttachment::doDetach(FbStatusVector* status, StableAttachmentPart* sA
|
||||
{
|
||||
JAttachment* jAtt = sAtt->getInterface();
|
||||
jAtt->detach(status);
|
||||
jAtt->release();
|
||||
}
|
||||
sAtt->release(); // !!
|
||||
}
|
||||
|
@ -50,6 +50,9 @@ public:
|
||||
|
||||
void fini();
|
||||
|
||||
protected:
|
||||
virtual void doOnIdleTimer(Firebird::TimerImpl* timer);
|
||||
|
||||
private:
|
||||
explicit WorkerStableAttachment(FbStatusVector* status, Jrd::Attachment* att);
|
||||
virtual ~WorkerStableAttachment();
|
||||
@ -80,6 +83,8 @@ public:
|
||||
static Jrd::StableAttachmentPart* getAttachment(FbStatusVector* status, Jrd::Database* dbb);
|
||||
static void releaseAttachment(FbStatusVector* status, Jrd::StableAttachmentPart* sAtt);
|
||||
|
||||
static bool detachIdle(Jrd::StableAttachmentPart* sAtt);
|
||||
|
||||
static void incUserAtts(const Firebird::PathName& dbname);
|
||||
static void decUserAtts(const Firebird::PathName& dbname);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user