PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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:974
void CreateCacheMemoryContext(void)
Definition: catcache.c:680
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:352
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:137
#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:1746
int i
Definition: isn.c:72
MemoryContext CacheMemoryContext
Definition: mcxt.c:152
uintptr_t Datum
Definition: postgres.h:64
#define InvalidOid
Definition: postgres_ext.h:36
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}
#define Assert(condition)
Definition: c.h:812
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:955
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1420
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1385
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
@ 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 136 of file relfilenumbermap.c.

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