|
From: <hv...@us...> - 2011-05-27 07:57:25
|
Revision: 53021
http://firebird.svn.sourceforge.net/firebird/?rev=53021&view=rev
Author: hvlad
Date: 2011-05-27 07:57:16 +0000 (Fri, 27 May 2011)
Log Message:
-----------
Enabled background threads (garbage collector and cache writer).
Introduced special kind of system attachments used in this threads and show its activity in monitoring.
Modified Paths:
--------------
firebird/trunk/builds/win32/msvc10/engine.vcxproj
firebird/trunk/builds/win32/msvc10/engine.vcxproj.filters
firebird/trunk/builds/win32/msvc8/engine.vcproj
firebird/trunk/builds/win32/msvc9/engine.vcproj
firebird/trunk/src/common/common.h
firebird/trunk/src/jrd/Attachment.h
firebird/trunk/src/jrd/Database.h
firebird/trunk/src/jrd/DatabaseSnapshot.cpp
firebird/trunk/src/jrd/DatabaseSnapshot.h
firebird/trunk/src/jrd/EngineInterface.h
firebird/trunk/src/jrd/Relation.cpp
firebird/trunk/src/jrd/Relation.h
firebird/trunk/src/jrd/cch.cpp
firebird/trunk/src/jrd/cch.h
firebird/trunk/src/jrd/cch_proto.h
firebird/trunk/src/jrd/dfw.epp
firebird/trunk/src/jrd/dpm.epp
firebird/trunk/src/jrd/jrd.cpp
firebird/trunk/src/jrd/req.h
firebird/trunk/src/jrd/tra.cpp
firebird/trunk/src/jrd/vio.cpp
firebird/trunk/src/jrd/vio_proto.h
Added Paths:
-----------
firebird/trunk/src/jrd/GarbageCollector.cpp
firebird/trunk/src/jrd/GarbageCollector.h
Modified: firebird/trunk/builds/win32/msvc10/engine.vcxproj
===================================================================
--- firebird/trunk/builds/win32/msvc10/engine.vcxproj 2011-05-27 03:27:46 UTC (rev 53020)
+++ firebird/trunk/builds/win32/msvc10/engine.vcxproj 2011-05-27 07:57:16 UTC (rev 53021)
@@ -82,6 +82,7 @@
<ClCompile Include="..\..\..\src\jrd\ExtEngineManager.cpp" />
<ClCompile Include="..\..\..\src\jrd\filters.cpp" />
<ClCompile Include="..\..\..\src\jrd\flu.cpp" />
+ <ClCompile Include="..\..\..\src\jrd\GarbageCollector.cpp" />
<ClCompile Include="..\..\..\src\jrd\GlobalRWLock.cpp" />
<ClCompile Include="..\..\..\src\jrd\idx.cpp" />
<ClCompile Include="..\..\..\src\jrd\inf.cpp" />
@@ -247,6 +248,7 @@
<ClInclude Include="..\..\..\src\jrd\flu_proto.h" />
<ClInclude Include="..\..\..\src\jrd\Function.h" />
<ClInclude Include="..\..\..\src\jrd\fun_proto.h" />
+ <ClInclude Include="..\..\..\src\jrd\GarbageCollector.h" />
<ClInclude Include="..\..\..\src\jrd\GlobalRWLock.h" />
<ClInclude Include="..\..\..\src\jrd\grant_proto.h" />
<ClInclude Include="..\..\..\src\jrd\ibase.h" />
Modified: firebird/trunk/builds/win32/msvc10/engine.vcxproj.filters
===================================================================
--- firebird/trunk/builds/win32/msvc10/engine.vcxproj.filters 2011-05-27 03:27:46 UTC (rev 53020)
+++ firebird/trunk/builds/win32/msvc10/engine.vcxproj.filters 2011-05-27 07:57:16 UTC (rev 53021)
@@ -465,6 +465,9 @@
<ClCompile Include="..\..\..\src\jrd\recsrc\ConditionalStream.cpp">
<Filter>JRD files\Data Access</Filter>
</ClCompile>
+ <ClCompile Include="..\..\..\src\jrd\GarbageCollector.cpp">
+ <Filter>JRD files</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\src\jrd\recsrc\RecordSource.h">
@@ -1010,6 +1013,9 @@
<ClInclude Include="..\..\..\src\jrd\vio_proto.h">
<Filter>Header files</Filter>
</ClInclude>
+ <ClInclude Include="..\..\..\src\jrd\GarbageCollector.h">
+ <Filter>Header files</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\..\..\src\dsql\DdlNodes.epp">
Modified: firebird/trunk/builds/win32/msvc8/engine.vcproj
===================================================================
--- firebird/trunk/builds/win32/msvc8/engine.vcproj 2011-05-27 03:27:46 UTC (rev 53020)
+++ firebird/trunk/builds/win32/msvc8/engine.vcproj 2011-05-27 07:57:16 UTC (rev 53021)
@@ -420,6 +420,10 @@
>
</File>
<File
+ RelativePath="..\..\..\src\jrd\GarbageCollector.cpp"
+ >
+ </File>
+ <File
RelativePath="..\..\..\src\jrd\GlobalRWLock.cpp"
>
</File>
@@ -1168,6 +1172,10 @@
>
</File>
<File
+ RelativePath="..\..\..\src\jrd\GarbageCollector.h"
+ >
+ </File>
+ <File
RelativePath="..\..\..\src\jrd\GlobalRWLock.h"
>
</File>
Modified: firebird/trunk/builds/win32/msvc9/engine.vcproj
===================================================================
--- firebird/trunk/builds/win32/msvc9/engine.vcproj 2011-05-27 03:27:46 UTC (rev 53020)
+++ firebird/trunk/builds/win32/msvc9/engine.vcproj 2011-05-27 07:57:16 UTC (rev 53021)
@@ -420,6 +420,10 @@
>
</File>
<File
+ RelativePath="..\..\..\src\jrd\GarbageCollector.cpp"
+ >
+ </File>
+ <File
RelativePath="..\..\..\src\jrd\GlobalRWLock.cpp"
>
</File>
@@ -1168,6 +1172,10 @@
>
</File>
<File
+ RelativePath="..\..\..\src\jrd\GarbageCollector.h"
+ >
+ </File>
+ <File
RelativePath="..\..\..\src\jrd\GlobalRWLock.h"
>
</File>
Modified: firebird/trunk/src/common/common.h
===================================================================
--- firebird/trunk/src/common/common.h 2011-05-27 03:27:46 UTC (rev 53020)
+++ firebird/trunk/src/common/common.h 2011-05-27 07:57:16 UTC (rev 53021)
@@ -78,11 +78,7 @@
do not use links in source code to maintain platform neutrality
*/
-#ifdef SUPERSERVER
-#define GARBAGE_THREAD
-#endif
-
/*****************************************************
* Linux platforms
*****************************************************/
Modified: firebird/trunk/src/jrd/Attachment.h
===================================================================
--- firebird/trunk/src/jrd/Attachment.h 2011-05-27 03:27:46 UTC (rev 53020)
+++ firebird/trunk/src/jrd/Attachment.h 2011-05-27 07:57:16 UTC (rev 53021)
@@ -351,33 +351,27 @@
// Attachment flags
-const ULONG ATT_no_cleanup = 1; // Don't expunge, purge, or garbage collect
-const ULONG ATT_shutdown = 2; // attachment has been shutdown
-const ULONG ATT_purge_error = 4; // trouble happened in purge attachment, att_mutex remains locked
-const ULONG ATT_shutdown_manager = 8; // attachment requesting shutdown
-const ULONG ATT_lck_init_done = 16; // LCK_init() called for the attachment
-const ULONG ATT_exclusive = 32; // attachment wants exclusive database access
-const ULONG ATT_attach_pending = 64; // Indicate attachment is only pending
-const ULONG ATT_exclusive_pending = 128; // Indicate exclusive attachment pending
-const ULONG ATT_gbak_attachment = 256; // Indicate GBAK attachment
+const ULONG ATT_no_cleanup = 0x0001L; // Don't expunge, purge, or garbage collect
+const ULONG ATT_shutdown = 0x0002L; // attachment has been shutdown
+const ULONG ATT_purge_error = 0x0004L; // trouble happened in purge attachment, att_mutex remains locked
+const ULONG ATT_shutdown_manager = 0x0008L; // attachment requesting shutdown
+const ULONG ATT_lck_init_done = 0x0010L; // LCK_init() called for the attachment
+const ULONG ATT_exclusive = 0x0020L; // attachment wants exclusive database access
+const ULONG ATT_attach_pending = 0x0040L; // Indicate attachment is only pending
+const ULONG ATT_exclusive_pending = 0x0080L; // Indicate exclusive attachment pending
+const ULONG ATT_gbak_attachment = 0x0100L; // Indicate GBAK attachment
+const ULONG ATT_notify_gc = 0x0200L; // Notify garbage collector to expunge, purge ..
+const ULONG ATT_disable_notify_gc = 0x0400L; // Temporarily perform own garbage collection
+const ULONG ATT_garbage_collector = 0x0800L; // I'm a garbage collector
+const ULONG ATT_cancel_raise = 0x1000L; // Cancel currently running operation
+const ULONG ATT_cancel_disable = 0x2000L; // Disable cancel operations
+const ULONG ATT_gfix_attachment = 0x4000L; // Indicate a GFIX attachment
+const ULONG ATT_gstat_attachment = 0x8000L; // Indicate a GSTAT attachment
+const ULONG ATT_no_db_triggers = 0x10000L; // Don't execute database triggers
-#ifdef GARBAGE_THREAD
-const ULONG ATT_notify_gc = 1024; // Notify garbage collector to expunge, purge ..
-const ULONG ATT_disable_notify_gc = 2048; // Temporarily perform own garbage collection
-const ULONG ATT_garbage_collector = 4096; // I'm a garbage collector
-
const ULONG ATT_NO_CLEANUP = (ATT_no_cleanup | ATT_notify_gc);
-#else
-const ULONG ATT_NO_CLEANUP = ATT_no_cleanup;
-#endif
-const ULONG ATT_cancel_raise = 8192; // Cancel currently running operation
-const ULONG ATT_cancel_disable = 16384; // Disable cancel operations
-const ULONG ATT_gfix_attachment = 32768; // Indicate a GFIX attachment
-const ULONG ATT_gstat_attachment = 65536; // Indicate a GSTAT attachment
-const ULONG ATT_no_db_triggers = 131072; // Don't execute database triggers
-
inline bool Attachment::locksmith() const
{
return att_user && att_user->locksmith();
Modified: firebird/trunk/src/jrd/Database.h
===================================================================
--- firebird/trunk/src/jrd/Database.h 2011-05-27 03:27:46 UTC (rev 53020)
+++ firebird/trunk/src/jrd/Database.h 2011-05-27 07:57:16 UTC (rev 53021)
@@ -75,6 +75,7 @@
class BackupManager;
class ExternalFileDirectoryList;
class MonitoringData;
+class GarbageCollector;
// general purpose vector
@@ -196,11 +197,9 @@
const ULONG DBB_damaged = 0x1L;
const ULONG DBB_exclusive = 0x2L; // Database is accessed in exclusive mode
const ULONG DBB_bugcheck = 0x4L; // Bugcheck has occurred
-#ifdef GARBAGE_THREAD
const ULONG DBB_garbage_collector = 0x8L; // garbage collector thread exists
const ULONG DBB_gc_active = 0x10L; // ... and is actively working.
const ULONG DBB_gc_pending = 0x20L; // garbage collection requested
-#endif
const ULONG DBB_force_write = 0x40L; // Database is forced write
const ULONG DBB_no_reserve = 0x80L; // No reserve space for versions
const ULONG DBB_DB_SQL_dialect_3 = 0x100L; // database SQL dialect 3
@@ -314,6 +313,7 @@
Database* dbb_next; // Next database block in system
Attachment* dbb_attachments; // Active attachments
+ Attachment* dbb_sys_attachments; // System attachments
BufferControl* dbb_bcb; // Buffer control block
int dbb_monitoring_id; // dbb monitoring identifier
Lock* dbb_lock; // granddaddy lock
@@ -370,12 +370,10 @@
SLONG dbb_attachment_id; // Next attachment id for ReadOnly DB's
ULONG dbb_page_buffers; // Page buffers from header page
-
-#ifdef GARBAGE_THREAD
+ GarbageCollector* dbb_garbage_collector; // GarbageCollector class
Firebird::Semaphore dbb_gc_sem; // Event to wake up garbage collector
Firebird::Semaphore dbb_gc_init; // Event for initialization garbage collector
Firebird::Semaphore dbb_gc_fini; // Event for finalization garbage collector
-#endif
Firebird::MemoryStats dbb_memory_stats;
Modified: firebird/trunk/src/jrd/DatabaseSnapshot.cpp
===================================================================
--- firebird/trunk/src/jrd/DatabaseSnapshot.cpp 2011-05-27 03:27:46 UTC (rev 53020)
+++ firebird/trunk/src/jrd/DatabaseSnapshot.cpp 2011-05-27 07:57:16 UTC (rev 53021)
@@ -784,59 +784,70 @@
{
Attachment::SyncGuard attGuard(attachment);
tdbb->setAttachment(attachment);
+ dumpAttachment(tdbb, attachment, writer);
+ }
- if (!putAttachment(tdbb, attachment, writer, fb_utils::genUniqueId()))
- continue;
+ for (Attachment* attachment = dbb->dbb_sys_attachments; attachment; attachment = attachment->att_next)
+ {
+ Attachment::SyncGuard attGuard(attachment);
+ tdbb->setAttachment(attachment);
+ dumpAttachment(tdbb, attachment, writer);
+ }
- putContextVars(attachment->att_context_vars, writer, attachment->att_attachment_id, true);
+ tdbb->setAttachment(old_attachment);
+}
- jrd_tra* transaction = NULL;
- jrd_req* request = NULL;
+void DatabaseSnapshot::dumpAttachment(thread_db* tdbb, const Attachment* attachment, Writer& writer)
+{
+ if (!putAttachment(tdbb, attachment, writer, fb_utils::genUniqueId()))
+ return;
- // Transaction information
+ putContextVars(attachment->att_context_vars, writer, attachment->att_attachment_id, true);
- for (transaction = attachment->att_transactions;
- transaction; transaction = transaction->tra_next)
- {
- putTransaction(transaction, writer, fb_utils::genUniqueId());
- putContextVars(transaction->tra_context_vars, writer, transaction->tra_number, false);
- }
+ jrd_tra* transaction = NULL;
+ jrd_req* request = NULL;
- // Call stack information
+ // Transaction information
- for (transaction = attachment->att_transactions;
- transaction; transaction = transaction->tra_next)
- {
- for (request = transaction->tra_requests; request; request = request->req_caller)
- {
- request->adjustCallerStats();
+ for (transaction = attachment->att_transactions;
+ transaction; transaction = transaction->tra_next)
+ {
+ putTransaction(transaction, writer, fb_utils::genUniqueId());
+ putContextVars(transaction->tra_context_vars, writer, transaction->tra_number, false);
+ }
- if (!(request->getStatement()->flags &
- (JrdStatement::FLAG_INTERNAL | JrdStatement::FLAG_SYS_TRIGGER)) &&
- request->req_caller)
- {
- putCall(request, writer, fb_utils::genUniqueId());
- }
- }
- }
+ // Call stack information
- // Request information
-
- for (const jrd_req* const* i = attachment->att_requests.begin();
- i != attachment->att_requests.end();
- ++i)
+ for (transaction = attachment->att_transactions;
+ transaction; transaction = transaction->tra_next)
+ {
+ for (request = transaction->tra_requests; request; request = request->req_caller)
{
- const jrd_req* request = *i;
+ request->adjustCallerStats();
if (!(request->getStatement()->flags &
- (JrdStatement::FLAG_INTERNAL | JrdStatement::FLAG_SYS_TRIGGER)))
+ (JrdStatement::FLAG_INTERNAL | JrdStatement::FLAG_SYS_TRIGGER)) &&
+ request->req_caller)
{
- putRequest(request, writer, fb_utils::genUniqueId());
+ putCall(request, writer, fb_utils::genUniqueId());
}
}
}
- tdbb->setAttachment(old_attachment);
+ // Request information
+
+ for (const jrd_req* const* i = attachment->att_requests.begin();
+ i != attachment->att_requests.end();
+ ++i)
+ {
+ const jrd_req* request = *i;
+
+ if (!(request->getStatement()->flags &
+ (JrdStatement::FLAG_INTERNAL | JrdStatement::FLAG_SYS_TRIGGER)))
+ {
+ putRequest(request, writer, fb_utils::genUniqueId());
+ }
+ }
}
Modified: firebird/trunk/src/jrd/DatabaseSnapshot.h
===================================================================
--- firebird/trunk/src/jrd/DatabaseSnapshot.h 2011-05-27 03:27:46 UTC (rev 53020)
+++ firebird/trunk/src/jrd/DatabaseSnapshot.h 2011-05-27 07:57:16 UTC (rev 53021)
@@ -360,6 +360,7 @@
RecordBuffer* allocBuffer(thread_db*, MemoryPool&, int);
static void dumpData(thread_db*);
+ static void dumpAttachment(thread_db*, const Attachment*, Writer&);
static SINT64 getGlobalId(int);
Modified: firebird/trunk/src/jrd/EngineInterface.h
===================================================================
--- firebird/trunk/src/jrd/EngineInterface.h 2011-05-27 03:27:46 UTC (rev 53020)
+++ firebird/trunk/src/jrd/EngineInterface.h 2011-05-27 07:57:16 UTC (rev 53021)
@@ -334,6 +334,36 @@
void freeEngineData(Firebird::IStatus* status);
};
+// internal class used in system background threads
+class SysAttachment : public JAttachment
+{
+public:
+ SysAttachment(Attachment* handle) :
+ JAttachment(handle)
+ {
+ }
+
+ virtual int FB_CARG release()
+ {
+ if (--refCounter != 0)
+ return 1;
+
+ Attachment* attachment = getHandle();
+ if (attachment)
+ {
+ destroy(attachment);
+ }
+ if (!attachment)
+ {
+ delete this;
+ }
+ return 0;
+ }
+
+private:
+ void destroy(Attachment* attachment);
+};
+
class JService : public Firebird::RefCntIface<Firebird::IService, FB_SERVICE_VERSION>
{
public:
Added: firebird/trunk/src/jrd/GarbageCollector.cpp
===================================================================
--- firebird/trunk/src/jrd/GarbageCollector.cpp (rev 0)
+++ firebird/trunk/src/jrd/GarbageCollector.cpp 2011-05-27 07:57:16 UTC (rev 53021)
@@ -0,0 +1,275 @@
+/*
+ * The contents of this file are subject to the Initial
+ * Developer's Public License Version 1.0 (the "License");
+ * you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
+ *
+ * Software distributed under the License is distributed AS IS,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied.
+ * See the License for the specific language governing rights
+ * and limitations under the License.
+ *
+ * The Original Code was created by Vlad Khorsun
+ * for the Firebird Open Source RDBMS project.
+ *
+ * Copyright (c) 2011 Vlad Khorsun <hv...@us...>
+ * and all contributors signed below.
+ *
+ * All Rights Reserved.
+ * Contributor(s): ______________________________________.
+ */
+
+#include "../common/classes/alloc.h"
+#include "../jrd/GarbageCollector.h"
+#include "../jrd/tra.h"
+
+using namespace Jrd;
+using namespace Firebird;
+
+
+namespace Jrd {
+
+void GarbageCollector::RelationData::clear()
+{
+ TranData::ConstAccessor accessor(&m_tranData);
+ if (accessor.getFirst())
+ do
+ {
+ delete accessor.current()->second;
+ } while(accessor.getNext());
+
+ m_tranData.clear();
+}
+
+
+void GarbageCollector::RelationData::addPage(const ULONG pageno, const SLONG tranid)
+{
+ // look if given page number is already set at given tx bitmap
+ PageBitmap** bmPtr = m_tranData.get(tranid);
+ PageBitmap* bm = bmPtr ? *bmPtr : NULL;
+ if (bm && bm->test(pageno))
+ return;
+
+ // search for given page at other transactions bitmaps
+ // if found at older tx - we are done, just return
+ // if found at yanger tx - clear it as page should be set at oldest tx (our)
+ TranData::ConstAccessor accessor(&m_tranData);
+ if (accessor.getFirst())
+ do
+ {
+ const TranBitMap* item = accessor.current();
+ if (item->first <= tranid)
+ {
+ if (item->second->test(pageno))
+ return;
+ }
+ else
+ {
+ if (item->second->clear(pageno))
+ break;
+ }
+ } while(accessor.getNext());
+
+ // add page to the our tx bitmap
+ if (bm)
+ {
+ PBM_SET(&m_pool, &bm, pageno);
+ }
+ else
+ {
+ PBM_SET(&m_pool, &bm, pageno);
+ m_tranData.put(tranid, bm);
+ }
+}
+
+
+void GarbageCollector::RelationData::getPageBitmap(const SLONG oldest_snapshot, PageBitmap **sbm)
+{
+ TranData::Accessor accessor(&m_tranData);
+ while (accessor.getFirst())
+ {
+ TranBitMap* item = accessor.current();
+
+ if (item->first >= oldest_snapshot)
+ break;
+
+ PageBitmap* bm_tran = item->second;
+ PageBitmap** bm_or = PageBitmap::bit_or(sbm, &bm_tran);
+ if (*bm_or == item->second)
+ {
+ bm_tran = *sbm;
+ *sbm = item->second;
+ item->second = bm_tran;
+ }
+ delete item->second;
+
+ m_tranData.remove(item->first);
+ }
+}
+
+
+void GarbageCollector::RelationData::swept(const SLONG oldest_snapshot)
+{
+ TranData::Accessor accessor(&m_tranData);
+ while (accessor.getFirst())
+ {
+ TranBitMap* item = accessor.current();
+
+ if (item->first >= oldest_snapshot)
+ break;
+
+ delete item->second;
+ m_tranData.remove(item->first);
+ }
+}
+
+
+SLONG GarbageCollector::RelationData::minTranID() const
+{
+ TranData::ConstAccessor accessor(&m_tranData);
+ if (accessor.getFirst())
+ return accessor.current()->first;
+ else
+ return MAX_TRA_NUMBER;
+}
+
+
+GarbageCollector::~GarbageCollector()
+{
+ SyncLockGuard exGuard(&m_sync, SYNC_EXCLUSIVE, "GarbageCollector::~GarbageCollector");
+ for (size_t pos = 0; pos < m_relations.getCount(); pos++)
+ {
+ Sync sync(&m_relations[pos]->m_sync, "GarbageCollector::~GarbageCollector");
+ sync.lock(SYNC_EXCLUSIVE);
+ sync.unlock();
+ delete m_relations[pos];
+ }
+
+ m_relations.clear();
+}
+
+
+void GarbageCollector::addPage(const USHORT relID, const ULONG pageno, const SLONG tranid)
+{
+ Sync syncGC(&m_sync, "GarbageCollector::addPage");
+ RelationData* relData = getRelData(syncGC, relID, true);
+
+ SyncLockGuard syncData(&relData->m_sync, SYNC_EXCLUSIVE, "GarbageCollector::addPage");
+ syncGC.unlock();
+
+ relData->addPage(pageno, tranid);
+}
+
+
+bool GarbageCollector::getPageBitmap(const SLONG oldest_snapshot, USHORT &relID, PageBitmap **sbm)
+{
+ *sbm = NULL;
+ SyncLockGuard shGuard(&m_sync, SYNC_EXCLUSIVE, "GarbageCollector::getPageBitmap");
+
+ if (m_relations.isEmpty())
+ {
+ m_nextRelID = 0;
+ return false;
+ }
+
+ size_t pos;
+ if (!m_relations.find(m_nextRelID, pos) && (pos == m_relations.getCount()) )
+ pos = 0;
+
+ for (; pos < m_relations.getCount(); pos++)
+ {
+ RelationData* relData = m_relations[pos];
+ SyncLockGuard syncData(&relData->m_sync, SYNC_EXCLUSIVE, "GarbageCollector::getPageBitmap");
+ relData->getPageBitmap(oldest_snapshot, sbm);
+ if (*sbm)
+ {
+ relID = relData->getRelID();
+ m_nextRelID = relID + 1;
+ return true;
+ }
+ }
+
+ m_nextRelID = 0;
+ return false;
+}
+
+
+void GarbageCollector::removeRelation(const USHORT relID)
+{
+ Sync syncGC(&m_sync, "GarbageCollector::removeRelation");
+ syncGC.lock(SYNC_EXCLUSIVE);
+
+ size_t pos;
+ if (!m_relations.find(relID, pos))
+ return;
+
+ RelationData* relData = m_relations[pos];
+ Sync syncData(&relData->m_sync, "GarbageCollector::removeRelation");
+ syncData.lock(SYNC_EXCLUSIVE);
+
+ m_relations.remove(pos);
+ syncGC.unlock();
+
+ syncData.unlock();
+ delete relData;
+}
+
+
+void GarbageCollector::sweptRelation(const SLONG oldest_snapshot, const USHORT relID)
+{
+ Sync syncGC(&m_sync, "GarbageCollector::sweptRelation");
+
+ RelationData* relData = getRelData(syncGC, relID, false);
+ if (relData)
+ {
+ SyncLockGuard syncData(&relData->m_sync, SYNC_EXCLUSIVE, "GarbageCollector::sweptRelation");
+
+ syncGC.unlock();
+ relData->swept(oldest_snapshot);
+ }
+ return;
+}
+
+
+SLONG GarbageCollector::minTranID(const USHORT relID)
+{
+ Sync syncGC(&m_sync, "GarbageCollector::minTranID");
+
+ RelationData* relData = getRelData(syncGC, relID, false);
+ if (relData)
+ {
+ SyncLockGuard syncData(&relData->m_sync, SYNC_SHARED, "GarbageCollector::minTranID");
+
+ syncGC.unlock();
+ return relData->minTranID();
+ }
+
+ return MAX_TRA_NUMBER;
+}
+
+
+GarbageCollector::RelationData* GarbageCollector::getRelData(Sync &sync, const USHORT relID, bool allowCreate)
+{
+ size_t pos;
+
+ sync.lock(SYNC_SHARED);
+ if (!m_relations.find(relID, pos))
+ {
+ if (!allowCreate)
+ return NULL;
+
+ sync.unlock();
+ sync.lock(SYNC_EXCLUSIVE);
+ if (!m_relations.find(relID, pos))
+ {
+ m_relations.insert(pos, FB_NEW(m_pool) RelationData(m_pool, relID));
+ sync.downgrade(SYNC_SHARED);
+ }
+ }
+
+ return m_relations[pos];
+}
+
+
+} // namespace Jrd
Property changes on: firebird/trunk/src/jrd/GarbageCollector.cpp
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:eol-style
+ native
Added: firebird/trunk/src/jrd/GarbageCollector.h
===================================================================
--- firebird/trunk/src/jrd/GarbageCollector.h (rev 0)
+++ firebird/trunk/src/jrd/GarbageCollector.h 2011-05-27 07:57:16 UTC (rev 53021)
@@ -0,0 +1,108 @@
+/*
+ * The contents of this file are subject to the Initial
+ * Developer's Public License Version 1.0 (the "License");
+ * you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
+ *
+ * Software distributed under the License is distributed AS IS,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied.
+ * See the License for the specific language governing rights
+ * and limitations under the License.
+ *
+ * The Original Code was created by Vlad Khorsun
+ * for the Firebird Open Source RDBMS project.
+ *
+ * Copyright (c) 2011 Vlad Khorsun <hv...@us...>
+ * and all contributors signed below.
+ *
+ * All Rights Reserved.
+ * Contributor(s): ______________________________________.
+ */
+
+#ifndef JRD_GARBAGE_COLLECTOR_H
+#define JRD_GARBAGE_COLLECTOR_H
+
+#include "firebird.h"
+#include "../common/classes/array.h"
+#include "../common/classes/GenericMap.h"
+#include "../common/classes/SyncObject.h"
+#include "../jrd/sbm.h"
+
+
+namespace Jrd {
+
+class Database;
+class Savepoint;
+
+class GarbageCollector
+{
+public:
+ GarbageCollector(MemoryPool& p, Database* dbb)
+ : m_pool(p), m_database(dbb), m_relations(m_pool), m_nextRelID(0)
+ {}
+
+ ~GarbageCollector();
+
+ void addPage(const USHORT relID, const ULONG pageno, const SLONG tranid);
+ bool getPageBitmap(const SLONG oldest_snapshot, USHORT &relID, PageBitmap **sbm);
+ void removeRelation(const USHORT relID);
+ void sweptRelation(const SLONG oldest_snapshot, const USHORT relID);
+
+ SLONG minTranID(const USHORT relID);
+
+private:
+ typedef Firebird::Pair<Firebird::NonPooled<SLONG, PageBitmap*> > TranBitMap;
+ typedef Firebird::GenericMap<TranBitMap> TranData;
+
+
+ class RelationData
+ {
+ public:
+ explicit RelationData(MemoryPool& p, USHORT relID)
+ : m_pool(p), m_tranData(p), m_relID(relID)
+ {}
+
+ ~RelationData() { clear(); }
+
+ void addPage(const ULONG pageno, const SLONG tranid);
+ void getPageBitmap(const SLONG oldest_snapshot, PageBitmap **sbm);
+ void swept(const SLONG oldest_snapshot);
+ SLONG minTranID() const;
+
+ USHORT getRelID() const
+ {
+ return m_relID;
+ }
+
+ static inline const USHORT generate(void const*, const RelationData* Item)
+ {
+ return Item->m_relID;
+ }
+
+ void clear();
+
+ Firebird::MemoryPool& m_pool;
+ Firebird::SyncObject m_sync;
+ TranData m_tranData;
+ USHORT m_relID;
+ };
+
+ typedef Firebird::SortedArray<
+ RelationData*,
+ Firebird::EmptyStorage<RelationData*>,
+ LONG,
+ RelationData> RelGarbageArray;
+
+ RelationData* getRelData(Firebird::Sync &sync, const USHORT relID, bool allowCreate);
+
+ Firebird::MemoryPool& m_pool;
+ Firebird::SyncObject m_sync;
+ Database* m_database;
+ RelGarbageArray m_relations;
+ USHORT m_nextRelID;
+};
+
+} // namespace Jrd
+
+#endif JRD_GARBAGE_COLLECTOR_H
Property changes on: firebird/trunk/src/jrd/GarbageCollector.h
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:eol-style
+ native
Modified: firebird/trunk/src/jrd/Relation.cpp
===================================================================
--- firebird/trunk/src/jrd/Relation.cpp 2011-05-27 03:27:46 UTC (rev 53020)
+++ firebird/trunk/src/jrd/Relation.cpp 2011-05-27 07:57:16 UTC (rev 53021)
@@ -10,10 +10,10 @@
* See the License for the specific language governing rights
* and limitations under the License.
*
- * The Original Code was created by Vlad Horsun
+ * The Original Code was created by Vlad Khorsun
* for the Firebird Open Source RDBMS project.
*
- * Copyright (c) 2005 Vlad Horsun <hv...@us...>
+ * Copyright (c) 2005 Vlad Khorsun <hv...@us...>
* and all contributors signed below.
*
* All Rights Reserved.
@@ -32,88 +32,8 @@
using namespace Jrd;
-#ifdef GARBAGE_THREAD
+/// jrd_rel
-void RelationGarbage::clear()
-{
- TranGarbage *item = array.begin(), *const last = array.end();
-
- for (; item < last; item++)
- {
- delete item->bm;
- item->bm = NULL;
- }
-
- array.clear();
-}
-
-void RelationGarbage::addPage(MemoryPool* pool, const SLONG pageno, const SLONG tranid)
-{
- bool found = false;
- TranGarbage const *item = array.begin(), *const last = array.end();
-
- for (; item < last; item++)
- {
- if (item->tran <= tranid)
- {
- if (PageBitmap::test(item->bm, pageno))
- {
- found = true;
- break;
- }
- }
- else
- {
- if (item->bm->clear(pageno))
- break;
- }
- }
-
- if (!found)
- {
- PageBitmap *bm = NULL;
- size_t pos = 0;
-
- if (array.find(tranid, pos) )
- {
- bm = array[pos].bm;
- PBM_SET(pool, &bm, pageno);
- }
- else
- {
- bm = NULL;
- PBM_SET(pool, &bm, pageno);
- array.add(TranGarbage(bm, tranid));
- }
- }
-}
-
-void RelationGarbage::getGarbage(const SLONG oldest_snapshot, PageBitmap **sbm)
-{
- while (array.getCount() > 0)
- {
- TranGarbage& garbage = array[0];
-
- if (garbage.tran >= oldest_snapshot)
- break;
-
- PageBitmap* bm_tran = garbage.bm;
- PageBitmap** bm_or = PageBitmap::bit_or(sbm, &bm_tran);
- if (*bm_or == garbage.bm)
- {
- bm_tran = *sbm;
- *sbm = garbage.bm;
- garbage.bm = bm_tran;
- }
- delete garbage.bm;
-
- // Need to cast zero to exact type because literal zero means null pointer
- array.remove(static_cast<size_t>(0));
- }
-}
-
-#endif //GARBAGE_THREAD
-
RelationPages* jrd_rel::getPagesInternal(thread_db* tdbb, SLONG tran, bool allocPages)
{
if (tdbb->tdbb_flags & TDBB_use_db_page_space)
Modified: firebird/trunk/src/jrd/Relation.h
===================================================================
--- firebird/trunk/src/jrd/Relation.h 2011-05-27 03:27:46 UTC (rev 53020)
+++ firebird/trunk/src/jrd/Relation.h 2011-05-27 07:57:16 UTC (rev 53021)
@@ -63,54 +63,7 @@
typedef Firebird::SortedArray<ViewContext*, Firebird::EmptyStorage<ViewContext*>,
USHORT, ViewContext> ViewContexts;
-#ifdef GARBAGE_THREAD
-class RelationGarbage
-{
-private:
- class TranGarbage
- {
- public:
- SLONG tran;
- PageBitmap *bm;
-
- TranGarbage(PageBitmap* aBm, SLONG aTran)
- : tran(aTran), bm(aBm)
- {}
-
- static inline const SLONG generate(void const*, const TranGarbage& Item)
- {
- return Item.tran;
- }
- };
-
- typedef Firebird::SortedArray<
- TranGarbage,
- Firebird::EmptyStorage<TranGarbage>,
- SLONG,
- TranGarbage> TranGarbageArray;
-
- TranGarbageArray array;
-
-public:
- explicit RelationGarbage(MemoryPool& p)
- : array(p)
- {}
- ~RelationGarbage() { clear(); }
-
- void addPage(MemoryPool* pool, const SLONG pageno, const SLONG tranid);
- void clear();
-
- void getGarbage(const SLONG oldest_snapshot, PageBitmap **sbm);
-
- SLONG minTranID() const
- {
- return (array.getCount() > 0) ? array[0].tran : MAX_SLONG;
- }
-};
-
-#endif //GARBAGE_THREAD
-
class RelationPages
{
public:
@@ -197,10 +150,6 @@
ExternalFile* rel_file; // external file name
vec<Record*>* rel_gc_rec; // vector of records for garbage collection
-#ifdef GARBAGE_THREAD
- PageBitmap* rel_gc_bitmap; // garbage collect bitmap of data page sequences
- RelationGarbage* rel_garbage; // deferred gc bitmap's by tran numbers
-#endif
USHORT rel_use_count; // requests compiled with relation
USHORT rel_sweep_count; // sweep and/or garbage collector threads active
Modified: firebird/trunk/src/jrd/cch.cpp
===================================================================
--- firebird/trunk/src/jrd/cch.cpp 2011-05-27 03:27:46 UTC (rev 53020)
+++ firebird/trunk/src/jrd/cch.cpp 2011-05-27 07:57:16 UTC (rev 53021)
@@ -76,7 +76,7 @@
IMPLEMENT_TRACE_ROUTINE(cch_trace, "CCH")
#endif
-// #define CACHE_WRITER
+#define CACHE_WRITER
#ifdef SUPERSERVER_V2
#define CACHE_READER
@@ -1038,7 +1038,6 @@
// Wait for cache writer startup to complete.
while (bcb->bcb_flags & BCB_writer_start)
{
- Database::Checkout dcoHolder(dbb);
THREAD_YIELD();
}
@@ -1048,10 +1047,7 @@
{
bcb->bcb_flags &= ~BCB_cache_writer;
bcb->bcb_writer_sem.release(); // Wake up running thread
- { // scope
- Database::Checkout dcoHolder(dbb);
- bcb->bcb_writer_fini.enter();
- }
+ bcb->bcb_writer_fini.enter();
}
#endif
@@ -1268,7 +1264,7 @@
BufferDesc* bdb;
if ((bcb->bcb_flags & BCB_free_pending) &&
- (bdb = get_buffer(tdbb, FREE_PAGE, SYNC_SHARED /*LATCH_none*/, 1)))
+ (bdb = get_buffer(tdbb, FREE_PAGE, SYNC_NONE, 1)))
{
if (!write_buffer(tdbb, bdb, bdb->bdb_page, true, tdbb->tdbb_status_vector, true))
CCH_unwind(tdbb, false);
@@ -1565,7 +1561,17 @@
if (dbb->dbb_lock->lck_logical != LCK_EX) {
dbb->dbb_ast_flags |= DBB_assert_locks;
}
+}
+
+void CCH_init2(thread_db* tdbb)
+{
+ Database* dbb = tdbb->getDatabase();
+ BufferControl* bcb = dbb->dbb_bcb;
+
+ if (!(bcb->bcb_flags & BCB_exclusive) || (bcb->bcb_flags & (BCB_cache_writer | BCB_writer_start)))
+ return;
+
#ifdef CACHE_READER
if (gds__thread_start(cache_reader, dbb, THREAD_high, 0, 0))
{
@@ -1586,7 +1592,7 @@
try
{
- ThreadSync::start(cache_writer, dbb, THREAD_high);
+ Thread::start(cache_writer, dbb, THREAD_medium);
}
catch (const Exception&)
{
@@ -1594,10 +1600,7 @@
ERR_bugcheck_msg("cannot start cache writer thread");
}
- { // scope
- Database::Checkout dcoHolder(dbb);
- bcb->bcb_writer_init.enter();
- }
+ bcb->bcb_writer_init.enter();
}
#endif
}
@@ -2942,6 +2945,7 @@
#ifdef CACHE_WRITER
+
static THREAD_ENTRY_DECLARE cache_writer(THREAD_ENTRY_PARAM arg)
{
/**************************************
@@ -2958,11 +2962,10 @@
*
**************************************/
- /***
Database* dbb = (Database*)arg;
- Database::SyncGuard dsGuard(dbb);
ISC_STATUS_ARRAY status_vector;
+ MOVE_CLEAR(status_vector, sizeof(status_vector));
// Establish a thread context.
ThreadContextHolder tdbb(status_vector);
@@ -2970,10 +2973,20 @@
// Dummy attachment needed for lock owner identification.
tdbb->setDatabase(dbb);
- Jrd::Attachment* const attachment = Jrd::Attachment::create(dbb, 0);
+
+ RefPtr<JAttachment> jAtt(NULL);
+
+ Jrd::Attachment* attachment = Jrd::Attachment::create(dbb);
+ jAtt = attachment->att_interface = new SysAttachment(attachment);
+ jAtt->getMutex()->enter();
+
tdbb->setAttachment(attachment);
attachment->att_filename = dbb->dbb_filename;
+ UserId user;
+ user.usr_user_name = "Cache Writer";
+ attachment->att_user = &user;
+
BufferControl* bcb = dbb->dbb_bcb;
Jrd::ContextPoolHolder context(tdbb, bcb->bcb_bufferpool);
@@ -2982,9 +2995,13 @@
// return, unlike the other try blocks further down the page.
Semaphore& writer_sem = bcb->bcb_writer_sem;
- try {
+ try
+ {
LCK_init(tdbb, LCK_OWNER_attachment);
+ PAG_header(tdbb, true);
+ PAG_attachment_id(tdbb);
TRA_init(attachment);
+
bcb->bcb_flags |= BCB_cache_writer;
bcb->bcb_flags &= ~BCB_writer_start;
@@ -2999,49 +3016,10 @@
bcb->bcb_flags &= ~(BCB_cache_writer | BCB_writer_start);
return (THREAD_ENTRY_RETURN)(-1);
}
- ***/
- ISC_STATUS_ARRAY status_vector = {0};
- Jrd::Attachment* attachment= NULL;
+ attachment->att_next = dbb->dbb_sys_attachments;
+ dbb->dbb_sys_attachments = attachment;
- {
- bcb->bcb_flags |= BCB_cache_writer;
- bcb->bcb_flags &= ~BCB_writer_start;
- bcb->bcb_writer_init.release();
-
- Database* dbb = (Database*)arg;
- Database::SyncGuard dsGuard(dbb);
- RefPtr<BufferControl> bcb = dbb->dbb_bcb;
-
- ClumpletWriter dpb(ClumpletReader::Tagged, MAX_DPB_SIZE);
- dpb.reset(isc_dpb_version1);
- dpb.insertString(isc_dpb_trusted_auth, "Cache Writer");
-
- if (jrd8_attach_database(status_vector, NULL, dbb->dbb_filename.c_str(), &attachment,
- dpb.getBufferLength(), dpb.getBuffer()))
- {
- gds__log_status(dbb->dbb_filename.c_str(), status_vector);
-
- bcb->bcb_flags &= ~BCB_writer_start;
-
- bcb->bcb_writer_init.release(); // ?
-
- return (THREAD_ENTRY_RETURN)(-1);
- }
- }
-
- Database* dbb = attachment->att_database;
-
- // Establish a thread context.
- ThreadContextHolder tdbb(status_vector);
- tdbb->setDatabase(dbb);
- tdbb->setAttachment(attachment);
-
- BufferControl* bcb = dbb->dbb_bcb;
- Jrd::ContextPoolHolder context(tdbb, bcb->bcb_bufferpool);
-
- Semaphore& writer_sem = bcb->bcb_writer_sem;
-
try
{
while (bcb->bcb_flags & BCB_cache_writer)
@@ -3053,10 +3031,8 @@
if (dbb->dbb_flags & DBB_suspend_bgio)
{
- { //scope
- Database::Checkout dcoHolder(dbb);
- writer_sem.tryEnter(10);
- }
+ Attachment::Checkout cout(attachment);
+ writer_sem.tryEnter(10);
continue;
}
@@ -3070,14 +3046,9 @@
}
#endif
- { // scope
- Database::Checkout dcoHolder(dbb);
- THREAD_YIELD();
- }
-
if (bcb->bcb_flags & BCB_free_pending)
{
- BufferDesc* bdb = get_buffer(tdbb, FREE_PAGE, None, 1);
+ BufferDesc* bdb = get_buffer(tdbb, FREE_PAGE, SYNC_NONE, 1);
if (bdb) {
write_buffer(tdbb, bdb, bdb->bdb_page, true, status_vector, true);
}
@@ -3090,12 +3061,11 @@
dbb->dbb_reader_sem.post();
}
#endif
-#ifdef GARBAGE_THREAD
+
if ((dbb->dbb_flags & DBB_garbage_collector) && !(dbb->dbb_flags & DBB_gc_active))
{
dbb->dbb_gc_sem.release();
}
-#endif
}
// If there's more work to do voluntarily ask to be rescheduled.
@@ -3121,16 +3091,14 @@
else
{
bcb->bcb_flags &= ~BCB_writer_active;
- Database::Checkout dcoHolder(dbb);
+ Attachment::Checkout cout(attachment);
writer_sem.tryEnter(10);
}
}
- /***
LCK_fini(tdbb, LCK_OWNER_attachment);
- Jrd::Attachment::destroy(attachment); // no need saving warning error strings here
- ***/
- jrd8_detach_database(status_vector, &attachment);
+ jAtt = NULL;
+
tdbb->setAttachment(NULL);
bcb->bcb_flags &= ~BCB_cache_writer;
@@ -3964,6 +3932,7 @@
}
if (walk)
{
+ oldest->release(tdbb);
if (!--walk)
break;
@@ -5047,7 +5016,7 @@
if (!isTempPage &&
(backup_state == nbak_state_stalled ||
- (backup_state == nbak_state_merge && bdb->bdb_difference_page)))
+ (backup_state == nbak_state_merge && bdb->bdb_difference_page)))
{
const bool res = dbb->dbb_backup_manager->writeDifference(status,
Modified: firebird/trunk/src/jrd/cch.h
===================================================================
--- firebird/trunk/src/jrd/cch.h 2011-05-27 03:27:46 UTC (rev 53020)
+++ firebird/trunk/src/jrd/cch.h 2011-05-27 07:57:16 UTC (rev 53021)
@@ -111,13 +111,11 @@
static BufferControl* create();
static void destroy(BufferControl*);
+ Database* bcb_database;
+
Firebird::MemoryPool* bcb_bufferpool;
Firebird::MemoryStats bcb_memory_stats;
- // To be deleted when PAG will be not coupled with Database.
- // Used only in CS mode when each BufferControl have one Database.
- Database* bcb_database;
-
UCharStack bcb_memory; // Large block partitioned into buffers
que bcb_in_use; // Que of buffers in use, main LRU que
que bcb_pending; // Que of buffers which are going to be freed and reassigned
Modified: firebird/trunk/src/jrd/cch_proto.h
===================================================================
--- firebird/trunk/src/jrd/cch_proto.h 2011-05-27 03:27:46 UTC (rev 53020)
+++ firebird/trunk/src/jrd/cch_proto.h 2011-05-27 07:57:16 UTC (rev 53021)
@@ -54,6 +54,7 @@
void CCH_get_related(Jrd::thread_db*, Jrd::PageNumber, Jrd::PagesArray&);
Ods::pag* CCH_handoff(Jrd::thread_db*, Jrd::win*, ULONG, int, SCHAR, int, const bool);
void CCH_init(Jrd::thread_db*, ULONG, bool);
+void CCH_init2(Jrd::thread_db*);
void CCH_mark(Jrd::thread_db*, Jrd::win*, bool, bool);
void CCH_must_write(Jrd::thread_db*, Jrd::win*);
void CCH_precedence(Jrd::thread_db*, Jrd::win*, ULONG);
Modified: firebird/trunk/src/jrd/dfw.epp
===================================================================
--- firebird/trunk/src/jrd/dfw.epp 2011-05-27 03:27:46 UTC (rev 53020)
+++ firebird/trunk/src/jrd/dfw.epp 2011-05-27 07:57:16 UTC (rev 53021)
@@ -118,6 +118,7 @@
#include "../jrd/event_proto.h"
#include "../jrd/nbak.h"
#include "../jrd/trig.h"
+#include "../jrd/GarbageCollector.h"
#include "../jrd/IntlManager.h"
#include "../jrd/UserManagement.h"
#include "../jrd/Function.h"
@@ -4166,15 +4167,11 @@
Arg::Gds(isc_obj_in_use) << Arg::Str(work->dfw_name));
}
-#ifdef GARBAGE_THREAD
// Free any memory associated with the relation's garbage collection bitmap
+ if (dbb->dbb_garbage_collector) {
+ dbb->dbb_garbage_collector->removeRelation(relation->rel_id);
+ }
- delete relation->rel_gc_bitmap;
- relation->rel_gc_bitmap = NULL;
-
- delete relation->rel_garbage;
- relation->rel_garbage = NULL;
-#endif
if (relation->rel_file) {
EXT_fini (relation, false);
}
Modified: firebird/trunk/src/jrd/dpm.epp
===================================================================
--- firebird/trunk/src/jrd/dpm.epp 2011-05-27 03:27:46 UTC (rev 53020)
+++ firebird/trunk/src/jrd/dpm.epp 2011-05-27 07:57:16 UTC (rev 53021)
@@ -1549,7 +1549,7 @@
// If I'm a sweeper I don't need to look at swept pages. Also I should
// check processed pages if they were swept.
- const bool sweeper = (tdbb->tdbb_flags & TDBB_sweeper);
+ const bool sweeper = (rpb->rpb_stream_flags & RPB_s_sweeper);
if (sweeper && (pp_sequence || slot) && !line)
{
Modified: firebird/trunk/src/jrd/jrd.cpp
===================================================================
--- firebird/trunk/src/jrd/jrd.cpp 2011-05-27 03:27:46 UTC (rev 53020)
+++ firebird/trunk/src/jrd/jrd.cpp 2011-05-27 07:57:16 UTC (rev 53021)
@@ -1379,6 +1379,7 @@
// initialize shadowing as soon as the database is ready for it
// but before any real work is done
SDW_init(tdbb, options.dpb_activate_shadow, options.dpb_delete_shadow);
+ CCH_init2(tdbb);
}
else
{
@@ -1604,11 +1605,10 @@
ERR_post(Arg::Gds(isc_bad_dpb_content) << Arg::Gds(isc_cant_validate));
}
-#ifdef GARBAGE_THREAD
// Can't allow garbage collection during database validation.
VIO_fini(tdbb);
-#endif
+
if (!VAL_validate(tdbb, options.dpb_verify)) {
ERR_punt();
}
@@ -1685,11 +1685,7 @@
}
PAG_attachment_id(tdbb);
-
-#ifdef GARBAGE_THREAD
VIO_init(tdbb);
-#endif
-
CCH_release_exclusive(tdbb);
// if there was an error, the status vector is all set
@@ -2573,10 +2569,8 @@
// but before any real work is done
SDW_init(tdbb, options.dpb_activate_shadow, options.dpb_delete_shadow);
-
-#ifdef GARBAGE_THREAD
+ CCH_init2(tdbb);
VIO_init(tdbb);
-#endif
if (options.dpb_set_db_readonly)
{
@@ -4282,6 +4276,22 @@
}
+void SysAttachment::destroy(Attachment* attachment)
+{
+ Database* dbb = attachment->att_database;
+
+ for (Jrd::Attachment** ptr = &dbb->dbb_sys_attachments; *ptr; ptr = &(*ptr)->att_next)
+ {
+ if (*ptr == attachment)
+ {
+ *ptr = attachment->att_next;
+ break;
+ }
+ }
+ Jrd::Attachment::destroy(attachment);
+}
+
+
JTransaction* JStatement::execute(IStatus* user_status, Firebird::ITransaction* apiTra,
unsigned int in_msg_type, const FbMessage* inMsgBuffer, const FbMessage* outMsgBuffer)
{
@@ -5666,21 +5676,27 @@
if ((dbb->dbb_flags & (DBB_gc_cooperative | DBB_gc_background)) == 0)
{
- string gc_policy = dbb->dbb_config->getGCPolicy();
- gc_policy.lower();
- if (gc_policy == GCPolicyCooperative) {
+ if (!dbb->dbb_config->getSharedCache()) {
dbb->dbb_flags |= DBB_gc_cooperative;
}
- else if (gc_policy == GCPolicyBackground) {
- dbb->dbb_flags |= DBB_gc_background;
- }
- else if (gc_policy == GCPolicyCombined) {
- dbb->dbb_flags |= DBB_gc_cooperative | DBB_gc_background;
- }
- else // config value is invalid
+ else
{
- // this should not happen - means bug in config
- fb_assert(false);
+ string gc_policy = dbb->dbb_config->getGCPolicy();
+ gc_policy.lower();
+ if (gc_policy == GCPolicyCooperative) {
+ dbb->dbb_flags |= DBB_gc_cooperative;
+ }
+ else if (gc_policy == GCPolicyBackground) {
+ dbb->dbb_flags |= DBB_gc_background;
+ }
+ else if (gc_policy == GCPolicyCombined) {
+ dbb->dbb_flags |= DBB_gc_cooperative | DBB_gc_background;
+ }
+ else // config value is invalid
+ {
+ // this should not happen - means bug in config
+ fb_assert(false);
+ }
}
}
@@ -6054,9 +6070,7 @@
TRA_header_write(tdbb, dbb, 0L); // Update transaction info on header page.
#endif
-#ifdef GARBAGE_THREAD
VIO_fini(tdbb);
-#endif
CMP_fini(tdbb);
CCH_fini(tdbb);
@@ -6853,6 +6867,10 @@
{
shutdown_database(dbb, true);
}
+ else
+ {
+ dbb->dbb_sync.unlock();
+ }
}
}
}
Modified: firebird/trunk/src/jrd/req.h
===================================================================
--- firebird/trunk/src/jrd/req.h 2011-05-27 03:27:46 UTC (rev 53020)
+++ firebird/trunk/src/jrd/req.h 2011-05-27 07:57:16 UTC (rev 53021)
@@ -123,6 +123,7 @@
const USHORT RPB_s_update = 0x2; // input stream fetched for update
const USHORT RPB_s_no_data = 0x4; // nobody is going to access the data
const USHORT RPB_s_undo_data = 0x8; // data got from undo log
+const USHORT RPB_s_sweeper = 0x10; // garbage collector - skip swept pages
#define SET_NULL(record, id) record->rec_data [id >> 3] |= (1 << (id & 7))
#define CLEAR_NULL(record, id) record->rec_data [id >> 3] &= ~(1 << (id & 7))
Modified: firebird/trunk/src/jrd/tra.cpp
===================================================================
--- firebird/trunk/src/jrd/tra.cpp 2011-05-27 03:27:46 UTC (rev 53020)
+++ firebird/trunk/src/jrd/tra.cpp 2011-05-27 07:57:16 UTC (rev 53021)
@@ -82,10 +82,6 @@
using namespace Ods;
using namespace Firebird;
-#ifdef GARBAGE_THREAD
-#include "../common/isc_s_proto.h"
-#endif
-
typedef Firebird::GenericMap<Firebird::Pair<Firebird::NonPooled<USHORT, UCHAR> > > RelationLockTypeMap;
@@ -446,13 +442,10 @@
if (transaction->tra_flags & (TRA_prepare2 | TRA_reconnected))
MET_update_transaction(tdbb, transaction, true);
-#ifdef GARBAGE_THREAD
// Flush pages if transaction logically modified data
if (transaction->tra_flags & TRA_write)
-#endif
CCH_flush(tdbb, FLUSH_TRAN, transaction->tra_number);
-#ifdef GARBAGE_THREAD
else if (transaction->tra_flags & (TRA_prepare2 | TRA_reconnected))
{
// If the transaction only read data but is a member of a
@@ -461,7 +454,6 @@
CCH_flush(tdbb, FLUSH_SYSTEM, 0);
}
-#endif
if (retaining_flag)
{
@@ -993,13 +985,10 @@
DFW_perform_work(tdbb, transaction);
-#ifdef GARBAGE_THREAD
// Flush pages if transaction logically modified data
if (transaction->tra_flags & TRA_write)
-#endif
CCH_flush(tdbb, FLUSH_TRAN, transaction->tra_number);
-#ifdef GARBAGE_THREAD
else if (transaction->tra_flags & TRA_prepare2)
{
// If the transaction only read data but is a member of a
@@ -1008,7 +997,6 @@
CCH_flush(tdbb, FLUSH_SYSTEM, 0);
}
-#endif
// Set the state on the inventory page to be limbo
@@ -1779,7 +1767,6 @@
tdbb->setTransaction(transaction);
-#ifdef GARBAGE_THREAD
// The garbage collector runs asynchronously with respect to
// our database sweep. This isn't good enough since we must
// be absolutely certain that all dead transactions have been
@@ -1788,7 +1775,6 @@
// synchronously perform the garbage collection ourselves.
transaction->tra_attachment->att_flags &= ~ATT_notify_gc;
-#endif
if (VIO_sweep(tdbb, transaction))
{
@@ -3490,13 +3476,11 @@
{
dbb->dbb_oldest_snapshot = trans->tra_oldest_active;
-#if defined(GARBAGE_THREAD)
if (!(dbb->dbb_flags & DBB_gc_active) && (dbb->dbb_flags & DBB_gc_background))
{
dbb->dbb_flags |= DBB_gc_pending;
dbb->dbb_gc_sem.release();
}
-#endif
}
// If the transaction block is getting out of hand, force a sweep
Modified: firebird/trunk/src/jrd/vio.cpp
===================================================================
--- firebird/trunk/src/jrd/vio.cpp 2011-05-27 03:27:46 UTC (rev 53020)
+++ firebird/trunk/src/jrd/vio.cpp 2011-05-27 07:57:16 UTC (rev 53021)
@@ -61,6 +61,8 @@
#include "../jrd/btr.h"
#include "../jrd/exe.h"
#include "../jrd/rse.h"
+#include "../jrd/scl.h"
+#include "../common/classes/alloc.h"
#include "../common/ThreadStart.h"
#include "../jrd/thread_proto.h"
#ifdef VIO_DEBUG
@@ -77,6 +79,7 @@
#include "../jrd/idx_proto.h"
#include "../common/isc_s_proto.h"
#include "../jrd/jrd_proto.h"
+#include "../jrd/ini_proto.h"
#include "../jrd/lck_proto.h"
#include "../jrd/met_proto.h"
#include "../jrd/mov_proto.h"
@@ -88,6 +91,7 @@
#include "../jrd/dyn_ut_proto.h"
#include "../jrd/Function.h"
#include "../common/StatusArg.h"
+#include "../jrd/GarbageCollector.h"
using namespace Jrd;
using namespace Firebird;
@@ -104,9 +108,7 @@
USHORT irrelevant_field, bool void_update_is_relevant = false);
static void garbage_collect(thread_db*, record_param*, ULONG, RecordStack&);
static void garbage_collect_idx(thread_db*, record_param*, Record*, Record*);
-#ifdef GARBAGE_THREAD
static THREAD_ENTRY_DECLARE garbage_collector(THREAD_ENTRY_PARAM);
-#endif
enum UndoDataRet {
udExists,
@@ -118,9 +120,7 @@
static UndoDataRet get_undo_data(thread_db* tdbb, jrd_tra* transaction, record_param* rpb);
static void list_staying(thread_db*, record_param*, RecordStack&);
-#ifdef GARBAGE_THREAD
static void notify_garbage_collector(thread_db*, record_param *, SLONG = -1);
-#endif
static Record* realloc_record(Record*& record, USHORT fmt_length);
const int PREPARE_OK = 0;
@@ -143,15 +143,14 @@
// Pick up relation ids
#include "../jrd/ini.h"
-#ifdef GARBAGE_THREAD
static const UCHAR gc_tpb[] =
{
isc_tpb_version1, isc_tpb_read,
isc_tpb_read_committed, isc_tpb_rec_version,
isc_tpb_ignore_limbo
};
-#endif
+
inline void clearRecordStack(RecordStack& stack)
{
/**************************************
@@ -506,16 +505,6 @@
}
#endif
-#ifndef DEV_BUILD
- // The sweeper threads run in the background without
- // any way to inspect these counters. For debugging
- // purposes, they are maintained in the DEV_BUILD.
-
- if (tdbb->tdbb_flags & TDBB_sweeper) {
- return;
- }
-#endif
-
const USHORT relation_id = relation->rel_id;
vcl** ptr = attachment->att_counts + count_id;
@@ -546,10 +535,8 @@
**************************************/
SET_TDBB(tdbb);
-#ifdef GARBAGE_THREAD
const bool gcPolicyCooperative = tdbb->getDatabase()->dbb_flags & DBB_gc_cooperative;
const bool gcPolicyBackground = tdbb->getDatabase()->dbb_flags & DBB_gc_background;
-#endif
#ifdef VIO_DEBUG
if (debug_flag > DEBUG_TRACE_ALL)
@@ -620,10 +607,8 @@
!(rpb->rpb_flags & (rpb_deleted | rpb_damaged)) &&
(rpb->rpb_b_page == 0 || rpb->rpb_transaction_nr >= transaction->tra_oldest_active))
{
-#ifdef GARBAGE_THREAD
if (gcPolicyBackground && rpb->rpb_b_page)
notify_garbage_collector(tdbb, rpb);
-#endif // GARBAGE_THREAD
return true;
}
@@ -747,13 +732,11 @@
rpb->rpb_transaction_nr, transaction->tra_number);
}
#endif
-#ifdef GARBAGE_THREAD
- if (!(rpb->rpb_flags & rpb_chained) && attachment->att_flags & ATT_notify_gc)
+ if (gcPolicyBackground && !(rpb->rpb_flags & rpb_chained) && attachment->att_flags & ATT_notify_gc)
{
notify_garbage_collector(tdbb, rpb);
}
-#endif
case tra_precommitted:
if (attachment->att_flags & ATT_NO_CLEANUP ||
@@ -852,7 +835,6 @@
return false;
}
-#ifdef GARBAGE_THREAD
// hvlad: if I'm garbage collector I don't need to read backversion
// of active record. Just do notify self about it
if (attachment->att_flags & ATT_garbage_collector)
@@ -861,7 +843,6 @@
CCH_RELEASE(tdbb, &rpb->getWindow(tdbb));
return false;
}
-#endif
if (!(rpb->rpb_flags & rpb_delta))
{
@@ -986,7 +967,6 @@
if (rpb->rpb_transaction_nr < transaction->tra_oldest_active &&
!(attachment->att_flags & ATT_no_cleanup))
{
-#ifdef GARBAGE_THREAD
if (!gcPolicyCooperative && (attachment->att_flags & ATT_notify_gc) &&
!rpb->rpb_relation->isTemporary())
{
@@ -994,7 +974,6 @@
CCH_RELEASE(tdbb, &rpb->getWindow(tdbb));
}
else
-#endif
{
CCH_RELEASE(tdbb, &rpb->getWindow(tdbb));
expunge(tdbb, rpb, transaction, 0);
@@ -1017,7 +996,6 @@
if (cannotGC)
{
-#ifdef GARBAGE_THREAD
if (gcPolicyBackground &&
attachment->att_flags & (ATT_notify_gc | ATT_garbage_collector) &&
(rpb->rpb_b_page != 0 && !(rpb->rpb_flags & rpb_chained)) )
@@ -1025,20 +1003,18 @@
// VIO_chase_record_version
notify_garbage_collector(tdbb, rpb);
}
-#endif
return true;
}
// Garbage collect.
-#ifdef GARBAGE_THREAD
if (!gcPolicyCooperative && (attachment->att_flags & ATT_notify_gc) &&
!rpb->rpb_relation->isTemporary())
{
notify_garbage_collector(tdbb, rpb);
return true;
}
-#endif
+
purge(tdbb, rpb);
// Go back to be primary record version and chase versions all over again.
@@ -1696,17 +1672,14 @@
transaction->tra_flags |= TRA_perform_autocommit;
}
-#ifdef GARBAGE_THREAD
// VIO_erase
if ((tdbb->getDatabase()->dbb_flags & DBB_gc_background) && !rpb->rpb_relation->isTemporary())
{
notify_garbage_collector(tdbb, rpb, transaction->tra_number);
}
-#endif
}
-#ifdef GARBAGE_THREAD
void VIO_fini(thread_db* tdbb)
{
/**************************************
@@ -1728,7 +1701,6 @@
dbb->dbb_gc_fini.enter();
}
}
-#endif
bool VIO_garbage_collect(thread_db* tdbb, record_param* rpb, const jrd_tra* transaction)
@@ -2195,7 +2167,6 @@
}
-#ifdef GARBAGE_THREAD
void VIO_init(thread_db* tdbb)
{
/**************************************
@@ -2248,7 +2219,6 @@
}
}
}
-#endif
void VIO_merge_proc_sav_points(thread_db* tdbb, jrd_tra* transaction, Savepoint** sav_point_list)
@@ -2658,14 +2628,12 @@
transaction->tra_flags |= TRA_perform_autocommit;
}
-#ifdef GARBAGE_THREAD
// VIO_modify
if ((tdbb->getDatabase()->dbb_flags & DBB_gc_background) &&
!org_rpb->rpb_relation->isTemporary())
{
notify_garbage_collector(tdbb, org_rpb, transaction->tra_number);
}
-#endif
}
@@ -2792,7 +2760,7 @@
if (!record)
{
if (!pool)
- pool = dbb->dbb_permanent;
+ pool = rpb->rpb_relation->rel_pool;
record = rpb->rpb_record = FB_NEW_RPT(*pool, format->fmt_length) Record(*pool);
}
@@ -3186,12 +3154,14 @@
record_param rpb;
rpb.rpb_record = NULL;
- rpb.rpb_stream_flags = 0;
+ rpb.rpb_stream_flags = RPB_s_no_data | RPB_s_sweeper;
rpb.getWindow(tdbb).win_flags = WIN_large_scan;
jrd_rel* relation = 0; // wasn't initialized: memory problem in catch() part.
vec<jrd_rel*>* vector = 0;
+ GarbageCollector* gc = dbb->dbb_garbage_collector;
+
try {
for (size_t i = 1; (vector = attachment->att_relations) && i < vector->count(); i++)
@@ -3203,11 +3173,11 @@
rpb.rpb_number.setValue(BOF_NUMBER);
rpb.rpb_org_scans = relation->rel_scan_count++;
++relation->rel_sweep_count;
-#ifdef GARBAGE_THREAD
- if (relation->rel_garbage) {
- relation->rel_garbage->clear();
+
+ if (gc) {
+ gc->sweptRelation(transaction->tra_oldest_active, relation->rel_id);
}
-#endif
+
while (VIO_next_record(tdbb, &rpb, transaction, 0, false))
{
CCH_RELEASE(tdbb, &rpb.getWindow(tdbb));
@@ -4013,11 +3983,10 @@
if (!DPM_get(tdbb, rpb, LCK_write))
{
-#ifdef GARBAGE_THREAD
// expunge
if (tdbb->getDatabase()->dbb_flags & DBB_gc_background)
notify_garbage_collector(tdbb, rpb);
-#endif
+
return;
}
@@ -4038,11 +4007,9 @@
if (!(rpb->rpb_flags & rpb_deleted) || rpb->rpb_transaction_nr >= transaction->tra_oldest_active)
{
-#ifdef GARBAGE_THREAD
// expunge
if (tdbb->getDatabase()->dbb_flags & DBB_gc_background)
notify_garbage_collector(tdbb, rpb);
-#endif
CCH_RELEASE(tdbb, &rpb->getWindow(tdbb));
return;
@@ -4180,7 +4147,6 @@
}
-#ifdef GARBAGE_THREAD
static THREAD_ENTRY_DECLARE garbage_collector(THREAD_ENTRY_PARAM arg)
{
/**************************************
@@ -4216,27 +4182,46 @@
bool found = false, flush = false;
record_param rpb;
MOVE_CLEAR(&rpb, sizeof(record_param));
+ rpb.getWindow(tdbb).win_flags = WIN_garbage_collector;
+ rpb.rpb_stream_flags = RPB_s_no_data | RPB_s_sweeper;
jrd_rel* relation = NULL;
jrd_tra* transaction = NULL;
+ RefPtr<JAttachment> jAtt(NULL);
+ GarbageCollector* gc = NULL;
+
try {
// Pseudo attachment needed for lock owner identification.
Jrd::Attachment* const attachment = Jrd::Attachment::create(dbb);
+ jAtt = attachment->att_interface = new SysAttachment(attachment);
+ jAtt->getMutex()->enter();
+
tdbb->setAttachment(attachment);
attachment->att_filename = dbb->dbb_filename;
attachment->att_flags = ATT_garbage_collector;
- rpb.getWindow(tdbb).win_flags = WIN_garbage_collector;
+ UserId user;
+ user.usr_user_name = "Garbage Collector";
+ attachment->att_user = &user;
LCK_init(tdbb, LCK_OWNER_attachment);
+ INI_init(tdbb);
+ INI_init2(tdbb);
+ PAG_header(tdbb, true);
+ PAG_attachment_id(tdbb);
TRA_init(attachment);
+ gc = FB_NEW(*attachment->att_pool) GarbageCollector(*attachment->att_pool, dbb);
+ dbb->dbb_garbage_collector = gc;
+
+ attachment->att_next = dbb->dbb_sys_attachments;
+ dbb->dbb_sys_attachments = attachment;
+
// Notify our creator that we have started
dbb->dbb_flags |= DBB_garbage_collector;
dbb->dbb_gc_init.release();
-
} // try
catch (const Firebird::Exception&) {
goto gc_exit;
@@ -4256,7 +4241,7 @@
dbb->dbb_flags |= DBB_gc_active;
found = false;
- relation = 0;
+ relation = NULL;
// If background thread activity has been suspended because
// of I/O errors then idle until the condition is cleared.
@@ -4277,6 +4262,7 @@
while (dbb->dbb_flags & DBB_suspend_bgio)
{
+ Attachment::Checkout cout(jAtt->getHandle());
dbb->dbb_gc_sem.tryEnter(10);
if (!(dbb->dbb_flags & DBB_garbage_collector))
@@ -4296,108 +4282,88 @@
// Express interest in the relation to prevent it from being deleted
// out from under us while garbage collection is in-progress.
- vec<jrd_rel*>* vector = tdbb->getAttachment()->att_relations;
-
- for (ULONG id = 0; vector && id < vector->count(); ++id)
+ USHORT relID;
+ PageBitmap* gc_bitmap = NULL;
+ if (gc->getPageBitmap(dbb->dbb_oldest_snapshot, relID, &gc_bitmap))
{
- relation = (*vector)[id];
+ relation = MET_lookup_relation_id(tdbb, relID, false);
+ if (!relation || (relation->rel_flags & (REL_deleted | REL_deleting)))
+ {
+ delete gc_bitmap;
+ gc_bitmap = NULL;
+ gc->removeRelation(relID);
+ }
//jrd_rel::RelPagesSnapshot pagesSnapshot(tdbb, relation);
//relation->fillPagesSnapshot(pagesSnapshot);
- RelationGarbage *relGarbage =
- relation ? (RelationGarbage*)relation->rel_garbage : NULL;
-
- if (relation && (relation->rel_gc_bitmap || relGarbage) &&
- !(relation->rel_flags & (REL_deleted | REL_deleting)))
+ if (gc_bitmap)
{
- if (relGarbage) {
- relGarbage->getGarbage(dbb->dbb_oldest_snapshot, &relation->rel_gc_bitmap);
- }
-
++relation->rel_sweep_count;
rpb.rpb_relation = relation;
- if (relation->rel_gc_bitmap)
+ while (gc_bitmap->getFirst())
{
- while (relation->rel_gc_bitmap->getFirst())
- {
- const ULONG dp_sequence = relation->rel_gc_bitmap->current();
+ const ULONG dp_sequence = gc_bitmap->current();
- if (!(dbb->dbb_flags & DBB_garbage_collector)) {
- --relation->rel_sweep_count;
- goto gc_exit;
- }
+ if (!(dbb->dbb_flags & DBB_garbage_collector)) {
+ --relation->rel_sweep_count;
+ goto gc_exit;
+ }
- relation->rel_gc_bitmap->clear(dp_sequence);
+ gc_bitmap->clear(dp_sequence);
- if (!transaction)
- {
- // Start a "precommitted" transaction by using read-only,
- // read committed. Of particular note is the absence of a
- // transaction lock which means the transaction does not
- // inhibit garbage collection by its very existence.
+ if (!transaction)
+ {
+ // Start a "precommitted" transaction by using read-only,
+ // read committed. Of particular note is the absence of a
+ // transaction lock which means the transaction does not
+ // inhibit garbage collection by its very existence.
- transaction = TRA_start(tdbb, sizeof(gc_tpb), gc_tpb);
- tdbb->setTransaction(transaction);
- }
- else
- {
- // Refresh our notion of the oldest transactions for
- // efficient garbage collection. This is very cheap.
+ transaction = TRA_start(tdbb, sizeof(gc_tpb), gc_tpb);
+ tdbb->setTransaction(transaction);
+ }
+ else
+ {
+ // Refresh our notion of the oldest transactions for
+ // efficient garbage collection. This is very cheap.
- transaction->tra_oldest = dbb->dbb_oldest_transaction;
- transaction->tra_oldest_active = dbb->dbb_oldest_snapshot;
- }
+ transaction->tra_oldest = dbb->dbb_oldest_transaction;
+ transaction->tra_oldest_active = dbb->dbb_oldest_snapshot;
+ }
- found = flush = true;
- rpb.rpb_number.setValue(((SINT64) dp_sequence * dbb->dbb_max_reco...
[truncated message content] |