PostgreSQL Source Code  git master
relfilenodemap.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/builtins.h"
#include "utils/catcache.h"
#include "utils/fmgroids.h"
#include "utils/hsearch.h"
#include "utils/inval.h"
#include "utils/rel.h"
#include "utils/relfilenodemap.h"
#include "utils/relmapper.h"
Include dependency graph for relfilenodemap.c:

Go to the source code of this file.

Data Structures

struct  RelfilenodeMapKey
 
struct  RelfilenodeMapEntry
 

Functions

static void RelfilenodeMapInvalidateCallback (Datum arg, Oid relid)
 
static void InitializeRelfilenodeMap (void)
 
Oid RelidByRelfilenode (Oid reltablespace, Oid relfilenode)
 

Variables

static HTABRelfilenodeMapHash = NULL
 
static ScanKeyData relfilenode_skey [2]
 

Function Documentation

◆ InitializeRelfilenodeMap()

static void InitializeRelfilenodeMap ( void  )
static

Definition at line 88 of file relfilenodemap.c.

References BTEqualStrategyNumber, CacheMemoryContext, CacheRegisterRelcacheCallback(), CreateCacheMemoryContext(), HASHCTL::entrysize, fmgr_info_cxt(), HASH_BLOBS, HASH_CONTEXT, hash_create(), HASH_ELEM, HASHCTL::hcxt, i, InvalidOid, HASHCTL::keysize, MemSet, RelfilenodeMapInvalidateCallback(), ScanKeyData::sk_attno, ScanKeyData::sk_collation, ScanKeyData::sk_strategy, and ScanKeyData::sk_subtype.

Referenced by RelidByRelfilenode().

89 {
90  HASHCTL ctl;
91  int i;
92 
93  /* Make sure we've initialized CacheMemoryContext. */
94  if (CacheMemoryContext == NULL)
96 
97  /* build skey */
99 
100  for (i = 0; i < 2; i++)
101  {
102  fmgr_info_cxt(F_OIDEQ,
103  &relfilenode_skey[i].sk_func,
108  }
109 
110  relfilenode_skey[0].sk_attno = Anum_pg_class_reltablespace;
111  relfilenode_skey[1].sk_attno = Anum_pg_class_relfilenode;
112 
113  /* Initialize the hash table. */
114  MemSet(&ctl, 0, sizeof(ctl));
115  ctl.keysize = sizeof(RelfilenodeMapKey);
116  ctl.entrysize = sizeof(RelfilenodeMapEntry);
117  ctl.hcxt = CacheMemoryContext;
118 
119  /*
120  * Only create the RelfilenodeMapHash now, so we don't end up partially
121  * initialized when fmgr_info_cxt() above ERRORs out with an out of memory
122  * error.
123  */
125  hash_create("RelfilenodeMap cache", 64, &ctl,
127 
128  /* Watch for invalidation events. */
130  (Datum) 0);
131 }
Oid sk_subtype
Definition: skey.h:69
#define HASH_CONTEXT
Definition: hsearch.h:91
#define HASH_ELEM
Definition: hsearch.h:85
MemoryContext hcxt
Definition: hsearch.h:77
Size entrysize
Definition: hsearch.h:72
#define MemSet(start, val, len)
Definition: c.h:1004
void CacheRegisterRelcacheCallback(RelcacheCallbackFunction func, Datum arg)
Definition: inval.c:1476
static HTAB * RelfilenodeMapHash
StrategyNumber sk_strategy
Definition: skey.h:68
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:136
static void RelfilenodeMapInvalidateCallback(Datum arg, Oid relid)
static ScanKeyData relfilenode_skey[2]
#define HASH_BLOBS
Definition: hsearch.h:86
uintptr_t Datum
Definition: postgres.h:367
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:326
Size keysize
Definition: hsearch.h:71
#define InvalidOid
Definition: postgres_ext.h:36
void CreateCacheMemoryContext(void)
Definition: catcache.c:620
Oid sk_collation
Definition: skey.h:70
int i
#define BTEqualStrategyNumber
Definition: stratnum.h:31
AttrNumber sk_attno
Definition: skey.h:67
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RelfilenodeMapInvalidateCallback()

static void RelfilenodeMapInvalidateCallback ( Datum  arg,
Oid  relid 
)
static

Definition at line 54 of file relfilenodemap.c.

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

Referenced by InitializeRelfilenodeMap().

55 {
57  RelfilenodeMapEntry *entry;
58 
59  /* callback only gets registered after creating the hash */
60  Assert(RelfilenodeMapHash != NULL);
61 
63  while ((entry = (RelfilenodeMapEntry *) hash_seq_search(&status)) != NULL)
64  {
65  /*
66  * If relid is InvalidOid, signaling a complete reset, we must remove
67  * all entries, otherwise just remove the specific relation's entry.
68  * Always remove negative cache entries.
69  */
70  if (relid == InvalidOid || /* complete reset */
71  entry->relid == InvalidOid || /* negative cache entry */
72  entry->relid == relid) /* individual flushed relation */
73  {
75  (void *) &entry->key,
77  NULL) == NULL)
78  elog(ERROR, "hash table corrupted");
79  }
80  }
81 }
RelfilenodeMapKey key
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:919
static HTAB * RelfilenodeMapHash
#define ERROR
Definition: elog.h:43
#define InvalidOid
Definition: postgres_ext.h:36
#define Assert(condition)
Definition: c.h:800
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1401
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1391
#define elog(elevel,...)
Definition: elog.h:228
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227

