PostgreSQL Source Code git master
relfilenumbermap.c File Reference
#include "postgres.h"
#include "access/genam.h"
#include "access/htup_details.h"
#include "access/table.h"
#include "catalog/pg_class.h"
#include "catalog/pg_tablespace.h"
#include "miscadmin.h"
#include "utils/catcache.h"
#include "utils/fmgroids.h"
#include "utils/hsearch.h"
#include "utils/inval.h"
#include "utils/relfilenumbermap.h"
#include "utils/relmapper.h"
Include dependency graph for relfilenumbermap.c:

Go to the source code of this file.

Data Structures

struct  RelfilenumberMapKey
 
struct  RelfilenumberMapEntry
 

Functions

static void RelfilenumberMapInvalidateCallback (Datum arg, Oid relid)
 
static void InitializeRelfilenumberMap (void)
 
Oid RelidByRelfilenumber (Oid reltablespace, RelFileNumber relfilenumber)
 

Variables

static HTABRelfilenumberMapHash = NULL
 
static ScanKeyData relfilenumber_skey [2]
 

Function Documentation

◆ InitializeRelfilenumberMap()

static void InitializeRelfilenumberMap ( void  )
static

Definition at line 86 of file relfilenumbermap.c.

87{
89 int i;
90
91 /* Make sure we've initialized CacheMemoryContext. */
92 if (CacheMemoryContext == NULL)
94
95 /* build skey */
97
98 for (i = 0; i < 2; i++)
99 {
100 fmgr_info_cxt(F_OIDEQ,
101 &relfilenumber_skey[i].sk_func,
106 }
107
108 relfilenumber_skey[0].sk_attno = Anum_pg_class_reltablespace;
109 relfilenumber_skey[1].sk_attno = Anum_pg_class_relfilenode;
110
111 /*
112 * Only create the RelfilenumberMapHash now, so we don't end up partially
113 * initialized when fmgr_info_cxt() above ERRORs out with an out of memory
114 * error.
115 */
116 ctl.keysize = sizeof(RelfilenumberMapKey);
117 ctl.entrysize = sizeof(RelfilenumberMapEntry);
118 ctl.hcxt = CacheMemoryContext;
119
121 hash_create("RelfilenumberMap cache", 64, &ctl,
123
124 /* Watch for invalidation events. */
126 (Datum) 0);
127}
#define MemSet(start, val, len)
Definition: c.h:1022
void CreateCacheMemoryContext(void)
Definition: catcache.c:715
HTAB * hash_create(const char *tabname, int64 nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:358
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:138
#define HASH_CONTEXT
Definition: hsearch.h:102
#define HASH_ELEM
Definition: hsearch.h:95
#define HASH_BLOBS
Definition: hsearch.h:97
void CacheRegisterRelcacheCallback(RelcacheCallbackFunction func, Datum arg)
Definition: inval.c:1854
int i
Definition: isn.c:77
MemoryContext CacheMemoryContext
Definition: mcxt.c:169
uint64_t Datum
Definition: postgres.h:70
#define InvalidOid
Definition: postgres_ext.h:37
tree ctl
Definition: radixtree.h:1838
static ScanKeyData relfilenumber_skey[2]
static void RelfilenumberMapInvalidateCallback(Datum arg, Oid relid)
static HTAB * RelfilenumberMapHash
#define BTEqualStrategyNumber
Definition: stratnum.h:31
Oid sk_subtype
Definition: skey.h:69
Oid sk_collation
Definition: skey.h:70
StrategyNumber sk_strategy
Definition: skey.h:68
AttrNumber sk_attno
Definition: skey.h:67

References BTEqualStrategyNumber, CacheMemoryContext, CacheRegisterRelcacheCallback(), CreateCacheMemoryContext(), ctl, fmgr_info_cxt(), HASH_BLOBS, HASH_CONTEXT, hash_create(), HASH_ELEM, i, InvalidOid, MemSet, relfilenumber_skey, RelfilenumberMapHash, RelfilenumberMapInvalidateCallback(), ScanKeyData::sk_attno, ScanKeyData::sk_collation, ScanKeyData::sk_strategy, and ScanKeyData::sk_subtype.

Referenced by RelidByRelfilenumber().

◆ RelfilenumberMapInvalidateCallback()

static void RelfilenumberMapInvalidateCallback ( Datum  arg,
Oid  relid 
)
static

Definition at line 52 of file relfilenumbermap.c.

53{
54 HASH_SEQ_STATUS status;
56
57 /* callback only gets registered after creating the hash */
59
61 while ((entry = (RelfilenumberMapEntry *) hash_seq_search(&status)) != NULL)
62 {
63 /*
64 * If relid is InvalidOid, signaling a complete reset, we must remove
65 * all entries, otherwise just remove the specific relation's entry.
66 * Always remove negative cache entries.
67 */
68 if (relid == InvalidOid || /* complete reset */
69 entry->relid == InvalidOid || /* negative cache entry */
70 entry->relid == relid) /* individual flushed relation */
71 {
73 &entry->key,
75 NULL) == NULL)
76 elog(ERROR, "hash table corrupted");
77 }
78 }
79}
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:952
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1415
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1380
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:226
Assert(PointerIsAligned(start, uint64))
@ HASH_REMOVE
Definition: hsearch.h:115
RelfilenumberMapKey key

