PostgreSQL Source Code git master
Loading...
Searching...
No Matches
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. */
94
95 /* build skey */
97
98 for (i = 0; i < 2; i++)
99 {
101 &relfilenumber_skey[i].sk_func,
106 }
107
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:1013
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:1858
int i
Definition isn.c:77
MemoryContext CacheMemoryContext
Definition mcxt.c:169
uint64_t Datum
Definition postgres.h:70
#define InvalidOid
static int fb(int x)
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, fb(), 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:873
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
@ HASH_REMOVE
Definition hsearch.h:115
RelfilenumberMapKey key

References Assert, elog, ERROR, fb(), 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;
149 Oid relid;
150
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 */
197
198 /* copy scankey to local copy and set scan arguments */
200 skey[0].sk_argument = ObjectIdGetDatum(reltablespace);
201 skey[1].sk_argument = ObjectIdGetDatum(relfilenumber);
202
203 scandesc = systable_beginscan(relation,
205 true,
206 NULL,
207 2,
208 skey);
209
210 found = false;
211
212 while (HeapTupleIsValid(ntp = systable_getnext(scandesc)))
213 {
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 */
243 entry = hash_search(RelfilenumberMapHash, &key, HASH_ENTER, &found);
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)
#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
static void InitializeRelfilenumberMap(void)
Oid RelationMapFilenumberToOid(RelFileNumber filenumber, bool shared)
Definition relmapper.c:218
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, fb(), GETSTRUCT(), HASH_ENTER, HASH_FIND, hash_search(), HeapTupleIsValid, InitializeRelfilenumberMap(), InvalidOid, MemSet, MyDatabaseTableSpace, ObjectIdGetDatum(), RelationMapFilenumberToOid(), relfilenumber_skey, RelfilenumberMapHash, RelfilenumberMapEntry::relid, 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