PostgreSQL Source Code  git master
evtcache.c File Reference
#include "postgres.h"
#include "access/genam.h"
#include "access/htup_details.h"
#include "access/relation.h"
#include "catalog/pg_event_trigger.h"
#include "catalog/pg_type.h"
#include "commands/trigger.h"
#include "tcop/cmdtag.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/catcache.h"
#include "utils/evtcache.h"
#include "utils/hsearch.h"
#include "utils/inval.h"
#include "utils/memutils.h"
#include "utils/rel.h"
#include "utils/syscache.h"
Include dependency graph for evtcache.c:

Go to the source code of this file.

Data Structures

struct  EventTriggerCacheEntry
 

Enumerations

enum  EventTriggerCacheStateType { ETCS_NEEDS_REBUILD , ETCS_REBUILD_STARTED , ETCS_VALID }
 

Functions

static void BuildEventTriggerCache (void)
 
static void InvalidateEventCacheCallback (Datum arg, int cacheid, uint32 hashvalue)
 
static BitmapsetDecodeTextArrayToBitmapset (Datum array)
 
ListEventCacheLookup (EventTriggerEvent event)
 

Variables

static HTABEventTriggerCache
 
static MemoryContext EventTriggerCacheContext
 
static EventTriggerCacheStateType EventTriggerCacheState = ETCS_NEEDS_REBUILD
 

Enumeration Type Documentation

◆ EventTriggerCacheStateType

Enumerator
ETCS_NEEDS_REBUILD 
ETCS_REBUILD_STARTED 
ETCS_VALID 

Definition at line 33 of file evtcache.c.

