PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
evtcache.c File Reference
#include "postgres.h"
#include "access/genam.h"
#include "access/heapam.h"
#include "access/htup_details.h"
#include "catalog/pg_event_trigger.h"
#include "catalog/indexing.h"
#include "catalog/pg_type.h"
#include "commands/trigger.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/catcache.h"
#include "utils/evtcache.h"
#include "utils/inval.h"
#include "utils/memutils.h"
#include "utils/hsearch.h"
#include "utils/rel.h"
#include "utils/snapmgr.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 int DecodeTextArrayToCString (Datum array, char ***cstringp)
 
ListEventCacheLookup (EventTriggerEvent event)
 

Variables

static HTABEventTriggerCache
 
static MemoryContext EventTriggerCacheContext
 
static EventTriggerCacheStateType EventTriggerCacheState = ETCS_NEEDS_REBUILD
 

Enumeration Type Documentation

Enumerator
ETCS_NEEDS_REBUILD 
ETCS_REBUILD_STARTED 
ETCS_VALID 

Definition at line 34 of file evtcache.c.

Function Documentation

static void BuildEventTriggerCache ( void  )
static

Definition at line 78 of file evtcache.c.

References AccessShareLock, ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate(), Anum_pg_event_trigger_evttags, CacheMemoryContext, CacheRegisterSyscacheCallback(), CreateCacheMemoryContext(), DecodeTextArrayToCString(), EventTriggerCacheItem::enabled, HASHCTL::entrysize, ETCS_REBUILD_STARTED, ETCS_VALID, EventTriggerCacheContext, EventTriggerCacheState, EventTriggerNameIndexId, EVENTTRIGGEROID, EventTriggerRelationId, EVT_DDLCommandEnd, EVT_DDLCommandStart, EVT_SQLDrop, EVT_TableRewrite, EventTriggerCacheItem::fnoid, ForwardScanDirection, GETSTRUCT, HASH_BLOBS, HASH_CONTEXT, hash_create(), HASH_ELEM, HASH_ENTER, hash_search(), HASHCTL::hcxt, heap_getattr, HeapTupleIsValid, index_close(), index_open(), InvalidateEventCacheCallback(), HASHCTL::keysize, lappend(), list_make1, MemoryContextResetAndDeleteChildren, MemoryContextSwitchTo(), MemSet, NameStr, EventTriggerCacheItem::ntags, NULL, palloc0(), pg_qsort_strcmp(), qsort, relation_close(), relation_open(), RelationGetDescr, systable_beginscan_ordered(), systable_endscan_ordered(), systable_getnext_ordered(), EventTriggerCacheItem::tag, TRIGGER_DISABLED, and EventTriggerCacheEntry::triggerlist.

Referenced by EventCacheLookup().

