Skip to content

Commit 9afc84b

Browse files
committed
Fixed a number of issues with drop GTT
1 parent b1c563d commit 9afc84b

File tree

10 files changed

+162
-23
lines changed

10 files changed

+162
-23
lines changed

src/dsql/DdlNodes.epp

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11401,13 +11401,6 @@ void DropRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
1140111401
if (dbb->dbb_garbage_collector)
1140211402
dbb->dbb_garbage_collector->removeRelation(rel->getId());
1140311403

11404-
if (relation->isTemporary())
11405-
{
11406-
// release pages, allocated for current GTT instance
11407-
AutoSetRestoreFlag<ULONG> tmpSpace(&tdbb->tdbb_flags, TDBB_use_db_page_space, false);
11408-
relation->delPages(tdbb);
11409-
}
11410-
1141111404
RelationPages* const relPages = relation->getBasePages();
1141211405
if (relPages->rel_pages)
1141311406
DPM_mark_relation(tdbb, relation);

src/jrd/Attachment.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -410,9 +410,6 @@ void Jrd::Attachment::resetSession(thread_db* tdbb, jrd_tra** traHandle)
410410
bool err = false;
411411
for (const jrd_tra* tra = att_transactions; tra; tra = tra->tra_next)
412412
{
413-
if (tra == att_meta_transaction)
414-
continue;
415-
416413
n++;
417414
if (tra != oldTran && !(tra->tra_flags & TRA_prepared))
418415
err = true;
@@ -977,6 +974,9 @@ void Attachment::createMetaTransaction(thread_db* tdbb)
977974
LCK_release(tdbb, att_meta_transaction->tra_lock);
978975
att_meta_transaction->tra_lock = nullptr;
979976
}
977+
978+
att_meta_transaction->unlinkFromAttachment();
979+
att_meta_transaction->tra_flags |= TRA_meta;
980980
}
981981
}
982982

src/jrd/Database.cpp

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -824,7 +824,8 @@ namespace Jrd
824824
dbb_compatibility_index(~0U),
825825
dbb_dic(*p),
826826
dbb_mdc(FB_NEW_POOL(*p) MetadataCache(*p)),
827-
dbb_user_ids(*p)
827+
dbb_user_ids(*p),
828+
dbb_del_pages(*p)
828829
{
829830
dbb_pools.add(p);
830831

@@ -895,5 +896,57 @@ namespace Jrd
895896
return result;
896897
}
897898

899+
void Database::markForDelete(RelationPermanent* relation)
900+
{
901+
MutexLockGuard g(dbb_del_pages_mutex, FB_FUNCTION);
902+
903+
#ifdef DEV_BUILD
904+
FB_SIZE_T dummy;
905+
bool rc = dbb_del_pages.findEx([relation](const DelPagesMarker& item)->int
906+
{
907+
return std::greater{}(item.relation, relation);
908+
},
909+
dummy);
910+
fb_assert(!rc);
911+
#endif
912+
913+
dbb_del_pages.add({dbb_next_transaction, relation});
914+
}
915+
916+
void Database::clearDeleteMark(RelationPermanent* relation)
917+
{
918+
MutexLockGuard g(dbb_del_pages_mutex, FB_FUNCTION);
919+
920+
FB_SIZE_T pos;
921+
bool found = dbb_del_pages.findEx([relation](const DelPagesMarker& item)->int
922+
{
923+
return std::greater{}(item.relation, relation);
924+
},
925+
pos);
926+
fb_assert(found);
927+
928+
if (found)
929+
dbb_del_pages.remove(pos);
930+
}
931+
932+
void Database::deleteTempPages(thread_db* tdbb, TraNumber oldestActive)
933+
{
934+
// check for data presence is safe even w/o mutex locked
935+
// normally there is no data in array
936+
if (!dbb_del_pages.hasData())
937+
return;
938+
939+
MutexLockGuard g(dbb_del_pages_mutex, FB_FUNCTION);
940+
while (dbb_del_pages.hasData() && dbb_del_pages[0].tran < oldestActive)
941+
{
942+
auto* relation = dbb_del_pages[0].relation;
943+
dbb_del_pages.remove(0u);
944+
945+
MutexUnlockGuard checkout(dbb_del_pages_mutex, FB_FUNCTION);
946+
printf("deleteTempPages for relation %s\n", relation->getName().toQuotedString().c_str());
947+
relation->freePages(tdbb);
948+
}
949+
}
950+
898951