◆ RelidByRelfilenode()

Oid RelidByRelfilenode ( Oid  reltablespace,
Oid  relfilenode 
)

Definition at line 140 of file relfilenodemap.c.

References AccessShareLock, Assert, ClassTblspcRelfilenodeIndexId, elog, ERROR, GETSTRUCT, HASH_ENTER, HASH_FIND, hash_search(), HeapTupleIsValid, InitializeRelfilenodeMap(), InvalidOid, sort-test::key, MemSet, MyDatabaseTableSpace, ObjectIdGetDatum, RelationMapFilenodeToOid(), RelfilenodeMapKey::relfilenode, RelfilenodeMapEntry::relid, RelfilenodeMapKey::reltablespace, ScanKeyData::sk_argument, systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

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

141 {
143  RelfilenodeMapEntry *entry;
144  bool found;
145  SysScanDesc scandesc;
146  Relation relation;
147  HeapTuple ntp;
148  ScanKeyData skey[2];
149  Oid relid;
150 
151  if (RelfilenodeMapHash == 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.relfilenode = relfilenode;
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(RelfilenodeMapHash, (void *) &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 = RelationMapFilenodeToOid(relfilenode, true);
185  }
186  else
187  {
188  /*
189  * Not a shared table, could either be a plain relation or a
190  * non-shared, nailed one, like e.g. pg_class.
191  */
192 
193  /* check for plain relations by looking in pg_class */
194  relation = table_open(RelationRelationId, AccessShareLock);
195 
196  /* copy scankey to local copy, it will be modified during the scan */
197  memcpy(skey, relfilenode_skey, sizeof(skey));
198 
199  /* set scan arguments */
200  skey[0].sk_argument = ObjectIdGetDatum(reltablespace);
201  skey[1].sk_argument = ObjectIdGetDatum(relfilenode);
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  {
214  Form_pg_class classform = (Form_pg_class) GETSTRUCT(ntp);
215 
216  if (found)
217  elog(ERROR,
218  "unexpected duplicate for tablespace %u, relfilenode %u",
219  reltablespace, relfilenode);
220  found = true;
221 
222  Assert(classform->reltablespace == reltablespace);
223  Assert(classform->relfilenode == relfilenode);
224  relid = classform->oid;
225  }
226 
227  systable_endscan(scandesc);
228  table_close(relation, AccessShareLock);
229 
230  /* check for tables that are mapped but not shared */
231  if (!found)
232  relid = RelationMapFilenodeToOid(relfilenode, false);
233  }
234 
235  /*
236  * Only enter entry into cache now, our opening of pg_class could have
237  * caused cache invalidations to be executed which would have deleted a
238  * new entry if we had entered it above.
239  */
240  entry = hash_search(RelfilenodeMapHash, (void *) &key, HASH_ENTER, &found);
241  if (found)
242  elog(ERROR, "corrupted hashtable");
243  entry->relid = relid;
244 
245  return relid;
246 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:569
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define AccessShareLock
Definition: lockdefs.h:36
#define MemSet(start, val, len)
Definition: c.h:1004
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:919
unsigned int Oid
Definition: postgres_ext.h:31
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:357
Oid MyDatabaseTableSpace
Definition: globals.c:87
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:476
static HTAB * RelfilenodeMapHash
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
static ScanKeyData relfilenode_skey[2]
#define ClassTblspcRelfilenodeIndexId
Definition: pg_class.h:160
#define InvalidOid
Definition: postgres_ext.h:36
Oid RelationMapFilenodeToOid(Oid filenode, bool shared)
Definition: relmapper.c:212
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:800
static void InitializeRelfilenodeMap(void)
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
#define elog(elevel,...)
Definition: elog.h:228
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
Datum sk_argument
Definition: skey.h:72

Variable Documentation

◆ relfilenode_skey

ScanKeyData relfilenode_skey[2]
static

Definition at line 35 of file relfilenodemap.c.

◆ RelfilenodeMapHash

HTAB* RelfilenodeMapHash = NULL
static

Definition at line 32 of file relfilenodemap.c.