79 {
80  HASHCTL ctl;
81  HTAB *cache;
82  MemoryContext oldcontext;
83  Relation rel;
84  Relation irel;
85  SysScanDesc scan;
86 
88  {
89  /*
90  * Free up any memory already allocated in EventTriggerCacheContext.
91  * This can happen either because a previous rebuild failed, or
92  * because an invalidation happened before the rebuild was complete.
93  */
95  }
96  else
97  {
98  /*
99  * This is our first time attempting to build the cache, so we need to
100  * set up the memory context and register a syscache callback to
101  * capture future invalidation events.
102  */
103  if (CacheMemoryContext == NULL)
107  "EventTriggerCache",
111  (Datum) 0);
112  }
113 
114  /* Switch to correct memory context. */
116 
117  /* Prevent the memory context from being nuked while we're rebuilding. */
119 
120  /* Create new hash table. */
121  MemSet(&ctl, 0, sizeof(ctl));
122  ctl.keysize = sizeof(EventTriggerEvent);
123  ctl.entrysize = sizeof(EventTriggerCacheEntry);
125  cache = hash_create("Event Trigger Cache", 32, &ctl,
127 
128  /*
129  * Prepare to scan pg_event_trigger in name order.
130  */
133  scan = systable_beginscan_ordered(rel, irel, NULL, 0, NULL);
134 
135  /*
136  * Build a cache item for each pg_event_trigger tuple, and append each one
137  * to the appropriate cache entry.
138  */
139  for (;;)
140  {
141  HeapTuple tup;
143  char *evtevent;
144  EventTriggerEvent event;
145  EventTriggerCacheItem *item;
146  Datum evttags;
147  bool evttags_isnull;
148  EventTriggerCacheEntry *entry;
149  bool found;
150 
151  /* Get next tuple. */
153  if (!HeapTupleIsValid(tup))
154  break;
155 
156  /* Skip trigger if disabled. */
157  form = (Form_pg_event_trigger) GETSTRUCT(tup);
158  if (form->evtenabled == TRIGGER_DISABLED)
159  continue;
160 
161  /* Decode event name. */
162  evtevent = NameStr(form->evtevent);
163  if (strcmp(evtevent, "ddl_command_start") == 0)
164  event = EVT_DDLCommandStart;
165  else if (strcmp(evtevent, "ddl_command_end") == 0)
166  event = EVT_DDLCommandEnd;
167  else if (strcmp(evtevent, "sql_drop") == 0)
168  event = EVT_SQLDrop;
169  else if (strcmp(evtevent, "table_rewrite") == 0)
170  event = EVT_TableRewrite;
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. */
181  RelationGetDescr(rel), &evttags_isnull);
182  if (!evttags_isnull)
183  {
184  item->ntags = DecodeTextArrayToCString(evttags, &item->tag);
185  qsort(item->tag, item->ntags, sizeof(char *), pg_qsort_strcmp);
186  }
187 
188  /* Add to cache entry. */
189  entry = hash_search(cache, &event, HASH_ENTER, &found);
190  if (found)
191  entry->triggerlist = lappend(entry->triggerlist, item);
192  else
193  entry->triggerlist = list_make1(item);
194  }
195 
196  /* Done with pg_event_trigger scan. */
200 
201  /* Restore previous memory context. */
202  MemoryContextSwitchTo(oldcontext);
203 
204  /* Install new cache. */
205  EventTriggerCache = cache;
206 
207  /*
208  * If the cache has been invalidated since we entered this routine, we
209  * still use and return the cache we just finished constructing, to avoid
210  * infinite loops, but we leave the cache marked stale so that we'll
211  * rebuild it again on next access. Otherwise, we mark the cache valid.
212  */
215 }
static void InvalidateEventCacheCallback(Datum arg, int cacheid, uint32 hashvalue)
Definition: evtcache.c:254
static HTAB * EventTriggerCache
Definition: evtcache.c:47
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define HASH_CONTEXT
Definition: hsearch.h:93
#define HASH_ELEM
Definition: hsearch.h:87
MemoryContext hcxt
Definition: hsearch.h:78
#define RelationGetDescr(relation)
Definition: rel.h:425
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static int DecodeTextArrayToCString(Datum array, char ***cstringp)
Definition: evtcache.c:225
#define AccessShareLock
Definition: lockdefs.h:36
Size entrysize
Definition: hsearch.h:73
static MemoryContext EventTriggerCacheContext
Definition: evtcache.c:48
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1263
#define MemSet(start, val, len)
Definition: c.h:853
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:885
HeapTuple systable_getnext_ordered(SysScanDesc sysscan, ScanDirection direction)
Definition: genam.c:591
EventTriggerEvent
Definition: evtcache.h:19
#define list_make1(x1)
Definition: pg_list.h:133
Definition: dynahash.c:193
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:145
static EventTriggerCacheStateType EventTriggerCacheState
Definition: evtcache.c:49
List * lappend(List *list, void *datum)
Definition: list.c:128
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:769
#define MemoryContextResetAndDeleteChildren(ctx)
Definition: memutils.h:88
#define HASH_BLOBS
Definition: hsearch.h:88
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:440
void CacheRegisterSyscacheCallback(int cacheid, SyscacheCallbackFunction func, Datum arg)
Definition: inval.c:1381
void * palloc0(Size size)
Definition: mcxt.c:920
#define TRIGGER_DISABLED
Definition: trigger.h:112
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:301
uintptr_t Datum
Definition: postgres.h:374
void systable_endscan_ordered(SysScanDesc sysscan)
Definition: genam.c:608
Size keysize
Definition: hsearch.h:72
FormData_pg_event_trigger * Form_pg_event_trigger
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
#define EventTriggerRelationId
#define Anum_pg_event_trigger_evttags
void CreateCacheMemoryContext(void)
Definition: catcache.c:525
int pg_qsort_strcmp(const void *a, const void *b)
Definition: qsort.c:232
#define EventTriggerNameIndexId
Definition: indexing.h:247
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:176
SysScanDesc systable_beginscan_ordered(Relation heapRelation, Relation indexRelation, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:527
#define NameStr(name)
Definition: c.h:495
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1117
#define qsort(a, b, c, d)
Definition: port.h:440
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:151
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
static int DecodeTextArrayToCString ( Datum  array,
char ***  cstringp 
)
static

Definition at line 225 of file evtcache.c.

References ARR_ELEMTYPE, ARR_HASNULL, ARR_NDIM, DatumGetArrayTypeP, deconstruct_array(), elog, ERROR, i, NULL, palloc(), pfree(), TextDatumGetCString, and TEXTOID.

Referenced by BuildEventTriggerCache().

226 {
227  ArrayType *arr = DatumGetArrayTypeP(array);
228  Datum *elems;
229  char **cstring;
230  int i;
231  int nelems;
232 
233  if (ARR_NDIM(arr) != 1 || ARR_HASNULL(arr) || ARR_ELEMTYPE(arr) != TEXTOID)
234  elog(ERROR, "expected 1-D text array");
235  deconstruct_array(arr, TEXTOID, -1, false, 'i', &elems, NULL, &nelems);
236 
237  cstring = palloc(nelems * sizeof(char *));
238  for (i = 0; i < nelems; ++i)
239  cstring[i] = TextDatumGetCString(elems[i]);
240 
241  pfree(elems);
242  *cstringp = cstring;
243  return nelems;
244 }
#define TEXTOID
Definition: pg_type.h:324
void pfree(void *pointer)
Definition: mcxt.c:992
#define ERROR
Definition: elog.h:43
#define ARR_HASNULL(a)
Definition: array.h:272
#define TextDatumGetCString(d)
Definition: builtins.h:91
uintptr_t Datum
Definition: postgres.h:374
#define NULL
Definition: c.h:226
#define ARR_NDIM(a)
Definition: array.h:271
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3475
void * palloc(Size size)
Definition: mcxt.c:891
int i
#define elog
Definition: elog.h:219
#define ARR_ELEMTYPE(a)
Definition: array.h:273
#define DatumGetArrayTypeP(X)
Definition: array.h:242
List* EventCacheLookup ( EventTriggerEvent  event)

Definition at line 64 of file evtcache.c.

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

Referenced by EventTriggerCommonSetup(), and trackDroppedObjectsNeeded().

65 {
67 
70  entry = hash_search(EventTriggerCache, &event, HASH_FIND, NULL);
71  return entry != NULL ? entry->triggerlist : NULL;
72 }
static HTAB * EventTriggerCache
Definition: evtcache.c:47
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:885
static void BuildEventTriggerCache(void)
Definition: evtcache.c:78
static EventTriggerCacheStateType EventTriggerCacheState
Definition: evtcache.c:49
#define NULL
Definition: c.h:226
static void InvalidateEventCacheCallback ( Datum  arg,
int  cacheid,
uint32  hashvalue 
)
static

Definition at line 254 of file evtcache.c.

References ETCS_NEEDS_REBUILD, ETCS_VALID, EventTriggerCacheState, MemoryContextResetAndDeleteChildren, and NULL.

Referenced by BuildEventTriggerCache().

255 {
256  /*
257  * If the cache isn't valid, then there might be a rebuild in progress, so
258  * we can't immediately blow it away. But it's advantageous to do this
259  * when possible, so as to immediately free memory.
260  */
262  {
265  }
266 
267  /* Mark cache for rebuild. */
269 }
static HTAB * EventTriggerCache
Definition: evtcache.c:47
static MemoryContext EventTriggerCacheContext
Definition: evtcache.c:48
static EventTriggerCacheStateType EventTriggerCacheState
Definition: evtcache.c:49
#define MemoryContextResetAndDeleteChildren(ctx)
Definition: memutils.h:88
#define NULL
Definition: c.h:226

Variable Documentation

HTAB* EventTriggerCache
static

Definition at line 47 of file evtcache.c.

MemoryContext EventTriggerCacheContext
static

Definition at line 48 of file evtcache.c.

Referenced by BuildEventTriggerCache().

EventTriggerCacheStateType EventTriggerCacheState = ETCS_NEEDS_REBUILD
static