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.

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  /*
114  * Only create the RelfilenodeMapHash now, so we don't end up partially
115  * initialized when fmgr_info_cxt() above ERRORs out with an out of memory
116  * error.
117  */
118  ctl.keysize = sizeof(RelfilenodeMapKey);
119  ctl.entrysize = sizeof(RelfilenodeMapEntry);
120  ctl.hcxt = CacheMemoryContext;
121 
123  hash_create("RelfilenodeMap cache", 64, &ctl,
125 
126  /* Watch for invalidation events. */
128  (Datum) 0);
129 }
#define MemSet(start, val, len)
Definition: c.h:1008
void CreateCacheMemoryContext(void)
Definition: catcache.c:620
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:349
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:136
#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:1560
int i
Definition: isn.c:73
MemoryContext CacheMemoryContext
Definition: mcxt.c:51
uintptr_t Datum
Definition: postgres.h:411
#define InvalidOid
Definition: postgres_ext.h:36
static void RelfilenodeMapInvalidateCallback(Datum arg, Oid relid)
static HTAB * RelfilenodeMapHash
static ScanKeyData relfilenode_skey[2]
#define BTEqualStrategyNumber
Definition: stratnum.h:31
Size keysize
Definition: hsearch.h:75
Size entrysize
Definition: hsearch.h:76
MemoryContext hcxt
Definition: hsearch.h:86
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(), HASHCTL::entrysize, fmgr_info_cxt(), HASH_BLOBS, HASH_CONTEXT, hash_create(), HASH_ELEM, HASHCTL::hcxt, i, InvalidOid, HASHCTL::keysize, MemSet, relfilenode_skey, RelfilenodeMapHash, RelfilenodeMapInvalidateCallback(), ScanKeyData::sk_attno, ScanKeyData::sk_collation, ScanKeyData::sk_strategy, and ScanKeyData::sk_subtype.

Referenced by RelidByRelfilenode().

◆ RelfilenodeMapInvalidateCallback()

static void RelfilenodeMapInvalidateCallback ( Datum  arg,
Oid  relid 
)
static

Definition at line 54 of file relfilenodemap.c.

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 }
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:954
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1436
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1426
#define ERROR
Definition: elog.h:33
#define elog(elevel,...)
Definition: elog.h:218
@ HASH_REMOVE
Definition: hsearch.h:115
Assert(fmt[strlen(fmt) - 1] !='\n')
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:229
RelfilenodeMapKey key

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

Referenced by InitializeRelfilenodeMap().

◆ RelidByRelfilenode()

Oid RelidByRelfilenode ( Oid  reltablespace,
Oid  relfilenode 
)

Definition at line 138 of file relfilenodemap.c.

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

References AccessShareLock, Assert(), elog, ERROR, GETSTRUCT, HASH_ENTER, HASH_FIND, hash_search(), HeapTupleIsValid, InitializeRelfilenodeMap(), InvalidOid, sort-test::key, MemSet, MyDatabaseTableSpace, ObjectIdGetDatum, RelationMapFilenodeToOid(), relfilenode_skey, RelfilenodeMapHash, RelfilenodeMapEntry::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

◆ relfilenode_skey

ScanKeyData relfilenode_skey[2]
static

Definition at line 35 of file relfilenodemap.c.

Referenced by InitializeRelfilenodeMap(), and RelidByRelfilenode().

◆ RelfilenodeMapHash

HTAB* RelfilenodeMapHash = NULL
static