Skip to content

Commit 4018f3f

Browse files
committed
Ensure safe MT access to relation's formats
1 parent 032b41d commit 4018f3f

File tree

5 files changed

+30
-22
lines changed

5 files changed

+30
-22
lines changed

src/dsql/DdlNodes.epp

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8835,12 +8835,11 @@ Format* RelationNode::makeFormat(thread_db* tdbb, jrd_tra* transaction, Cached::
88358835
{
88368836
// Find and return the format matching new number of fields
88378837

8838-
fb_assert(relation->rel_formats.hasData());
8839-
8840-
auto formats = relation->rel_formats.readAccessor();
8838+
auto formats = relation->getFormats();
8839+
fb_assert(formats->getCount());
88418840
for (const auto format : *(formats.getPointer()))
88428841
{
8843-
if (format->fmt_count == count + 1)
8842+
if (format && (format->fmt_count == count + 1))
88448843
{
88458844
if (version)
88468845
*version = format->fmt_version;
@@ -8935,12 +8934,7 @@ Format* RelationNode::makeFormat(thread_db* tdbb, jrd_tra* transaction, Cached::
89358934
}
89368935

89378936
// Link the format block into the world
8938-
{
8939-
MutexLockGuard g(relation->rel_formats_grow, FB_FUNCTION);
8940-
8941-
relation->rel_formats.grow(format->fmt_version + 1, true);
8942-
relation->rel_formats.writeAccessor()->value(format->fmt_version) = format;
8943-
}
8937+
relation->addFormat(format);
89448938

89458939
// Store format in system relation
89468940

src/jrd/Relation.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,14 @@ Lock* RelationPermanent::createLock(thread_db* tdbb, MemoryPool& pool, lck_t lck
687687
return lock;
688688
}
689689

690+
void RelationPermanent::addFormat(Format* fmt)
691+
{
692+
MutexLockGuard g(rel_formats_grow, FB_FUNCTION);
693+
694+
rel_formats.grow(fmt->fmt_version + 1, true);
695+
rel_formats.writeAccessor()->value(fmt->fmt_version) = fmt;
696+
}
697+
690698

691699
void GCLock::blockingAst()
692700
{

src/jrd/Relation.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -882,8 +882,20 @@ class RelationPermanent : public Firebird::PermanentStorage
882882
// ... will be removed
883883
void removeDepends(thread_db* tdbb);
884884

885+
typedef SharedReadVector<Format*, 16> Formats;
886+
887+
private:
885888
SharedReadVector<Format*, 16> rel_formats; // Known record formats
886889
Firebird::Mutex rel_formats_grow; // Mutex to grow rel_formats
890+
891+
public:
892+
HazardPtr<Formats::Generation> getFormats()
893+
{
894+
return rel_formats.readAccessor();
895+
}
896+
897+
void addFormat(Format* fmt);
898+
887899
Indices rel_indices; // Active indices
888900
QualifiedName rel_name; // ascii relation name
889901
MetaId rel_id;

src/jrd/ini.epp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,8 @@ namespace
8585
unsigned getLatestFormat(thread_db* tdbb, int relId, int maxFieldId)
8686
{
8787
auto* const relation = MetadataCache::lookupRelation(tdbb, relId, CacheFlag::AUTOCREATE | CacheFlag::NOSCAN);
88-
fb_assert(relation && relation->rel_formats.hasData());
89-
auto formats = relation->rel_formats.readAccessor();
88+
fb_assert(relation);
89+
auto formats = relation->getFormats();
9090

9191
const auto formatNumber = formats->getCount() - 1;
9292
fb_assert(formatNumber < MAX_TABLE_VERSIONS);
@@ -1043,9 +1043,7 @@ void INI_init(thread_db* tdbb)
10431043
format->fmt_version = formatNumber;
10441044
format->fmt_length = FLAG_BYTES(format->fmt_count);
10451045

1046-
// no need in any locking inside ini.epp - we have exclusive access
1047-
relation->rel_formats.grow(format->fmt_version + 1, true);
1048-
relation->rel_formats.writeAccessor()->value(format->fmt_version) = format;
1046+
relation->addFormat(format);
10491047

10501048
auto desc = format->fmt_desc.begin();
10511049

@@ -1089,7 +1087,7 @@ void INI_init(thread_db* tdbb)
10891087
formatNumber++;
10901088
}
10911089

1092-
const auto* formats = relation->rel_formats.writeAccessor();
1090+
const auto formats = relation->getFormats();
10931091
fb_assert(currentFormat < formats->getCount());
10941092
relVers->rel_current_fmt = currentFormat;
10951093
relVers->rel_current_format = formats->value(currentFormat);

src/jrd/met.epp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -916,7 +916,7 @@ Format* MET_format(thread_db* tdbb, RelationPermanent* relation, USHORT number)
916916
Database* dbb = tdbb->getDatabase();
917917

918918
Format* format;
919-
auto formats = relation->rel_formats.readAccessor();
919+
auto formats = relation->getFormats();
920920
if ((number < formats->getCount()) && (format = formats->value(number)))
921921
{
922922
return format;
@@ -987,11 +987,7 @@ Format* MET_format(thread_db* tdbb, RelationPermanent* relation, USHORT number)
987987
format->fmt_version = number;
988988

989989
// Link the format block into the world
990-
991-
MutexLockGuard g(relation->rel_formats_grow, FB_FUNCTION);
992-
993-
relation->rel_formats.grow(number + 1, true);
994-
relation->rel_formats.writeAccessor()->value(number) = format;
990+
relation->addFormat(format);
995991

996992
return format;
997993
}

0 commit comments

Comments
 (0)