mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 00:03: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/classes/TimerImpl.h"
|
||||||
#include "../../common/StatusHolder.h"
|
#include "../../common/StatusHolder.h"
|
||||||
#include "../../common/ThreadStart.h"
|
|
||||||
#include "../../common/utils_proto.h"
|
#include "../../common/utils_proto.h"
|
||||||
|
|
||||||
namespace Firebird {
|
namespace Firebird {
|
||||||
@ -36,7 +35,7 @@ void TimerImpl::handler()
|
|||||||
{
|
{
|
||||||
{
|
{
|
||||||
MutexLockGuard guard(m_mutex, FB_FUNCTION);
|
MutexLockGuard guard(m_mutex, FB_FUNCTION);
|
||||||
fb_assert(!m_inHandler);
|
fb_assert(!m_handlerTid);
|
||||||
|
|
||||||
m_fireTime = 0;
|
m_fireTime = 0;
|
||||||
if (!m_expTime) // Timer was reset to zero or stopped, do nothing
|
if (!m_expTime) // Timer was reset to zero or stopped, do nothing
|
||||||
@ -54,7 +53,7 @@ void TimerImpl::handler()
|
|||||||
m_expTime = 0;
|
m_expTime = 0;
|
||||||
|
|
||||||
if (m_onTimer)
|
if (m_onTimer)
|
||||||
m_inHandler = true;
|
m_handlerTid = Thread::getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_onTimer)
|
if (!m_onTimer)
|
||||||
@ -63,7 +62,7 @@ void TimerImpl::handler()
|
|||||||
m_onTimer(this);
|
m_onTimer(this);
|
||||||
|
|
||||||
MutexLockGuard guard(m_mutex, FB_FUNCTION);
|
MutexLockGuard guard(m_mutex, FB_FUNCTION);
|
||||||
m_inHandler = false;
|
m_handlerTid = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimerImpl::reset(unsigned int timeout)
|
void TimerImpl::reset(unsigned int timeout)
|
||||||
@ -108,8 +107,12 @@ void TimerImpl::stop()
|
|||||||
{
|
{
|
||||||
MutexLockGuard guard(m_mutex, FB_FUNCTION);
|
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
|
// 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);
|
MutexUnlockGuard unlock(m_mutex, FB_FUNCTION);
|
||||||
Thread::sleep(10);
|
Thread::sleep(10);
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
|
|
||||||
#include "../../common/classes/ImplementHelper.h"
|
#include "../../common/classes/ImplementHelper.h"
|
||||||
#include "../../common/classes/locks.h"
|
#include "../../common/classes/locks.h"
|
||||||
|
#include "../../common/ThreadStart.h"
|
||||||
|
|
||||||
namespace Firebird {
|
namespace Firebird {
|
||||||
|
|
||||||
@ -51,7 +52,7 @@ public:
|
|||||||
TimerImpl() :
|
TimerImpl() :
|
||||||
m_fireTime(0),
|
m_fireTime(0),
|
||||||
m_expTime(0),
|
m_expTime(0),
|
||||||
m_inHandler(false)
|
m_handlerTid(0)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
// ITimer implementation
|
// ITimer implementation
|
||||||
@ -82,9 +83,9 @@ public:
|
|||||||
private:
|
private:
|
||||||
Mutex m_mutex;
|
Mutex m_mutex;
|
||||||
SINT64 m_fireTime; // when ITimer will fire, could be less than m_expTime
|
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;
|
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
|
// Ensure attachment is still alive and still idle
|
||||||
|
|
||||||
@ -1075,8 +1075,11 @@ void Attachment::setupIdleTimer(bool clear)
|
|||||||
{
|
{
|
||||||
if (!att_idle_timer)
|
if (!att_idle_timer)
|
||||||
{
|
{
|
||||||
att_idle_timer = FB_NEW IdleTimer(getStable());
|
using IdleTimer = TimerWithRef<StableAttachmentPart>;
|
||||||
att_idle_timer->setOnTimer(&StableAttachmentPart::onIdleTimer);
|
|
||||||
|
auto idleTimer = FB_NEW IdleTimer(getStable());
|
||||||
|
idleTimer->setOnTimer(&StableAttachmentPart::onIdleTimer);
|
||||||
|
att_idle_timer = idleTimer;
|
||||||
}
|
}
|
||||||
|
|
||||||
att_idle_timer->reset(timeout);
|
att_idle_timer->reset(timeout);
|
||||||
|
@ -374,7 +374,13 @@ public:
|
|||||||
return shutError;
|
return shutError;
|
||||||
}
|
}
|
||||||
|
|
||||||
void onIdleTimer(Firebird::TimerImpl*);
|
void onIdleTimer(Firebird::TimerImpl* timer)
|
||||||
|
{
|
||||||
|
doOnIdleTimer(timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void doOnIdleTimer(Firebird::TimerImpl* timer);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Attachment* att;
|
Attachment* att;
|
||||||
@ -809,9 +815,7 @@ private:
|
|||||||
|
|
||||||
unsigned int att_idle_timeout; // seconds
|
unsigned int att_idle_timeout; // seconds
|
||||||
unsigned int att_stmt_timeout; // milliseconds
|
unsigned int att_stmt_timeout; // milliseconds
|
||||||
|
Firebird::RefPtr<Firebird::TimerImpl> att_idle_timer;
|
||||||
typedef Firebird::TimerWithRef<StableAttachmentPart> IdleTimer;
|
|
||||||
Firebird::RefPtr<IdleTimer> att_idle_timer;
|
|
||||||
|
|
||||||
Firebird::Array<JBatch*> att_batches;
|
Firebird::Array<JBatch*> att_batches;
|
||||||
InitialOptions att_initial_options; // Initial session options
|
InitialOptions att_initial_options; // Initial session options
|
||||||
|
@ -45,6 +45,8 @@ using namespace Firebird;
|
|||||||
namespace Jrd {
|
namespace Jrd {
|
||||||
|
|
||||||
|
|
||||||
|
const unsigned WORKER_IDLE_TIMEOUT = 60; // 1 minute
|
||||||
|
|
||||||
/// class WorkerStableAttachment
|
/// class WorkerStableAttachment
|
||||||
|
|
||||||
WorkerStableAttachment::WorkerStableAttachment(FbStatusVector* status, Jrd::Attachment* attachment) :
|
WorkerStableAttachment::WorkerStableAttachment(FbStatusVector* status, Jrd::Attachment* attachment) :
|
||||||
@ -65,6 +67,7 @@ WorkerStableAttachment::WorkerStableAttachment(FbStatusVector* status, Jrd::Atta
|
|||||||
PAG_header(tdbb, true);
|
PAG_header(tdbb, true);
|
||||||
PAG_attachment_id(tdbb);
|
PAG_attachment_id(tdbb);
|
||||||
TRA_init(attachment);
|
TRA_init(attachment);
|
||||||
|
Monitoring::publishAttachment(tdbb);
|
||||||
|
|
||||||
initDone();
|
initDone();
|
||||||
}
|
}
|
||||||
@ -97,6 +100,11 @@ WorkerStableAttachment* WorkerStableAttachment::create(FbStatusVector* status, J
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WorkerStableAttachment::doOnIdleTimer(Firebird::TimerImpl* timer)
|
||||||
|
{
|
||||||
|
WorkerAttachment::detachIdle(this);
|
||||||
|
}
|
||||||
|
|
||||||
void WorkerStableAttachment::fini()
|
void WorkerStableAttachment::fini()
|
||||||
{
|
{
|
||||||
Attachment* attachment = NULL;
|
Attachment* attachment = NULL;
|
||||||
@ -232,7 +240,19 @@ void WorkerAttachment::shutdownDbb(Database* dbb)
|
|||||||
|
|
||||||
StableAttachmentPart* WorkerAttachment::getAttachment(FbStatusVector* status, 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);
|
Arg::Gds(isc_shutdown).copyTo(status);
|
||||||
|
|
||||||
@ -245,7 +265,6 @@ StableAttachmentPart* WorkerAttachment::getAttachment(FbStatusVector* status, Da
|
|||||||
if (m_shutdown)
|
if (m_shutdown)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
|
||||||
FB_SIZE_T maxWorkers = Config::getMaxParallelWorkers();
|
FB_SIZE_T maxWorkers = Config::getMaxParallelWorkers();
|
||||||
if (maxWorkers <= 0)
|
if (maxWorkers <= 0)
|
||||||
maxWorkers = MAX_ULONG;
|
maxWorkers = MAX_ULONG;
|
||||||
@ -298,7 +317,10 @@ StableAttachmentPart* WorkerAttachment::getAttachment(FbStatusVector* status, Da
|
|||||||
fb_assert(!att || (att->att_flags & ATT_worker));
|
fb_assert(!att || (att->att_flags & ATT_worker));
|
||||||
|
|
||||||
if (att)
|
if (att)
|
||||||
|
{
|
||||||
att->att_use_count++;
|
att->att_use_count++;
|
||||||
|
att->setupIdleTimer(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (att)
|
if (att)
|
||||||
@ -319,10 +341,12 @@ void WorkerAttachment::releaseAttachment(FbStatusVector* status, StableAttachmen
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
att->att_use_count--;
|
att->att_use_count--;
|
||||||
|
att->setupIdleTimer(false);
|
||||||
|
|
||||||
item = getByName(att->att_database->dbb_filename);
|
item = getByName(att->att_database->dbb_filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool detach = (m_shutdown || (item == NULL));
|
const bool detach = (m_shutdown || (item == NULL));
|
||||||
bool tryClear = false;
|
bool tryClear = false;
|
||||||
|
|
||||||
if (item)
|
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* WorkerAttachment::doAttach(FbStatusVector* status, Database* dbb)
|
||||||
{
|
{
|
||||||
StableAttachmentPart* sAtt = NULL;
|
StableAttachmentPart* sAtt = NULL;
|
||||||
@ -396,7 +450,10 @@ StableAttachmentPart* WorkerAttachment::doAttach(FbStatusVector* status, Databas
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sAtt)
|
if (sAtt)
|
||||||
|
{
|
||||||
sAtt->addRef(); // !!
|
sAtt->addRef(); // !!
|
||||||
|
sAtt->getHandle()->setIdleTimeout(WORKER_IDLE_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
return sAtt;
|
return sAtt;
|
||||||
}
|
}
|
||||||
@ -415,7 +472,6 @@ void WorkerAttachment::doDetach(FbStatusVector* status, StableAttachmentPart* sA
|
|||||||
{
|
{
|
||||||
JAttachment* jAtt = sAtt->getInterface();
|
JAttachment* jAtt = sAtt->getInterface();
|
||||||
jAtt->detach(status);
|
jAtt->detach(status);
|
||||||
jAtt->release();
|
|
||||||
}
|
}
|
||||||
sAtt->release(); // !!
|
sAtt->release(); // !!
|
||||||
}
|
}
|
||||||
|
@ -50,6 +50,9 @@ public:
|
|||||||
|
|
||||||
void fini();
|
void fini();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void doOnIdleTimer(Firebird::TimerImpl* timer);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit WorkerStableAttachment(FbStatusVector* status, Jrd::Attachment* att);
|
explicit WorkerStableAttachment(FbStatusVector* status, Jrd::Attachment* att);
|
||||||
virtual ~WorkerStableAttachment();
|
virtual ~WorkerStableAttachment();
|
||||||
@ -80,6 +83,8 @@ public:
|
|||||||
static Jrd::StableAttachmentPart* getAttachment(FbStatusVector* status, Jrd::Database* dbb);
|
static Jrd::StableAttachmentPart* getAttachment(FbStatusVector* status, Jrd::Database* dbb);
|
||||||
static void releaseAttachment(FbStatusVector* status, Jrd::StableAttachmentPart* sAtt);
|
static void releaseAttachment(FbStatusVector* status, Jrd::StableAttachmentPart* sAtt);
|
||||||
|
|
||||||
|
static bool detachIdle(Jrd::StableAttachmentPart* sAtt);
|
||||||
|
|
||||||
static void incUserAtts(const Firebird::PathName& dbname);
|
static void incUserAtts(const Firebird::PathName& dbname);
|
||||||
static void decUserAtts(const Firebird::PathName& dbname);
|
static void decUserAtts(const Firebird::PathName& dbname);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user