899952
} // namespace

src/jrd/Database.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ class CryptoManager;
9696
class KeywordsMap;
9797
class MetadataCache;
9898
class ExtEngineManager;
99+
class RelationPermanent;
99100

100101
// Flags to indicate normal internal requests vs. dyn internal requests
101102
// IRQ_REQUESTS & DYN_REQUESTS are depecated
@@ -292,6 +293,17 @@ class Database : public pool_alloc<type_dbb>
292293
bool active;
293294
};
294295

296+
struct DelPagesMarker
297+
{
298+
TraNumber tran;
299+
RelationPermanent* relation;
300+
301+
static TraNumber generate(const DelPagesMarker& item)
302+
{
303+
return item.tran;
304+
}
305+
};
306+
295307
static Database* create(Firebird::IPluginConfig* pConf, bool shared)
296308
{
297309
Firebird::MemoryStats temp_stats;
@@ -459,6 +471,10 @@ class Database : public pool_alloc<type_dbb>
459471
Firebird::GenericMap<Firebird::Pair<Firebird::Left<
460472
Firebird::MetaString, UserId*> > > dbb_user_ids; // set of used UserIds
461473

474+
Firebird::SortedArray<DelPagesMarker, Firebird::EmptyStorage<DelPagesMarker>,
475+
TraNumber, DelPagesMarker> dbb_del_pages;
476+
Firebird::Mutex dbb_del_pages_mutex;
477+
462478
public:
463479
// returns true if primary file is located on raw device
464480
bool onRawDevice() const;
@@ -469,6 +485,11 @@ class Database : public pool_alloc<type_dbb>
469485
// returns the minimum IO block size
470486
ULONG getIOBlockSize() const;
471487

488+
// control temporary pages cleanup
489+
void markForDelete(RelationPermanent* relation);
490+
void clearDeleteMark(RelationPermanent* relation);
491+
void deleteTempPages(thread_db* tdbb, TraNumber oldestActive);
492+
472493
#ifdef DEV_BUILD
473494
// returns true if main lock is in exclusive state
474495
bool locked() const

src/jrd/Relation.cpp

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ RelationPages* RelationPermanent::getPagesInternal(thread_db* tdbb, TraNumber tr
293293
else
294294
inst_id = PAG_attachment_id(tdbb);
295295

296-
MutexLockGuard relPerm(rel_pages_mutex, FB_FUNCTION);
296+
MutexLockGuard g(rel_pages_mutex, FB_FUNCTION);
297297

298298
if (!rel_pages_inst)
299299
rel_pages_inst = FB_NEW_POOL(getPool()) RelationPagesInstances(getPool());
@@ -409,31 +409,59 @@ bool RelationPermanent::delPages(thread_db* tdbb, TraNumber tran, RelationPages*
409409
pages);
410410
#endif
411411

412-
FB_SIZE_T pos;
412+
{ // mutex scope
413+
MutexLockGuard g(rel_pages_mutex, FB_FUNCTION);
414+
415+
FB_SIZE_T pos;
413416
#ifdef DEV_BUILD
414-
const bool found =
417+
const bool found =
415418
#endif
416-
rel_pages_inst->find(pages->rel_instance_id, pos);
417-
fb_assert(found && ((*rel_pages_inst)[pos] == pages) );
419+
rel_pages_inst->find(pages->rel_instance_id, pos);
420+
fb_assert(found && ((*rel_pages_inst)[pos] == pages) );
418421

419-
rel_pages_inst->remove(pos);
422+
rel_pages_inst->remove(pos);
423+
}
420424

421425
if (pages->rel_index_root)
422426
IDX_delete_indices(tdbb, this, pages, false);
423427

424428
if (pages->rel_pages)
425429
DPM_delete_relation_pages(tdbb, this, pages);
426430

431+
MutexLockGuard g(rel_pages_mutex, FB_FUNCTION);
432+
427433
pages->free(rel_pages_free);
428434
return true;
429435
}
430436

437+
void RelationPermanent::freePages(thread_db* tdbb)
438+
{
439+
if (!rel_pages_inst)
440+
return;
441+
442+
// no need in rel_pages_mutex - it's cleanup after DROP TABLE
443+
while (rel_pages_inst->hasData())
444+
{
445+
auto* pages = rel_pages_inst->pop();
446+
447+
if (pages->rel_index_root)
448+
IDX_delete_indices(tdbb, this, pages, false);
449+
450+
if (pages->rel_pages)
451+
DPM_delete_relation_pages(tdbb, this, pages);
452+
453+
pages->free(rel_pages_free);
454+
}
455+
}
456+
431457
void RelationPermanent::retainPages(thread_db* tdbb, TraNumber oldNumber, TraNumber newNumber)
432458
{
433459
fb_assert(rel_flags & REL_temp_tran);
434460
fb_assert(oldNumber != 0);
435461
fb_assert(newNumber != 0);
436462

463+
MutexLockGuard g(rel_pages_mutex, FB_FUNCTION);
464+
437465
if (!rel_pages_inst)
438466
return;
439467

@@ -450,6 +478,24 @@ void RelationPermanent::retainPages(thread_db* tdbb, TraNumber oldNumber, TraNum
450478
rel_pages_inst->add(pages);
451479
}
452480

481+
void RelationPermanent::dropTempPages(thread_db* tdbb)
482+
{
483+
if (rel_flags & REL_temp_gtt)
484+
{
485+
Database* dbb = tdbb->getDatabase();
486+
dbb->markForDelete(this);
487+
}
488+
}
489+
490+
void RelationPermanent::clearDropMarker(thread_db* tdbb)
491+
{
492+
if (rel_flags & REL_temp_gtt)
493+
{
494+
Database* dbb = tdbb->getDatabase();
495+
dbb->clearDeleteMark(this);
496+
}
497+
}
498+
453499
void RelationPermanent::getRelLockKey(thread_db* tdbb, UCHAR* key)
454500
{
455501
const ULONG val = getId();
@@ -474,6 +520,8 @@ void RelationPermanent::cleanUp() noexcept
474520

475521
void RelationPermanent::fillPagesSnapshot(RelPagesSnapshot& snapshot, const bool attachmentOnly)
476522
{
523+
MutexLockGuard g(rel_pages_mutex, FB_FUNCTION);
524+
477525
if (rel_pages_inst)
478526
{
479527
for (FB_SIZE_T i = 0; i < rel_pages_inst->getCount(); i++)

src/jrd/Relation.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -898,6 +898,7 @@ class RelationPermanent : public Firebird::PermanentStorage
898898

899899
RelationPages* getPages(thread_db* tdbb, TraNumber tran = MAX_TRA_NUMBER, bool allocPages = true);
900900
bool delPages(thread_db* tdbb, TraNumber tran = MAX_TRA_NUMBER, RelationPages* aPages = NULL);
901+
void freePages(thread_db* tdbb);
901902
void retainPages(thread_db* tdbb, TraNumber oldNumber, TraNumber newNumber);
902903
void cleanUp() noexcept;
903904
void fillPagesSnapshot(RelPagesSnapshot&, const bool AttachmentOnly = false);
@@ -960,6 +961,10 @@ class RelationPermanent : public Firebird::PermanentStorage
960961
// Relation must be updated on next use or commit
961962
static Cached::Relation* newVersion(thread_db* tdbb, const QualifiedName& name);
962963

964+
// Relation is in process of remove - mark it with current transaction
965+
void dropTempPages(thread_db* tdbb);
966+
void clearDropMarker(thread_db* tdbb);
967+
963968
// Lists of FK partners should be updated on next update
964969
void checkPartners(thread_db* tdbb);
965970

@@ -996,7 +1001,7 @@ class RelationPermanent : public Firebird::PermanentStorage
9961001
ForeignRefs* rel_foreign_refs = nullptr; // foreign references to other relations' primary keys
9971002

9981003
private:
999-
Firebird::Mutex rel_pages_mutex;
1004+
Firebird::Mutex rel_pages_mutex; // protects rel_pages_inst and rel_pages_free
10001005

10011006
typedef Firebird::SortedArray<
10021007
RelationPages*,

src/jrd/dfw.epp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3606,6 +3606,7 @@ static bool delete_relation(thread_db* tdbb, SSHORT phase, DeferredWork* work, j
36063606
auto* relation = MetadataCache::getPerm<Cached::Relation>(tdbb, work->dfw_id, CacheFlag::ERASED);
36073607
if (relation)
36083608
{
3609+
relation->clearDropMarker(tdbb);
36093610
if (relation->isDropped())
36103611
relation->rollback(tdbb);
36113612
}
@@ -3652,16 +3653,29 @@ static bool delete_relation(thread_db* tdbb, SSHORT phase, DeferredWork* work, j
36523653

36533654
case 2:
36543655
case 3:
3656+
return true;
3657+
36553658
case 4:
3659+
{
3660+
auto* relation = MetadataCache::getPerm<Cached::Relation>(tdbb, work->dfw_id, CacheFlag::ERASED);
3661+
if (!relation)
3662+
return false;
3663+
3664+
relation->dropTempPages(tdbb);
3665+
}
3666+
return true;
3667+
36563668
case 5:
36573669
case 6:
36583670
return true;
36593671

36603672
case 7:
36613673
{
36623674
auto* relation = MetadataCache::getPerm<Cached::Relation>(tdbb, work->dfw_id, CacheFlag::ERASED);
3663-
if (relation)
3664-
relation->commit(tdbb);
3675+
if (!relation)
3676+
return false;
3677+
3678+
relation->commit(tdbb);
36653679
}
36663680
break;
36673681
}

src/jrd/jrd.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8352,7 +8352,6 @@ void Attachment::purgeTransactions(thread_db* tdbb, const bool force_flag)
83528352
*
83538353
**************************************/
83548354
jrd_tra* const trans_dbk = att_dbkey_trans;
8355-
auto* const trans_meta = att_meta_transaction;
83568355

83578356
if (force_flag)
83588357
{
@@ -8366,7 +8365,7 @@ void Attachment::purgeTransactions(thread_db* tdbb, const bool force_flag)
83668365
for (jrd_tra* transaction = att_transactions; transaction; transaction = next)
83678366
{
83688367
next = transaction->tra_next;
8369-
if (transaction != trans_dbk && transaction != trans_meta)
8368+
if (transaction != trans_dbk)
83708369
{
83718370
if (transaction->tra_flags & TRA_prepared)
83728371
{

src/jrd/tra.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2391,6 +2391,9 @@ static int limbo_transaction(thread_db* tdbb, TraNumber id)
23912391

23922392
void jrd_tra::unlinkFromAttachment()
23932393
{
2394+
if (tra_flags & TRA_meta)
2395+
return; // Unlinked on creation
2396+
23942397
for (jrd_tra** ptr = &tra_attachment->att_transactions; *ptr; ptr = &(*ptr)->tra_next)
23952398
{
23962399
if (*ptr == this)
@@ -3771,9 +3774,11 @@ static void transaction_start(thread_db* tdbb, jrd_tra* trans)
37713774
dbb->dbb_oldest_transaction, dbb->dbb_oldest_snapshot);
37723775

37733776
// Plumb remove really old objects from metadata cache
3774-
37753777
dbb->dbb_mdc->checkCleanup(tdbb, oldest);
37763778

3779+
// Also remove really old temporary pages of dropped relations
3780+
dbb->deleteTempPages(tdbb, trans->tra_oldest_active);
3781+
37773782
// If the transaction block is getting out of hand, force a sweep
37783783

37793784
if (dbb->dbb_sweep_interval &&

src/jrd/tra.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,7 @@ inline constexpr ULONG TRA_replicating = 0x100000L; // transaction is allowed
449449
inline constexpr ULONG TRA_no_blob_check = 0x200000L; // disable blob access checking
450450
inline constexpr ULONG TRA_auto_release_temp_blobid = 0x400000L;// remove temp ids of materialized user blobs from tra_blobs
451451
inline constexpr ULONG TRA_deps_to_disk = 0x800000L; // store dependencies to RDB$DEPENDENCIES
452+
inline constexpr ULONG TRA_meta = 0x1000000L; // transaction is used to load metadata
452453

453454
// flags derived from TPB, see also transaction_options() at tra.cpp
454455
inline constexpr ULONG TRA_OPTIONS_MASK = (TRA_degree3 | TRA_readonly | TRA_ignore_limbo | TRA_read_committed |

0 commit comments

Comments
 (0)