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

Commitf01d1ae

Browse files
committed
Add infrastructure for mapping relfilenodes to relation OIDs.
Future patches are expected to introduce logical replication thatworks by decoding WAL. WAL contains relfilenodes rather than relationOIDs, so this infrastructure will be needed to find the relation OIDbased on WAL contents.If logical replication does not make it into this release, we probablyshould consider reverting this, since it will add some overhead to DDLoperations that create new relations. One additional index insert perpg_class row is not a large overhead, but it's more than zero.Another way of meeting the needs of logical replication would be tothe relation OID to WAL, but that would burden DML operations, notonly DDL.Andres Freund, with some changes by me. Design review, in earlierversions, by Álvaro Herrera.
1 parentb3b10c3 commitf01d1ae

File tree

14 files changed

+408
-3
lines changed

14 files changed

+408
-3
lines changed

‎doc/src/sgml/func.sgml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15748,6 +15748,9 @@ postgres=# SELECT * FROM pg_xlogfile_name_offset(pg_stop_backup());
1574815748
<indexterm>
1574915749
<primary>pg_relation_filepath</primary>
1575015750
</indexterm>
15751+
<indexterm>
15752+
<primary>pg_filenode_relation</primary>
15753+
</indexterm>
1575115754

1575215755
<table id="functions-admin-dblocation">
1575315756
<title>Database Object Location Functions</title>
@@ -15776,6 +15779,15 @@ postgres=# SELECT * FROM pg_xlogfile_name_offset(pg_stop_backup());
1577615779
File path name of the specified relation
1577715780
</entry>
1577815781
</row>
15782+
<row>
15783+
<entry>
15784+
<literal><function>pg_filenode_relation(<parameter>tablespace</parameter> <type>oid</type>, <parameter>filenode</parameter> <type>oid</type>)</function></literal>
15785+
</entry>
15786+
<entry><type>regclass</type></entry>
15787+
<entry>
15788+
Find the relation associated with a given tablespace and filenode
15789+
</entry>
15790+
</row>
1577915791
</tbody>
1578015792
</tgroup>
1578115793
</table>
@@ -15799,6 +15811,13 @@ postgres=# SELECT * FROM pg_xlogfile_name_offset(pg_stop_backup());
1579915811
the relation.
1580015812
</para>
1580115813

15814+
<para>
15815+
<function>pg_filenode_relation</> is the reverse of
15816+
<function>pg_relation_filenode</>. Given a <quote>tablespace</> OID and
15817+
a <quote>filenode</> it returns the associated relation. The default
15818+
tablespace can be specified as 0.
15819+
</para>
15820+
1580215821
</sect2>
1580315822

1580415823
<sect2 id="functions-admin-genfile">

‎src/backend/utils/adt/dbsize.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include"utils/builtins.h"
2929
#include"utils/numeric.h"
3030
#include"utils/rel.h"
31+
#include"utils/relfilenodemap.h"
3132
#include"utils/relmapper.h"
3233
#include"utils/syscache.h"
3334

@@ -755,6 +756,33 @@ pg_relation_filenode(PG_FUNCTION_ARGS)
755756
PG_RETURN_OID(result);
756757
}
757758

759+
/*
760+
* Get the relation via (reltablespace, relfilenode)
761+
*
762+
* This is expected to be used when somebody wants to match an individual file
763+
* on the filesystem back to its table. Thats not trivially possible via
764+
* pg_class because that doesn't contain the relfilenodes of shared and nailed
765+
* tables.
766+
*
767+
* We don't fail but return NULL if we cannot find a mapping.
768+
*
769+
* Instead of knowing DEFAULTTABLESPACE_OID you can pass 0.
770+
*/
771+
Datum
772+
pg_filenode_relation(PG_FUNCTION_ARGS)
773+
{
774+
Oidreltablespace=PG_GETARG_OID(0);
775+
Oidrelfilenode=PG_GETARG_OID(1);
776+
Oidheaprel=InvalidOid;
777+
778+
heaprel=RelidByRelfilenode(reltablespace,relfilenode);
779+
780+
if (!OidIsValid(heaprel))
781+
PG_RETURN_NULL();
782+
else
783+
PG_RETURN_OID(heaprel);
784+
}
785+
758786
/*
759787
* Get the pathname (relative to $PGDATA) of a relation
760788
*

‎src/backend/utils/cache/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ top_builddir = ../../../..
1313
include$(top_builddir)/src/Makefile.global
1414

1515
OBJS = attoptcache.o catcache.o evtcache.o inval.o plancache.o relcache.o\
16-
relmapper.o spccache.o syscache.o lsyscache.o typcache.o ts_cache.o
16+
relmapper.o relfilenodemap.o spccache.o syscache.o lsyscache.o\
17+
typcache.o ts_cache.o
1718

1819
include$(top_srcdir)/src/backend/common.mk

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ static intmaxSharedInvalidMessagesArray;
178178
*/
179179

