Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitb4a607c

Browse files
committed
Modify RelationFlushRelation so that if the relcache entry
has positive refcount, it is rebuilt from pg_class data. This ensuresthat relcache entries will track changes made by other backends. Formerly,a shared inval report would just be ignored if it happened to arrive whilethe relcache entry was in use. Also, fix relcache to reset ref countsto zero during transaction abort. Finally, change LockRelation() so thatit checks for shared inval reports after obtaining the lock. In this way,once any kind of lock has been obtained on a rel, we can trust the relcacheentry to be up-to-date.
1 parent8add6d7 commitb4a607c

File tree

4 files changed

+135
-53
lines changed

4 files changed

+135
-53
lines changed

‎src/backend/access/transam/xact.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.47 1999/08/08 20:12:52 tgl Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.48 1999/09/04 18:42:15 tgl Exp $
1111
*
1212
* NOTES
1313
*Transaction aborts can now occur two ways:
@@ -755,6 +755,7 @@ static void
755755
AtAbort_Cache()
756756
{
757757
RegisterInvalid(false);
758+
RelationCacheAbort();
758759
}
759760

760761
/* --------------------------------

‎src/backend/storage/lmgr/lmgr.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lmgr.c,v 1.33 1999/07/17 20:17:46 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lmgr.c,v 1.34 1999/09/04 18:42:14 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -22,6 +22,7 @@
2222
#include"postgres.h"
2323
#include"access/transam.h"
2424
#include"catalog/catalog.h"
25+
#include"utils/inval.h"
2526

2627
externOidMyDatabaseId;
2728

@@ -161,7 +162,16 @@ LockRelation(Relation relation, LOCKMODE lockmode)
161162
tag.objId.blkno=InvalidBlockNumber;
162163

163164
LockAcquire(LockTableId,&tag,lockmode);
164-
return;
165+
166+
/*
167+
* Check to see if the relcache entry has been invalidated
168+
* while we were waiting to lock it. If so, rebuild it,
169+
* or elog() trying. Increment the refcount to ensure that
170+
* RelationFlushRelation will rebuild it and not just delete it.
171+
*/
172+
RelationIncrementReferenceCount(relation);
173+
DiscardInvalid();
174+
RelationDecrementReferenceCount(relation);
165175
}
166176