References Assert(), elog, ERROR, HASH_REMOVE, hash_search(), hash_seq_init(), hash_seq_search(), InvalidOid, RelfilenumberMapEntry::key, RelfilenumberMapHash, and RelfilenumberMapEntry::relid.

Referenced by InitializeRelfilenumberMap().

◆ RelidByRelfilenumber()

Oid RelidByRelfilenumber ( Oid  reltablespace,
RelFileNumber  relfilenumber 
)

Definition at line 141 of file relfilenumbermap.c.

142{
145 bool found;
146 SysScanDesc scandesc;
147 Relation relation;
148 HeapTuple ntp;
149 Oid relid;
150
151 if (RelfilenumberMapHash == NULL)
153
154 /* pg_class will show 0 when the value is actually MyDatabaseTableSpace */
155 if (reltablespace == MyDatabaseTableSpace)
156 reltablespace = 0;
157
158 MemSet(&key, 0, sizeof(key));
159 key.reltablespace = reltablespace;
160 key.relfilenumber = relfilenumber;
161
162 /*
163 * Check cache and return entry if one is found. Even if no target
164 * relation can be found later on we store the negative match and return a
165 * InvalidOid from cache. That's not really necessary for performance
166 * since querying invalid values isn't supposed to be a frequent thing,
167 * but it's basically free.
168 */
169 entry = hash_search(RelfilenumberMapHash, &key, HASH_FIND, &found);
170
171 if (found)
172 return entry->relid;
173
174 /* ok, no previous cache entry, do it the hard way */
175
176 /* initialize empty/negative cache entry before doing the actual lookups */
177 relid = InvalidOid;
178
179 if (reltablespace == GLOBALTABLESPACE_OID)
180 {
181 /*
182 * Ok, shared table, check relmapper.
183 */
184 relid = RelationMapFilenumberToOid(relfilenumber, true);
185 }
186 else
187 {
188 ScanKeyData skey[2];
189
190 /*
191 * Not a shared table, could either be a plain relation or a
192 * non-shared, nailed one, like e.g. pg_class.
193 */
194
195 /* check for plain relations by looking in pg_class */
196 relation = table_open(RelationRelationId, AccessShareLock);
197
198 /* copy scankey to local copy and set scan arguments */
199 memcpy(skey, relfilenumber_skey, sizeof(skey));
200 skey[0].sk_argument = ObjectIdGetDatum(reltablespace);
201 skey[1].sk_argument = ObjectIdGetDatum(relfilenumber);
202
203 scandesc = systable_beginscan(relation,
204 ClassTblspcRelfilenodeIndexId,
205 true,
206 NULL,
207 2,
208 skey);
209
210 found = false;
211
212 while (HeapTupleIsValid(ntp = systable_getnext(scandesc)))
213 {
214 Form_pg_class classform = (Form_pg_class) GETSTRUCT(ntp);
215
216 if (classform->relpersistence == RELPERSISTENCE_TEMP)
217 continue;
218
219 if (found)
220 elog(ERROR,
221 "unexpected duplicate for tablespace %u, relfilenumber %u",
222 reltablespace, relfilenumber);
223 found = true;
224
225 Assert(classform->reltablespace == reltablespace);
226 Assert(classform->relfilenode == relfilenumber);
227 relid = classform->oid;
228 }
229
230 systable_endscan(scandesc);
231 table_close(relation, AccessShareLock);
232
233 /* check for tables that are mapped but not shared */
234 if (!found)
235 relid = RelationMapFilenumberToOid(relfilenumber, false);
236 }
237
238 /*
239 * Only enter entry into cache now, our opening of pg_class could have
240 * caused cache invalidations to be executed which would have deleted a
241 * new entry if we had entered it above.
242 */
244 if (found)
245 elog(ERROR, "corrupted hashtable");
246 entry->relid = relid;
247
248 return relid;
249}
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:603
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:514
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:388
Oid MyDatabaseTableSpace
Definition: globals.c:96
@ HASH_FIND
Definition: hsearch.h:113
@ HASH_ENTER
Definition: hsearch.h:114
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
Definition: htup_details.h:728
#define AccessShareLock
Definition: lockdefs.h:36
FormData_pg_class * Form_pg_class
Definition: pg_class.h:156
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:262
unsigned int Oid
Definition: postgres_ext.h:32
static void InitializeRelfilenumberMap(void)
Oid RelationMapFilenumberToOid(RelFileNumber filenumber, bool shared)
Definition: relmapper.c:218
Datum sk_argument
Definition: skey.h:72
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40

References AccessShareLock, Assert(), elog, ERROR, GETSTRUCT(), HASH_ENTER, HASH_FIND, hash_search(), HeapTupleIsValid, InitializeRelfilenumberMap(), InvalidOid, sort-test::key, MemSet, MyDatabaseTableSpace, ObjectIdGetDatum(), RelationMapFilenumberToOid(), relfilenumber_skey, RelfilenumberMapHash, RelfilenumberMapEntry::relid, ScanKeyData::sk_argument, systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by autoprewarm_database_main(), pg_filenode_relation(), and ReorderBufferProcessTXN().

Variable Documentation

◆ relfilenumber_skey

ScanKeyData relfilenumber_skey[2]
static

Definition at line 33 of file relfilenumbermap.c.

Referenced by InitializeRelfilenumberMap(), and RelidByRelfilenumber().

◆ RelfilenumberMapHash

HTAB* RelfilenumberMapHash = NULL
static