34 {
37  ETCS_VALID,
EventTriggerCacheStateType
Definition: evtcache.c:34
@ ETCS_REBUILD_STARTED
Definition: evtcache.c:36
@ ETCS_NEEDS_REBUILD
Definition: evtcache.c:35
@ ETCS_VALID
Definition: evtcache.c:37

Function Documentation

◆ BuildEventTriggerCache()

static void BuildEventTriggerCache ( void  )
static

Definition at line 77 of file evtcache.c.

78 {
79  HASHCTL ctl;
80  HTAB *cache;
81  MemoryContext oldcontext;
82  Relation rel;
83  Relation irel;
84  SysScanDesc scan;
85 
86  if (EventTriggerCacheContext != NULL)
87  {
88  /*
89  * Free up any memory already allocated in EventTriggerCacheContext.
90  * This can happen either because a previous rebuild failed, or
91  * because an invalidation happened before the rebuild was complete.
92  */
94  }
95  else
96  {
97  /*
98  * This is our first time attempting to build the cache, so we need to
99  * set up the memory context and register a syscache callback to
100  * capture future invalidation events.
101  */
102  if (CacheMemoryContext == NULL)
106  "EventTriggerCache",
108  CacheRegisterSyscacheCallback(EVENTTRIGGEROID,
110  (Datum) 0);
111  }
112 
113  /* Switch to correct memory context. */
115 
116  /* Prevent the memory context from being nuked while we're rebuilding. */
118 
119  /* Create new hash table. */
120  ctl.keysize = sizeof(EventTriggerEvent);
121  ctl.entrysize = sizeof(EventTriggerCacheEntry);
123  cache = hash_create("EventTriggerCacheHash", 32, &ctl,
125 
126  /*
127  * Prepare to scan pg_event_trigger in name order.
128  */
129  rel = relation_open(EventTriggerRelationId, AccessShareLock);
130  irel = index_open(EventTriggerNameIndexId, AccessShareLock);
131  scan = systable_beginscan_ordered(rel, irel, NULL, 0, NULL);
132 
133  /*
134  * Build a cache item for each pg_event_trigger tuple, and append each one
135  * to the appropriate cache entry.
136  */
137  for (;;)
138  {
139  HeapTuple tup;
141  char *evtevent;
142  EventTriggerEvent event;
143  EventTriggerCacheItem *item;
144  Datum evttags;
145  bool evttags_isnull;
146  EventTriggerCacheEntry *entry;
147  bool found;
148 
149  /* Get next tuple. */
151  if (!HeapTupleIsValid(tup))
152  break;
153 
154  /* Skip trigger if disabled. */
155  form = (Form_pg_event_trigger) GETSTRUCT(tup);
156  if (form->evtenabled == TRIGGER_DISABLED)
157  continue;
158 
159  /* Decode event name. */
160  evtevent = NameStr(form->evtevent);
161  if (strcmp(evtevent, "ddl_command_start") == 0)
162  event = EVT_DDLCommandStart;
163  else if (strcmp(evtevent, "ddl_command_end") == 0)
164  event = EVT_DDLCommandEnd;
165  else if (strcmp(evtevent, "sql_drop") == 0)
166  event = EVT_SQLDrop;
167  else if (strcmp(evtevent, "table_rewrite") == 0)
168  event = EVT_TableRewrite;
169  else if (strcmp(evtevent, "login") == 0)
170  event = EVT_Login;
171  else
172  continue;
173 
174  /* Allocate new cache item. */
175  item = palloc0(sizeof(EventTriggerCacheItem));
176  item->fnoid = form->evtfoid;
177  item->enabled = form->evtenabled;
178 
179  /* Decode and sort tags array. */
180  evttags = heap_getattr(tup, Anum_pg_event_trigger_evttags,
181  RelationGetDescr(rel), &evttags_isnull);
182  if (!evttags_isnull)
183  item->tagset = DecodeTextArrayToBitmapset(evttags);
184 
185  /* Add to cache entry. */
186  entry = hash_search(cache, &event, HASH_ENTER, &found);
187  if (found)
188  entry->triggerlist = lappend(entry->triggerlist, item);
189  else
190  entry->triggerlist = list_make1(item);
191  }
192 
193  /* Done with pg_event_trigger scan. */
197 
198  /* Restore previous memory context. */
199  MemoryContextSwitchTo(oldcontext);
200 
201  /* Install new cache. */
202  EventTriggerCache = cache;
203 
204  /*
205  * If the cache has been invalidated since we entered this routine, we
206  * still use and return the cache we just finished constructing, to avoid
207  * infinite loops, but we leave the cache marked stale so that we'll
208  * rebuild it again on next access. Otherwise, we mark the cache valid.
209  */
212 }
#define NameStr(name)
Definition: c.h:746
void CreateCacheMemoryContext(void)
Definition: catcache.c:679
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:955
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:352
static void InvalidateEventCacheCallback(Datum arg, int cacheid, uint32 hashvalue)
Definition: evtcache.c:255
static MemoryContext EventTriggerCacheContext
Definition: evtcache.c:47
static Bitmapset * DecodeTextArrayToBitmapset(Datum array)
Definition: evtcache.c:222
static HTAB * EventTriggerCache
Definition: evtcache.c:46
static EventTriggerCacheStateType EventTriggerCacheState
Definition: evtcache.c:48
EventTriggerEvent
Definition: evtcache.h:21
@ EVT_SQLDrop
Definition: evtcache.h:24
@ EVT_Login
Definition: evtcache.h:26
@ EVT_DDLCommandEnd
Definition: evtcache.h:23
@ EVT_DDLCommandStart
Definition: evtcache.h:22
@ EVT_TableRewrite
Definition: evtcache.h:25
SysScanDesc systable_beginscan_ordered(Relation heapRelation, Relation indexRelation, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:643
void systable_endscan_ordered(SysScanDesc sysscan)
Definition: genam.c:735
HeapTuple systable_getnext_ordered(SysScanDesc sysscan, ScanDirection direction)
Definition: genam.c:710
@ HASH_ENTER
Definition: hsearch.h:114
#define HASH_CONTEXT
Definition: hsearch.h:102
#define HASH_ELEM
Definition: hsearch.h:95
#define HASH_BLOBS
Definition: hsearch.h:97
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: htup_details.h:792
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:177
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:133
void CacheRegisterSyscacheCallback(int cacheid, SyscacheCallbackFunction func, Datum arg)
Definition: inval.c:1516
List * lappend(List *list, void *datum)
Definition: list.c:339
#define AccessShareLock
Definition: lockdefs.h:36
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:383
void * palloc0(Size size)
Definition: mcxt.c:1346
MemoryContext CacheMemoryContext
Definition: mcxt.c:152
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160
FormData_pg_event_trigger * Form_pg_event_trigger
#define list_make1(x1)
Definition: pg_list.h:212
uintptr_t Datum
Definition: postgres.h:64
MemoryContextSwitchTo(old_ctx)
tree ctl
Definition: radixtree.h:1851
#define RelationGetDescr(relation)
Definition: rel.h:531
@ ForwardScanDirection
Definition: sdir.h:28
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:205
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:47
Bitmapset * tagset
Definition: evtcache.h:33
Definition: dynahash.c:220
#define TRIGGER_DISABLED
Definition: trigger.h:152

References AccessShareLock, ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, CacheMemoryContext, CacheRegisterSyscacheCallback(), CreateCacheMemoryContext(), ctl, DecodeTextArrayToBitmapset(), EventTriggerCacheItem::enabled, ETCS_REBUILD_STARTED, ETCS_VALID, EventTriggerCache, EventTriggerCacheContext, EventTriggerCacheState, EVT_DDLCommandEnd, EVT_DDLCommandStart, EVT_Login, EVT_SQLDrop, EVT_TableRewrite, EventTriggerCacheItem::fnoid, ForwardScanDirection, GETSTRUCT, HASH_BLOBS, HASH_CONTEXT, hash_create(), HASH_ELEM, HASH_ENTER, hash_search(), heap_getattr(), HeapTupleIsValid, index_close(), index_open(), InvalidateEventCacheCallback(), lappend(), list_make1, MemoryContextReset(), MemoryContextSwitchTo(), NameStr, palloc0(), relation_close(), relation_open(), RelationGetDescr, systable_beginscan_ordered(), systable_endscan_ordered(), systable_getnext_ordered(), EventTriggerCacheItem::tagset, TRIGGER_DISABLED, and EventTriggerCacheEntry::triggerlist.

Referenced by EventCacheLookup().

◆ DecodeTextArrayToBitmapset()

static Bitmapset * DecodeTextArrayToBitmapset ( Datum  array)
static

Definition at line 222 of file evtcache.c.

223 {
224  ArrayType *arr = DatumGetArrayTypeP(array);
225  Datum *elems;
226  Bitmapset *bms;
227  int i;
228  int nelems;
229 
230  if (ARR_NDIM(arr) != 1 || ARR_HASNULL(arr) || ARR_ELEMTYPE(arr) != TEXTOID)
231  elog(ERROR, "expected 1-D text array");
232  deconstruct_array_builtin(arr, TEXTOID, &elems, NULL, &nelems);
233 
234  for (bms = NULL, i = 0; i < nelems; ++i)
235  {
236  char *str = TextDatumGetCString(elems[i]);
237 
238  bms = bms_add_member(bms, GetCommandTagEnum(str));
239  pfree(str);
240  }
241 
242  pfree(elems);
243 
244  return bms;
245 }
#define ARR_NDIM(a)
Definition: array.h:290
#define DatumGetArrayTypeP(X)
Definition: array.h:261
#define ARR_ELEMTYPE(a)
Definition: array.h:292
#define ARR_HASNULL(a)
Definition: array.h:291
void deconstruct_array_builtin(ArrayType *array, Oid elmtype, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3678
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:815
#define TextDatumGetCString(d)
Definition: builtins.h:98
CommandTag GetCommandTagEnum(const char *commandname)
Definition: cmdtag.c:83
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:224
const char * str
int i
Definition: isn.c:73
void pfree(void *pointer)
Definition: mcxt.c:1520

References ARR_ELEMTYPE, ARR_HASNULL, ARR_NDIM, bms_add_member(), DatumGetArrayTypeP, deconstruct_array_builtin(), elog, ERROR, GetCommandTagEnum(), i, pfree(), str, and TextDatumGetCString.

Referenced by BuildEventTriggerCache().

◆ EventCacheLookup()

List* EventCacheLookup ( EventTriggerEvent  event)

Definition at line 63 of file evtcache.c.

64 {
66 
69  entry = hash_search(EventTriggerCache, &event, HASH_FIND, NULL);
70  return entry != NULL ? entry->triggerlist : NIL;
71 }
static void BuildEventTriggerCache(void)
Definition: evtcache.c:77
@ HASH_FIND
Definition: hsearch.h:113
#define NIL
Definition: pg_list.h:68

References BuildEventTriggerCache(), ETCS_VALID, EventTriggerCache, EventTriggerCacheState, HASH_FIND, hash_search(), NIL, and EventTriggerCacheEntry::triggerlist.

Referenced by EventTriggerCommonSetup(), and trackDroppedObjectsNeeded().

◆ InvalidateEventCacheCallback()

static void InvalidateEventCacheCallback ( Datum  arg,
int  cacheid,
uint32  hashvalue 
)
static

Definition at line 255 of file evtcache.c.

256 {
257  /*
258  * If the cache isn't valid, then there might be a rebuild in progress, so
259  * we can't immediately blow it away. But it's advantageous to do this
260  * when possible, so as to immediately free memory.
261  */
263  {
265  EventTriggerCache = NULL;
266  }
267 
268  /* Mark cache for rebuild. */
270 }

References ETCS_NEEDS_REBUILD, ETCS_VALID, EventTriggerCache, EventTriggerCacheContext, EventTriggerCacheState, and MemoryContextReset().

Referenced by BuildEventTriggerCache().

Variable Documentation

◆ EventTriggerCache

HTAB* EventTriggerCache
static

◆ EventTriggerCacheContext

MemoryContext EventTriggerCacheContext
static

Definition at line 47 of file evtcache.c.

Referenced by BuildEventTriggerCache(), and InvalidateEventCacheCallback().

◆ EventTriggerCacheState

EventTriggerCacheStateType EventTriggerCacheState = ETCS_NEEDS_REBUILD
static