167177
/*

‎src/backend/utils/cache/relcache.c

Lines changed: 118 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.68 1999/09/02 02:57:50 tgl Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.69 1999/09/04 18:42:13 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -61,6 +61,8 @@
6161
staticvoidRelationFlushRelation(Relation*relationPtr,
6262
boolonlyFlushReferenceCountZero);
6363
staticRelationRelationNameCacheGetRelation(char*relationName);
64+
staticvoidRelationCacheAbortWalker(Relation*relationPtr,
65+
intdummy);
6466
staticvoidinit_irels(void);
6567
staticvoidwrite_irels(void);
6668

@@ -213,14 +215,16 @@ static void RelationFlushIndexes(Relation *r, Oid accessMethodId);
213215
staticHeapTupleScanPgRelation(RelationBuildDescInfobuildinfo);
214216
staticHeapTuplescan_pg_rel_seq(RelationBuildDescInfobuildinfo);
215217
staticHeapTuplescan_pg_rel_ind(RelationBuildDescInfobuildinfo);
216-
staticRelationAllocateRelationDesc(u_intnatts,Form_pg_classrelp);
218+
staticRelationAllocateRelationDesc(Relationrelation,u_intnatts,
219+
Form_pg_classrelp);
217220
staticvoidRelationBuildTupleDesc(RelationBuildDescInfobuildinfo,
218221
Relationrelation,u_intnatts);
219222
staticvoidbuild_tupdesc_seq(RelationBuildDescInfobuildinfo,
220223
Relationrelation,u_intnatts);
221224
staticvoidbuild_tupdesc_ind(RelationBuildDescInfobuildinfo,
222225
Relationrelation,u_intnatts);
223-
staticRelationRelationBuildDesc(RelationBuildDescInfobuildinfo);
226+
staticRelationRelationBuildDesc(RelationBuildDescInfobuildinfo,
227+
Relationoldrelation);
224228
staticvoidIndexedAccessMethodInitialize(Relationrelation);
225229
staticvoidAttrDefaultFetch(Relationrelation);
226230
staticvoidRelCheckFetch(Relationrelation);
@@ -405,12 +409,16 @@ scan_pg_rel_ind(RelationBuildDescInfo buildinfo)
405409
*
406410
*This is used to allocate memory for a new relation descriptor
407411
*and initialize the rd_rel field.
412+
*
413+
*If 'relation' is NULL, allocate a new RelationData object.
414+
*If not, reuse the given object (that path is taken only when
415+
*we have to rebuild a relcache entry during RelationFlushRelation).
408416
* ----------------
409417
*/
410418
staticRelation
411-
AllocateRelationDesc(u_intnatts,Form_pg_classrelp)
419+
AllocateRelationDesc(Relationrelation,u_intnatts,
420+
Form_pg_classrelp)
412421
{
413-
Relationrelation;
414422
Sizelen;
415423
Form_pg_classrelationForm;
416424

@@ -424,18 +432,22 @@ AllocateRelationDesc(u_int natts, Form_pg_class relp)
424432
memmove((char*)relationForm, (char*)relp,CLASS_TUPLE_SIZE);
425433

426434
/* ----------------
427-
*allocate space for new relation descriptor
435+
*allocate space for new relation descriptor, if needed
428436
*/
429-
len=sizeof(RelationData)+10;/* + 10 is voodoo XXX mao */
437+
len=sizeof(RelationData);
430438

431-
relation= (Relation)palloc(len);
439+
if (relation==NULL)
440+
relation= (Relation)palloc(len);
432441

433442
/* ----------------
434443
*clear new reldesc
435444
* ----------------
436445
*/
437446
MemSet((char*)relation,0,len);
438447

448+
/* make sure relation is marked as having no open file yet */
449+
relation->rd_fd=-1;
450+
439451
/* initialize attribute tuple form */
440452
relation->rd_att=CreateTemplateTupleDesc(natts);
441453

@@ -737,6 +749,11 @@ RelationBuildRuleLock(Relation relation)
737749
/* --------------------------------
738750
*RelationBuildDesc
739751
*
752+
*Build a relation descriptor --- either a new one, or by
753+
*recycling the given old relation object. The latter case
754+
*supports rebuilding a relcache entry without invalidating
755+
*pointers to it.
756+
*
740757
*To build a relation descriptor, we have to allocate space,
741758
*open the underlying unix file and initialize the following
742759
*fields:
@@ -758,7 +775,8 @@ RelationBuildRuleLock(Relation relation)
758775
* --------------------------------
759776
*/
760777
staticRelation
761-
RelationBuildDesc(RelationBuildDescInfobuildinfo)
778+
RelationBuildDesc(RelationBuildDescInfobuildinfo,
779+
Relationoldrelation)
762780
{
763781
Filefd;
764782
Relationrelation;
@@ -803,7 +821,7 @@ RelationBuildDesc(RelationBuildDescInfo buildinfo)
803821
*initialize relation->rd_rel and get the access method id.
804822
* ----------------
805823
*/
806-
relation=AllocateRelationDesc(natts,relp);
824+
relation=AllocateRelationDesc(oldrelation,natts,relp);
807825
relam=relation->rd_rel->relam;
808826

809827
/* ----------------
@@ -833,9 +851,6 @@ RelationBuildDesc(RelationBuildDescInfo buildinfo)
833851

834852
/* ----------------
835853
*initialize the tuple descriptor (relation->rd_att).
836-
*remember, rd_att is an array of attribute pointers that lives
837-
*off the end of the relation descriptor structure so space was
838-
*already allocated for it by AllocateRelationDesc.
839854
* ----------------
840855
*/
841856
RelationBuildTupleDesc(buildinfo,relation,natts);
@@ -1153,7 +1168,7 @@ RelationIdGetRelation(Oid relationId)
11531168
buildinfo.infotype=INFO_RELID;
11541169
buildinfo.i.info_id=relationId;
11551170

1156-
rd=RelationBuildDesc(buildinfo);
1171+
rd=RelationBuildDesc(buildinfo,NULL);
11571172
returnrd;
11581173
}
11591174

@@ -1193,7 +1208,7 @@ RelationNameGetRelation(char *relationName)
11931208
buildinfo.infotype=INFO_RELNAME;
11941209
buildinfo.i.info_name=relationName;
11951210

1196-
rd=RelationBuildDesc(buildinfo);
1211+
rd=RelationBuildDesc(buildinfo,NULL);
11971212
returnrd;
11981213
}
11991214

