From aba34753cbc82f1f574cf82238aea80de4fec097 Mon Sep 17 00:00:00 2001 From: hvlad Date: Tue, 9 Nov 2004 12:59:37 +0000 Subject: [PATCH] Add config file parameter for the garbage collection policy --- src/common/config/config.cpp | 17 +++++++++++- src/common/config/config.h | 13 ++++++++- src/jrd/jrd.cpp | 28 +++++++++++++++++++ src/jrd/jrd.h | 6 ++-- src/jrd/tra.cpp | 8 ++++-- src/jrd/vio.cpp | 54 ++++++++++++++++++++---------------- 6 files changed, 93 insertions(+), 33 deletions(-) diff --git a/src/common/config/config.cpp b/src/common/config/config.cpp index ce958cdac5..226ff6e7fc 100644 --- a/src/common/config/config.cpp +++ b/src/common/config/config.cpp @@ -40,6 +40,15 @@ typedef Firebird::PathName string; * Configuration entries */ +const char* GCPolicyCooperative = "cooperative"; +const char* GCPolicyBackground = "background"; +const char* GCPolicyCombined = "combined"; +#ifdef SUPERSERVER +const char* GCPolicyDefault = GCPolicyCombined; +#else +const char* GCPolicyDefault = GCPolicyCooperative; +#endif + const ConfigImpl::ConfigEntry ConfigImpl::entries[] = { {TYPE_STRING, "RootDirectory", (ConfigValue) 0}, @@ -114,7 +123,8 @@ const ConfigImpl::ConfigEntry ConfigImpl::entries[] = {TYPE_BOOLEAN, "BugcheckAbort", (ConfigValue) false}, // whether to abort() engine when internal error is found #endif {TYPE_INTEGER, "TraceDSQL", (ConfigValue) 0}, // bitmask - {TYPE_BOOLEAN, "LegacyHash", (ConfigValue) false} // let use old passwd hash verification + {TYPE_BOOLEAN, "LegacyHash", (ConfigValue) false}, // let use old passwd hash verification + {TYPE_STRING, "GCPolicy", (ConfigValue) GCPolicyDefault} // garbage collection policy }; /****************************************************************************** @@ -488,3 +498,8 @@ bool Config::getLegacyHash() { return (bool) sysConfig.values[KEY_LEGACY_HASH]; } + +const char *Config::getGCPolicy() +{ + return (const char *) sysConfig.values[KEY_GC_POLICY]; +} diff --git a/src/common/config/config.h b/src/common/config/config.h index e0e3c19cb4..740317ea8b 100644 --- a/src/common/config/config.h +++ b/src/common/config/config.h @@ -58,6 +58,11 @@ in config.cpp module. **/ +extern const char* GCPolicyCooperative; +extern const char* GCPolicyBackground; +extern const char* GCPolicyCombined; +extern const char* GCPolicyDefault; + class Config { enum ConfigKey @@ -106,7 +111,8 @@ class Config KEY_TEMP_DIRECTORIES, // 40 KEY_BUGCHECK_ABORT, // 41 KEY_TRACE_DSQL, // 42 - KEY_LEGACY_HASH // 43 + KEY_LEGACY_HASH, // 43 + KEY_GC_POLICY // 44 }; public: @@ -330,6 +336,11 @@ public: Let use of des hash to verify passwords */ static bool getLegacyHash(); + + /* + GC policy + */ + static const char *getGCPolicy(); }; namespace Firebird { diff --git a/src/jrd/jrd.cpp b/src/jrd/jrd.cpp index a18b77f539..efd9d21a2a 100644 --- a/src/jrd/jrd.cpp +++ b/src/jrd/jrd.cpp @@ -5490,6 +5490,34 @@ static Database* init(thread_db* tdbb, dbb->dbb_flags |= DBB_exclusive; dbb->dbb_sweep_interval = SWEEP_INTERVAL; +/* set a garbage collection policy */ + + if ((dbb->dbb_flags & (DBB_gc_cooperative | DBB_gc_background)) == 0) + { + const char* gc_policy = Config::getGCPolicy(); + if (stricmp(gc_policy, GCPolicyCooperative) == 0) { + dbb->dbb_flags |= DBB_gc_cooperative; + } + else if (stricmp(gc_policy, GCPolicyBackground) == 0) { + dbb->dbb_flags |= DBB_gc_background; + } + else if (stricmp(gc_policy, GCPolicyCombined) == 0) { + dbb->dbb_flags |= DBB_gc_cooperative | DBB_gc_background; + } + else // config value is invalid, use default + if (stricmp(GCPolicyDefault, GCPolicyCooperative) == 0) { + dbb->dbb_flags |= DBB_gc_cooperative; + } + else if (stricmp(GCPolicyDefault, GCPolicyBackground) == 0) { + dbb->dbb_flags |= DBB_gc_background; + } + else if (stricmp(GCPolicyDefault, GCPolicyCombined) == 0) { + dbb->dbb_flags |= DBB_gc_cooperative | DBB_gc_background; + } + else + fb_assert(false); + }; + /* Initialize a number of subsystems */ TRA_init(tdbb); diff --git a/src/jrd/jrd.h b/src/jrd/jrd.h index 4facceecbe..b7c8d2eb65 100644 --- a/src/jrd/jrd.h +++ b/src/jrd/jrd.h @@ -335,7 +335,8 @@ const ULONG DBB_security_db = 0x80000L; /* ISC security database */ const ULONG DBB_sweep_thread_started = 0x100000L; /* A database sweep thread has been started */ const ULONG DBB_suspend_bgio = 0x200000L; /* Suspend I/O by background threads */ const ULONG DBB_being_opened = 0x400000L; /* database is being attached to */ - +const ULONG DBB_gc_cooperative = 0x0800000L; /* cooperative garbage collection */ +const ULONG DBB_gc_background = 0x1000000L; /* background garbage collection by gc_thread */ // // dbb_ast_flags // @@ -633,9 +634,6 @@ typedef Firebird::ObjectsArray trig_vec; #ifdef GARBAGE_THREAD -#define GC_NOTIFY_ON_WRITE -//#define GC_NOTIFY_ON_READ - class RelationGarbage { private: diff --git a/src/jrd/tra.cpp b/src/jrd/tra.cpp index 09e803e988..ec9c86135f 100644 --- a/src/jrd/tra.cpp +++ b/src/jrd/tra.cpp @@ -95,7 +95,7 @@ const int DEFAULT_LOCK_TIMEOUT = -1; // infinite using namespace Jrd; using namespace Ods; -#if defined(GARBAGE_THREAD) && defined(GC_NOTIFY_ON_WRITE) +#ifdef GARBAGE_THREAD #include "../jrd/isc_s_proto.h" #endif @@ -1662,8 +1662,10 @@ jrd_tra* TRA_start(thread_db* tdbb, int tpb_length, const SCHAR* tpb) if (trans->tra_oldest_active > dbb->dbb_oldest_snapshot) { dbb->dbb_oldest_snapshot = trans->tra_oldest_active; -#if defined(GARBAGE_THREAD) && defined(GC_NOTIFY_ON_WRITE) - if (!(dbb->dbb_flags & DBB_gc_active)) { +#if defined(GARBAGE_THREAD) + if (!(dbb->dbb_flags & DBB_gc_active) && + (dbb->dbb_flags & DBB_gc_background) ) + { dbb->dbb_flags |= DBB_gc_pending; ISC_event_post(dbb->dbb_gc_event); } diff --git a/src/jrd/vio.cpp b/src/jrd/vio.cpp index 0febf48b56..26d44fe0cf 100644 --- a/src/jrd/vio.cpp +++ b/src/jrd/vio.cpp @@ -496,6 +496,9 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb, RecordSource* **************************************/ SET_TDBB(tdbb); + const bool gcPolicyCooperative = tdbb->tdbb_database->dbb_flags & DBB_gc_cooperative; + const bool gcPolicyBackground = tdbb->tdbb_database->dbb_flags & DBB_gc_background; + #ifdef VIO_DEBUG if (debug_flag > DEBUG_TRACE_ALL) { printf @@ -547,8 +550,8 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb, RecordSource* (rpb->rpb_b_page == 0 || rpb->rpb_transaction_nr >= transaction->tra_oldest_active)) { -#if defined(GARBAGE_THREAD) && defined(GC_NOTIFY_ON_WRITE) - if (rpb->rpb_b_page) +#ifdef GARBAGE_THREAD + if (gcPolicyBackground && rpb->rpb_b_page) notify_garbage_collector(tdbb, rpb); #endif // GARBAGE_THREAD @@ -877,8 +880,8 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb, RecordSource* if (rpb->rpb_transaction_nr < transaction->tra_oldest_active && !(attachment->att_flags & ATT_no_cleanup)) { -#if defined(GARBAGE_THREAD) && defined(GC_NOTIFY_ON_READ) - if (attachment->att_flags & ATT_notify_gc) { +#ifdef GARBAGE_THREAD + if (!gcPolicyCooperative && (attachment->att_flags & ATT_notify_gc)) { notify_garbage_collector(tdbb, rpb); CCH_RELEASE(tdbb, &rpb->rpb_window); } @@ -900,15 +903,16 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb, RecordSource* might interfere with the updater (prepare_update, update_in_place...). That might be the reason for the rpb_chained check. */ - bool cannotGC = + const bool cannotGC = rpb->rpb_transaction_nr >= transaction->tra_oldest_active || rpb->rpb_b_page == 0 || rpb->rpb_flags & rpb_chained || attachment->att_flags & ATT_no_cleanup; if (cannotGC) { -#if defined(GARBAGE_THREAD) && defined(GC_NOTIFY_ON_WRITE) - if (attachment->att_flags & (ATT_notify_gc | ATT_garbage_collector) && +#ifdef GARBAGE_THREAD + if (gcPolicyBackground && + attachment->att_flags & (ATT_notify_gc | ATT_garbage_collector) && (rpb->rpb_b_page != 0 && !(rpb->rpb_flags & rpb_chained)) ) { // VIO_chase_record_version @@ -920,8 +924,8 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb, RecordSource* /* Garbage collect. */ -#if defined(GARBAGE_THREAD) && defined(GC_NOTIFY_ON_READ) - if (attachment->att_flags & ATT_notify_gc) { +#ifdef GARBAGE_THREAD + if (!gcPolicyCooperative && (attachment->att_flags & ATT_notify_gc)) { notify_garbage_collector(tdbb, rpb); return true; } @@ -1508,9 +1512,10 @@ void VIO_erase(thread_db* tdbb, record_param* rpb, jrd_tra* transaction) transaction->tra_flags |= TRA_perform_autocommit; } -#if defined(GARBAGE_THREAD) && defined(GC_NOTIFY_ON_WRITE) +#ifdef GARBAGE_THREAD // VIO_erase - notify_garbage_collector(tdbb, rpb, transaction->tra_number); + if (tdbb->tdbb_database->dbb_flags | DBB_gc_background) + notify_garbage_collector(tdbb, rpb, transaction->tra_number); #endif } @@ -2057,7 +2062,8 @@ void VIO_init(thread_db* tdbb) Database* dbb = tdbb->tdbb_database; Attachment* attachment = tdbb->tdbb_attachment; - if (dbb->dbb_flags & DBB_read_only) { + if ((dbb->dbb_flags & DBB_read_only) || + !(dbb->dbb_flags & DBB_gc_background) ) { return; } @@ -2378,9 +2384,10 @@ void VIO_modify(thread_db* tdbb, record_param* org_rpb, record_param* new_rpb, transaction->tra_flags |= TRA_perform_autocommit; } -#if defined(GARBAGE_THREAD) && defined(GC_NOTIFY_ON_WRITE) +#ifdef GARBAGE_THREAD // VIO_modify - notify_garbage_collector(tdbb, org_rpb, transaction->tra_number); + if (tdbb->tdbb_database->dbb_flags | DBB_gc_background) + notify_garbage_collector(tdbb, org_rpb, transaction->tra_number); #endif } @@ -3494,9 +3501,10 @@ static void expunge(thread_db* tdbb, record_param* rpb, /* Re-fetch the record */ if (!DPM_get(tdbb, rpb, LCK_write)) { -#if defined(GARBAGE_THREAD) && defined(GC_NOTIFY_ON_WRITE) +#ifdef GARBAGE_THREAD // expunge - notify_garbage_collector(tdbb, rpb); + if (tdbb->tdbb_database->dbb_flags | DBB_gc_background) + notify_garbage_collector(tdbb, rpb); #endif return; } @@ -3517,9 +3525,10 @@ static void expunge(thread_db* tdbb, record_param* rpb, rpb->rpb_transaction_nr >= transaction->tra_oldest_active) { -#if defined(GARBAGE_THREAD) && defined(GC_NOTIFY_ON_WRITE) +#ifdef GARBAGE_THREAD // expunge - notify_garbage_collector(tdbb, rpb); + if (tdbb->tdbb_database->dbb_flags | DBB_gc_background) + notify_garbage_collector(tdbb, rpb); #endif CCH_RELEASE(tdbb, &rpb->rpb_window); @@ -4120,9 +4129,6 @@ static void notify_garbage_collector(thread_db* tdbb, record_param* rpb, SLONG t ContextPoolHolder context(tdbb, dbb->dbb_permanent); const SLONG dp_sequence = rpb->rpb_number.getValue() / dbb->dbb_max_records; -#if !defined(GC_NOTIFY_ON_WRITE) - PBM_SET(tdbb->getDefaultPool(), &relation->rel_gc_bitmap, dp_sequence); -#else if (!relation->rel_garbage) { relation->rel_garbage = FB_NEW(*tdbb->getDefaultPool()) RelationGarbage(*tdbb->getDefaultPool()); @@ -4132,7 +4138,6 @@ static void notify_garbage_collector(thread_db* tdbb, record_param* rpb, SLONG t if (tranid > relation->rel_garbage->minTranID()) tranid = relation->rel_garbage->minTranID(); -#endif // GC_NOTIFY_ON_WRITE /* If the garbage collector isn't active then poke the event on which it sleeps to awaken it. */ @@ -4574,9 +4579,10 @@ static void purge(thread_db* tdbb, record_param* rpb) if (!DPM_get(tdbb, rpb, LCK_write)) { gc_rec->rec_flags &= ~REC_gc_active; -#if defined(GARBAGE_THREAD) && defined(GC_NOTIFY_ON_WRITE) +#ifdef GARBAGE_THREAD // purge - notify_garbage_collector(tdbb, rpb); + if (tdbb->tdbb_database->dbb_flags | DBB_gc_background) + notify_garbage_collector(tdbb, rpb); #endif return; //false; }