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