@@ -1236,58 +1251,82 @@ RelationClose(Relation relation)
12361251
/* --------------------------------
12371252
* RelationFlushRelation
12381253
*
1239-
* Actually blows away a relation... RelationFree doesn't do
1254+
* Actually blows away a relation cache entry... RelationFree doesn't do
12401255
* anything anymore.
12411256
* --------------------------------
12421257
*/
12431258
staticvoid
12441259
RelationFlushRelation(Relation*relationPtr,
12451260
boolonlyFlushReferenceCountZero)
12461261
{
1247-
MemoryContextoldcxt;
12481262
Relationrelation=*relationPtr;
1263+
MemoryContextoldcxt;
1264+
1265+
/*
1266+
* Make sure smgr and lower levels close the relation's files,
1267+
* if they weren't closed already. We do this unconditionally;
1268+
* if the relation is not deleted, the next smgr access should
1269+
* reopen the files automatically. This ensures that the low-level
1270+
* file access state is updated after, say, a vacuum truncation.
1271+
* NOTE: this call is a no-op if the relation's smgr file is already
1272+
* closed or unlinked.
1273+
*/
1274+
smgrclose(DEFAULT_SMGR,relation);
12491275

12501276
if (relation->rd_isnailed)
12511277
{
1252-
/* this is a nailed special relation forbootstraping */
1278+
/* this is a nailed special relation forbootstrapping */
12531279
return;
12541280
}
12551281

1256-
if (!onlyFlushReferenceCountZero||
1257-
RelationHasReferenceCountZero(relation))
1258-
{
1259-
oldcxt=MemoryContextSwitchTo((MemoryContext)CacheCxt);
1282+
oldcxt=MemoryContextSwitchTo((MemoryContext)CacheCxt);
12601283

1261-
/* make sure smgr and lower levels close the relation's files,
1262-
* if they weren't closed already
1263-
*/
1264-
smgrclose(DEFAULT_SMGR,relation);
1284+
/* Remove relation from hash tables
1285+
*
1286+
* Note: we might be reinserting it momentarily, but we must not have it
1287+
* visible in the hash tables until it's valid again, so don't try to
1288+
* optimize this away...
1289+
*/
1290+
RelationCacheDelete(relation);
1291+
1292+
/* Clear out catcache's entries for this relation */
1293+
SystemCacheRelationFlushed(RelationGetRelid(relation));
12651294

1266-
RelationCacheDelete(relation);
1295+
/* Free all the subsidiary data structures of the relcache entry */
1296+
FreeTupleDesc(relation->rd_att);
1297+
FreeTriggerDesc(relation);
1298+
pfree(RelationGetLockInfo(relation));
1299+
pfree(RelationGetForm(relation));
12671300

1268-
FreeTupleDesc(relation->rd_att);
1269-
SystemCacheRelationFlushed(RelationGetRelid(relation));
1301+
/* If we're really done with the relcache entry, blow it away.
1302+
* But if someone is still using it, reconstruct the whole deal
1303+
* without moving the physical RelationData record (so that the
1304+
* someone's pointer is still valid). Preserve ref count, too.
1305+
*/
1306+
if (!onlyFlushReferenceCountZero||
1307+
RelationHasReferenceCountZero(relation))
1308+
{
1309+
pfree(relation);
1310+
}
1311+
else
1312+
{
1313+
uint16old_refcnt=relation->rd_refcnt;
1314+
RelationBuildDescInfobuildinfo;
12701315

1271-
FreeTriggerDesc(relation);
1316+
buildinfo.infotype=INFO_RELID;
1317+
buildinfo.i.info_id=RelationGetRelid(relation);
12721318

1273-
#ifdefNOT_USED
1274-
if (relation->rd_rules)
1319+
if (RelationBuildDesc(buildinfo,relation)!=relation)
12751320
{
1276-
intj;
1277-
1278-
for (j=0;j<relation->rd_rules->numLocks;j++)
1279-
pfree(relation->rd_rules->rules[j]);
1280-
pfree(relation->rd_rules->rules);
1281-
pfree(relation->rd_rules);
1321+
/* Should only get here if relation was deleted */
1322+
pfree(relation);
1323+
elog(ERROR,"RelationFlushRelation: relation %u deleted while still in use",
1324+
buildinfo.i.info_id);
12821325
}
1283-
#endif
1284-
1285-
pfree(RelationGetLockInfo(relation));
1286-
pfree(RelationGetForm(relation));
1287-
pfree(relation);
1288-
1289-
MemoryContextSwitchTo(oldcxt);
1326+
RelationSetReferenceCount(relation,old_refcnt);
12901327
}
1328+
1329+
MemoryContextSwitchTo(oldcxt);
12911330
}
12921331

12931332
/* --------------------------------
@@ -1442,6 +1481,36 @@ RelationCacheInvalidate(bool onlyFlushReferenceCountZero)
14421481
}
14431482
}
14441483

1484+
/*
1485+
* RelationCacheAbort
1486+
*
1487+
*Clean up the relcache at transaction abort.
1488+
*
1489+
*What we need to do here is reset relcache entry ref counts to
1490+
*their normal not-in-a-transaction state. A ref count may be
1491+
*too high because some routine was exited by elog() between
1492+
*incrementing and decrementing the count.
1493+
*
1494+
*XXX Maybe we should do this at transaction commit, too, in case
1495+
*someone forgets to decrement a refcount in a non-error path?
1496+
*/
1497+
void
1498+
RelationCacheAbort(void)
1499+
{
1500+
HashTableWalk(RelationNameCache, (HashtFunc)RelationCacheAbortWalker,
1501+
0);
1502+
}
1503+
1504+
staticvoid
1505+
RelationCacheAbortWalker(Relation*relationPtr,intdummy)
1506+
{
1507+
Relationrelation=*relationPtr;
1508+
1509+
if (relation->rd_isnailed)
1510+
RelationSetReferenceCount(relation,1);
1511+
else
1512+
RelationSetReferenceCount(relation,0);
1513+
}
14451514

14461515
/* --------------------------------
14471516
*RelationRegisterRelation -
@@ -1523,7 +1592,7 @@ RelationPurgeLocalRelation(bool xactCommitted)
15231592
reln->rd_myxactonly= FALSE;
15241593

15251594
if (!IsBootstrapProcessingMode())
1526-
RelationFlushRelation(&reln,FALSE);
1595+
RelationFlushRelation(&reln,false);
15271596

15281597
newlyCreatedRelns=lnext(newlyCreatedRelns);
15291598
pfree(l);
@@ -2010,15 +2079,15 @@ write_irels(void)
20102079

20112080
bi.infotype=INFO_RELNAME;
20122081
bi.i.info_name=AttributeNumIndex;
2013-
irel[0]=RelationBuildDesc(bi);
2082+
irel[0]=RelationBuildDesc(bi,NULL);
20142083
irel[0]->rd_isnailed= true;
20152084

20162085
bi.i.info_name=ClassNameIndex;
2017-
irel[1]=RelationBuildDesc(bi);
2086+
irel[1]=RelationBuildDesc(bi,NULL);
20182087
irel[1]->rd_isnailed= true;
20192088

20202089
bi.i.info_name=ClassOidIndex;
2021-
irel[2]=RelationBuildDesc(bi);
2090+
irel[2]=RelationBuildDesc(bi,NULL);
20222091
irel[2]->rd_isnailed= true;
20232092

20242093
SetProcessingMode(oldmode);

‎src/include/utils/relcache.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*
77
* Copyright (c) 1994, Regents of the University of California
88
*
9-
* $Id: relcache.h,v 1.13 1999/07/15 23:04:23 momjian Exp $
9+
* $Id: relcache.h,v 1.14 1999/09/04 18:42:11 tgl Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -34,6 +34,8 @@ extern void RelationRegisterRelation(Relation relation);
3434
externvoidRelationPurgeLocalRelation(boolxactComitted);
3535
externvoidRelationInitialize(void);
3636

37+
externvoidRelationCacheAbort(void);
38+
3739
/*
3840
* both vacuum.c and relcache.c need to know the name of the relcache init file
3941
*/

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp