PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
relfilenodemap.c File Reference
#include "postgres.h"
#include "access/genam.h"
#include "access/heapam.h"
#include "access/htup_details.h"
#include "catalog/indexing.h"
#include "catalog/pg_class.h"
#include "catalog/pg_tablespace.h"
#include "miscadmin.h"
#include "utils/builtins.h"
#include "utils/catcache.h"
#include "utils/hsearch.h"
#include "utils/inval.h"
#include "utils/fmgroids.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

static void InitializeRelfilenodeMap ( void  )
static

Definition at line 89 of file relfilenodemap.c.

References Anum_pg_class_relfilenode, Anum_pg_class_reltablespace, 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().

90 {
91  HASHCTL ctl;
92  int i;
93 
94  /* Make sure we've initialized CacheMemoryContext. */
95  if (CacheMemoryContext == NULL)
97 
98  /* build skey */
100 
101  for (i = 0; i < 2; i++)
102  {
103  fmgr_info_cxt(F_OIDEQ,
104  &relfilenode_skey[i].sk_func,
109  }
110 
113 
114  /* Initialize the hash table. */
115  MemSet(&ctl, 0, sizeof(ctl));
116  ctl.keysize = sizeof(RelfilenodeMapKey);
117  ctl.entrysize = sizeof(RelfilenodeMapEntry);
118  ctl.hcxt = CacheMemoryContext;
119 
120  /*
121  * Only create the RelfilenodeMapHash now, so we don't end up partially
122  * initialized when fmgr_info_cxt() above ERRORs out with an out of memory
123  * error.
124  */
126  hash_create("RelfilenodeMap cache", 64, &ctl,
128 
129  /* Watch for invalidation events. */
131  (Datum) 0);
132 }
Oid sk_subtype
Definition: skey.h:69
#define HASH_CONTEXT
Definition: hsearch.h:93
#define HASH_ELEM
Definition: hsearch.h:87
MemoryContext hcxt
Definition: hsearch.h:78
#define Anum_pg_class_reltablespace
Definition: pg_class.h:110
Size entrysize
Definition: hsearch.h:73
#define MemSet(start, val, len)
Definition: c.h:863
#define Anum_pg_class_relfilenode
Definition: pg_class.h:109
void CacheRegisterRelcacheCallback(RelcacheCallbackFunction func, Datum arg)
Definition: inval.c:1431
static HTAB * RelfilenodeMapHash
StrategyNumber sk_strategy
Definition: skey.h:68
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:132
static void RelfilenodeMapInvalidateCallback(Datum arg, Oid relid)
static ScanKeyData relfilenode_skey[2]
#define HASH_BLOBS
Definition: hsearch.h:88
uintptr_t Datum
Definition: postgres.h:372
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:316
Size keysize
Definition: hsearch.h:72
#define InvalidOid
Definition: postgres_ext.h:36
void CreateCacheMemoryContext(void)
Definition: catcache.c:636
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:46
static void RelfilenodeMapInvalidateCallback ( Datum  arg,
Oid  relid 
)
static

Definition at line 55 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().

56 {
58  RelfilenodeMapEntry *entry;
59 
60  /* callback only gets registered after creating the hash */
61  Assert(RelfilenodeMapHash != NULL);
62 
64  while ((entry = (RelfilenodeMapEntry *) hash_seq_search(&status)) != NULL)
65  {
66  /*
67  * If relid is InvalidOid, signalling a complete reset, we must remove
68  * all entries, otherwise just remove the specific relation's entry.
69  * Always remove negative cache entries.
70  */
71  if (relid == InvalidOid || /* complete reset */
72  entry->relid == InvalidOid || /* negative cache entry */
73  entry->relid == relid) /* individual flushed relation */
74  {
76  (void *) &entry->key,
78  NULL) == NULL)
79  elog(ERROR, "hash table corrupted");
80  }
81  }
82 }
RelfilenodeMapKey key
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:902
static HTAB * RelfilenodeMapHash
#define ERROR
Definition: elog.h:43
#define InvalidOid
Definition: postgres_ext.h:36
#define Assert(condition)
Definition: c.h:681
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1385
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1375
#define elog
Definition: elog.h:219
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225
Oid RelidByRelfilenode ( Oid  reltablespace,
Oid  relfilenode 
)

Definition at line 141 of file relfilenodemap.c.

References AccessShareLock, Anum_pg_class_relfilenode, Anum_pg_class_reltablespace, Assert, ClassTblspcRelfilenodeIndexId, elog, ERROR, fastgetattr, GLOBALTABLESPACE_OID, HASH_ENTER, HASH_FIND, hash_search(), heap_close, heap_open(), HeapTupleGetOid, HeapTupleIsValid, InitializeRelfilenodeMap(), InvalidOid, MemSet, MyDatabaseTableSpace, ObjectIdGetDatum, RelationGetDescr, RelationMapFilenodeToOid(), RelationRelationId, RelfilenodeMapKey::relfilenode, RelfilenodeMapEntry::relid, RelfilenodeMapKey::reltablespace, ScanKeyData::sk_argument, systable_beginscan(), systable_endscan(), and systable_getnext().

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

142 {
143  RelfilenodeMapKey key;
144  RelfilenodeMapEntry *entry;
145  bool found;
146  SysScanDesc scandesc;
147  Relation relation;
148  HeapTuple ntp;
149  ScanKeyData skey[2];
150  Oid relid;
151 
152  if (RelfilenodeMapHash == NULL)
154 
155  /* pg_class will show 0 when the value is actually MyDatabaseTableSpace */
156  if (reltablespace == MyDatabaseTableSpace)
157  reltablespace = 0;
158 
159  MemSet(&key, 0, sizeof(key));
160  key.reltablespace = reltablespace;
161  key.relfilenode = relfilenode;
162 
163  /*
164  * Check cache and return entry if one is found. Even if no target
165  * relation can be found later on we store the negative match and return a
166  * InvalidOid from cache. That's not really necessary for performance
167  * since querying invalid values isn't supposed to be a frequent thing,
168  * but it's basically free.
169  */
170  entry = hash_search(RelfilenodeMapHash, (void *) &key, HASH_FIND, &found);
171 
172  if (found)
173  return entry->relid;
174 
175  /* ok, no previous cache entry, do it the hard way */
176 
177  /* initialize empty/negative cache entry before doing the actual lookups */
178  relid = InvalidOid;
179 
180  if (reltablespace == GLOBALTABLESPACE_OID)
181  {
182  /*
183  * Ok, shared table, check relmapper.
184  */
185  relid = RelationMapFilenodeToOid(relfilenode, true);
186  }
187  else
188  {
189  /*
190  * Not a shared table, could either be a plain relation or a
191  * non-shared, nailed one, like e.g. pg_class.
192  */
193 
194  /* check for plain relations by looking in pg_class */
196 
197  /* copy scankey to local copy, it will be modified during the scan */
198  memcpy(skey, relfilenode_skey, sizeof(skey));
199 
200  /* set scan arguments */
201  skey[0].sk_argument = ObjectIdGetDatum(reltablespace);
202  skey[1].sk_argument = ObjectIdGetDatum(relfilenode);
203 
204  scandesc = systable_beginscan(relation,
206  true,
207  NULL,
208  2,
209  skey);
210 
211  found = false;
212 
213  while (HeapTupleIsValid(ntp = systable_getnext(scandesc)))
214  {
215  if (found)
216  elog(ERROR,
217  "unexpected duplicate for tablespace %u, relfilenode %u",
218  reltablespace, relfilenode);
219  found = true;
220 
221 #ifdef USE_ASSERT_CHECKING
222  {
223  bool isnull;
224  Oid check;
225 
227  RelationGetDescr(relation),
228  &isnull);
229  Assert(!isnull && check == reltablespace);
230 
232  RelationGetDescr(relation),
233  &isnull);
234  Assert(!isnull && check == relfilenode);
235  }
236 #endif
237  relid = HeapTupleGetOid(ntp);
238  }
239 
240  systable_endscan(scandesc);
241  heap_close(relation, AccessShareLock);
242 
243  /* check for tables that are mapped but not shared */
244  if (!found)
245  relid = RelationMapFilenodeToOid(relfilenode, false);
246  }
247 
248  /*
249  * Only enter entry into cache now, our opening of pg_class could have
250  * caused cache invalidations to be executed which would have deleted a
251  * new entry if we had entered it above.
252  */
253  entry = hash_search(RelfilenodeMapHash, (void *) &key, HASH_ENTER, &found);
254  if (found)
255  elog(ERROR, "corrupted hashtable");
256  entry->relid = relid;
257 
258  return relid;
259 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#define fastgetattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:719
#define RelationGetDescr(relation)
Definition: rel.h:428
#define RelationRelationId
Definition: pg_class.h:29
#define Anum_pg_class_reltablespace
Definition: pg_class.h:110
#define AccessShareLock
Definition: lockdefs.h:36
#define GLOBALTABLESPACE_OID
Definition: pg_tablespace.h:64
#define MemSet(start, val, len)
Definition: c.h:863
#define heap_close(r, l)
Definition: heapam.h:97
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:902
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:328
#define Anum_pg_class_relfilenode
Definition: pg_class.h:109
Oid MyDatabaseTableSpace
Definition: globals.c:79
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:416
static HTAB * RelfilenodeMapHash
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
static ScanKeyData relfilenode_skey[2]
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define InvalidOid
Definition: postgres_ext.h:36
Oid RelationMapFilenodeToOid(Oid filenode, bool shared)
Definition: relmapper.c:199
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Assert(condition)
Definition: c.h:681
static void InitializeRelfilenodeMap(void)
#define elog
Definition: elog.h:219
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
Datum sk_argument
Definition: skey.h:72
#define ClassTblspcRelfilenodeIndexId
Definition: indexing.h:116

Variable Documentation

ScanKeyData relfilenode_skey[2]
static

Definition at line 36 of file relfilenodemap.c.

HTAB* RelfilenodeMapHash = NULL
static

Definition at line 33 of file relfilenodemap.c.