180180
#defineMAX_SYSCACHE_CALLBACKS 32
181-
#defineMAX_RELCACHE_CALLBACKS5
181+
#defineMAX_RELCACHE_CALLBACKS10
182182

183183
staticstructSYSCACHECALLBACK
184184
{
Lines changed: 247 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,247 @@
1+
/*-------------------------------------------------------------------------
2+
*
3+
* relfilenodemap.c
4+
* relfilenode to oid mapping cache.
5+
*
6+
* Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
7+
* Portions Copyright (c) 1994, Regents of the University of California
8+
*
9+
* IDENTIFICATION
10+
* src/backend/utils/cache/relfilenode.c
11+
*
12+
*-------------------------------------------------------------------------
13+
*/
14+
#include"postgres.h"
15+
16+
#include"access/genam.h"
17+
#include"access/heapam.h"
18+
#include"access/htup_details.h"
19+
#include"catalog/indexing.h"
20+
#include"catalog/pg_class.h"
21+
#include"catalog/pg_tablespace.h"
22+
#include"miscadmin.h"
23+
#include"utils/builtins.h"
24+
#include"utils/catcache.h"
25+
#include"utils/hsearch.h"
26+
#include"utils/inval.h"
27+
#include"utils/fmgroids.h"
28+
#include"utils/rel.h"
29+
#include"utils/relfilenodemap.h"
30+
#include"utils/relmapper.h"
31+
32+
/* Hash table for informations about each relfilenode <-> oid pair */
33+
staticHTAB*RelfilenodeMapHash=NULL;
34+
35+
/* built first time through in InitializeRelfilenodeMap */
36+
ScanKeyDatarelfilenode_skey[2];
37+
38+
typedefstruct
39+
{
40+
Oidreltablespace;
41+
Oidrelfilenode;
42+
}RelfilenodeMapKey;
43+
44+
typedefstruct
45+
{
46+
RelfilenodeMapKeykey;/* lookup key - must be first */
47+
Oidrelid;/* pg_class.oid */
48+
}RelfilenodeMapEntry;
49+
50+
/*
51+
* RelfilenodeMapInvalidateCallback
52+
*Flush mapping entries when pg_class is updated in a relevant fashion.
53+
*/
54+
staticvoid
55+
RelfilenodeMapInvalidateCallback(Datumarg,Oidrelid)
56+
{
57+
HASH_SEQ_STATUSstatus;
58+
RelfilenodeMapEntry*entry;
59+
60+
/* nothing to do if not active or deleted */
61+
if (RelfilenodeMapHash==NULL)
62+
return;
63+
64+
/* if relid is InvalidOid, we must invalidate the entire cache */
65+
if (relid==InvalidOid)
66+
{
67+
hash_destroy(RelfilenodeMapHash);
68+
RelfilenodeMapHash=NULL;
69+
return;
70+
}
71+
72+
hash_seq_init(&status,RelfilenodeMapHash);
73+
while ((entry= (RelfilenodeMapEntry*)hash_seq_search(&status))!=NULL)
74+
{
75+
/* Same OID may occur in more than one tablespace. */
76+
if (entry->relid==relid)
77+
{
78+
if (hash_search(RelfilenodeMapHash,
79+
(void*)&entry->key,
80+
HASH_REMOVE,
81+
NULL)==NULL)
82+
elog(ERROR,"hash table corrupted");
83+
}
84+
}
85+
}
86+
87+
/*
88+
* RelfilenodeMapInvalidateCallback
89+
*Initialize cache, either on first use or after a reset.
90+
*/
91+
staticvoid
92+
InitializeRelfilenodeMap(void)
93+
{
94+
HASHCTLctl;
95+
staticboolinitial_init_done= false;
96+
inti;
97+
98+
/* Make sure we've initialized CacheMemoryContext. */
99+
if (CacheMemoryContext==NULL)
100+
CreateCacheMemoryContext();
101+
102+
/* Initialize the hash table. */
103+
MemSet(&ctl,0,sizeof(ctl));
104+
ctl.keysize=sizeof(RelfilenodeMapKey);
105+
ctl.entrysize=sizeof(RelfilenodeMapEntry);
106+
ctl.hash=tag_hash;
107+
ctl.hcxt=CacheMemoryContext;
108+
109+
RelfilenodeMapHash=
110+
hash_create("RelfilenodeMap cache",1024,&ctl,
111+
HASH_ELEM |HASH_FUNCTION |HASH_CONTEXT);
112+
113+
/*
114+
* For complete resets we simply delete the entire hash, but there's no
115+
* need to do the other stuff multiple times. Especially the initialization
116+
* of the relcche invalidation should only be done once.
117+
*/
118+
if (initial_init_done)
119+
return;
120+
121+
/* build skey */
122+
MemSet(&relfilenode_skey,0,sizeof(relfilenode_skey));
123+
124+
for (i=0;i<2;i++)
125+
{
126+
fmgr_info_cxt(F_OIDEQ,
127+
&relfilenode_skey[i].sk_func,
128+
CacheMemoryContext);
129+
relfilenode_skey[i].sk_strategy=BTEqualStrategyNumber;
130+
relfilenode_skey[i].sk_subtype=InvalidOid;
131+
relfilenode_skey[i].sk_collation=InvalidOid;
132+
}
133+
134+
relfilenode_skey[0].sk_attno=Anum_pg_class_reltablespace;
135+
relfilenode_skey[1].sk_attno=Anum_pg_class_relfilenode;
136+
137+
/* Watch for invalidation events. */
138+
CacheRegisterRelcacheCallback(RelfilenodeMapInvalidateCallback,
139+
(Datum)0);
140+
initial_init_done= true;
141+
}
142+
143+
/*
144+
* Map a relation's (tablespace, filenode) to a relation's oid and cache the
145+
* result.
146+
*
147+
* Returns InvalidOid if no relation matching the criteria could be found.
148+
*/
149+
Oid
150+
RelidByRelfilenode(Oidreltablespace,Oidrelfilenode)
151+
{
152+
RelfilenodeMapKeykey;
153+
RelfilenodeMapEntry*entry;
154+
boolfound;
155+
SysScanDescscandesc;
156+
Relationrelation;
157+
HeapTuplentp;
158+
ScanKeyDataskey[2];
159+
160+
if (RelfilenodeMapHash==NULL)
161+
InitializeRelfilenodeMap();
162+
163+
/* pg_class will show 0 when the value is actually MyDatabaseTableSpace */
164+
if (reltablespace==MyDatabaseTableSpace)
165+
reltablespace=0;
166+
167+
MemSet(&key,0,sizeof(key));
168+
key.reltablespace=reltablespace;
169+
key.relfilenode=relfilenode;
170+
171+
/*
172+
* Check cache and enter entry if nothing could be found. Even if no target
173+
* relation can be found later on we store the negative match and return a
174+
* InvalidOid from cache. That's not really necessary for performance since
175+
* querying invalid values isn't supposed to be a frequent thing, but the
176+
* implementation is simpler this way.
177+
*/
178+
entry=hash_search(RelfilenodeMapHash, (void*)&key,HASH_ENTER,&found);
179+
180+
if (found)
181+
returnentry->relid;
182+
183+
/* ok, no previous cache entry, do it the hard way */
184+
185+
/* check shared tables */
186+
if (reltablespace==GLOBALTABLESPACE_OID)
187+
{
188+
entry->relid=RelationMapFilenodeToOid(relfilenode, true);
189+
returnentry->relid;
190+
}
191+
192+
/* check plain relations by looking in pg_class */
193+
relation=heap_open(RelationRelationId,AccessShareLock);
194+
195+
/* copy scankey to local copy, it will be modified during the scan */
196+
memcpy(skey,relfilenode_skey,sizeof(skey));
197+
198+
/* set scan arguments */
199+
skey[0].sk_argument=ObjectIdGetDatum(reltablespace);
200+
skey[1].sk_argument=ObjectIdGetDatum(relfilenode);
201+
202+
scandesc=systable_beginscan(relation,
203+
ClassTblspcRelfilenodeIndexId,
204+
true,
205+
NULL,
206+
2,
207+
skey);
208+
209+
found= false;
210+
211+
while (HeapTupleIsValid(ntp=systable_getnext(scandesc)))
212+
{
213+
boolisnull;
214+
215+
if (found)
216+
elog(ERROR,
217+
"unexpected duplicate for tablespace %u, relfilenode %u",
218+
reltablespace,relfilenode);
219+
found= true;
220+
221+
#ifdefUSE_ASSERT_CHECKING
222+
if (assert_enabled)
223+
{
224+
Oidcheck;
225+
check=fastgetattr(ntp,Anum_pg_class_reltablespace,
226+
RelationGetDescr(relation),
227+
&isnull);
228+
Assert(!isnull&&check==reltablespace);
229+
230+
check=fastgetattr(ntp,Anum_pg_class_relfilenode,
231+
RelationGetDescr(relation),
232+
&isnull);
233+
Assert(!isnull&&check==relfilenode);
234+
}
235+
#endif
236+
entry->relid=HeapTupleGetOid(ntp);
237+
}
238+
239+
systable_endscan(scandesc);
240+
heap_close(relation,AccessShareLock);
241+
242+
/* check for tables that are mapped but not shared */
243+
if (!found)
244+
entry->relid=RelationMapFilenodeToOid(relfilenode, false);
245+
246+
returnentry->relid;
247+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp