22#ifdef USE_INJECTION_POINTS
35#define INJ_NAME_MAXLEN 64
36#define INJ_LIB_MAXLEN 128
37#define INJ_FUNC_MAXLEN 128
38#define INJ_PRIVATE_MAXLEN 1024
41typedef struct InjectionPointEntry
64 char library[INJ_LIB_MAXLEN];
71 char private_data[INJ_PRIVATE_MAXLEN];
74#define MAX_INJECTION_POINTS 128
83typedef struct InjectionPointsCtl
86 InjectionPointEntry entries[MAX_INJECTION_POINTS];
95typedef struct InjectionPointCacheEntry
98 char private_data[INJ_PRIVATE_MAXLEN];
108} InjectionPointCacheEntry;
110static HTAB *InjectionPointCache = NULL;
117static InjectionPointCacheEntry *
118injection_point_cache_add(
const char *
name,
122 const void *private_data)
124 InjectionPointCacheEntry *entry;
128 if (InjectionPointCache == NULL)
133 hash_ctl.
entrysize =
sizeof(InjectionPointCacheEntry);
136 InjectionPointCache =
hash_create(
"InjectionPoint cache hash",
137 MAX_INJECTION_POINTS,
142 entry = (InjectionPointCacheEntry *)
147 entry->slot_idx = slot_idx;
148 entry->generation = generation;
150 memcpy(entry->private_data, private_data, INJ_PRIVATE_MAXLEN);
163injection_point_cache_remove(
const char *
name)
176static InjectionPointCacheEntry *
177injection_point_cache_load(InjectionPointEntry *entry,
int slot_idx,
uint64 generation)
180 void *injection_callback_local;
183 entry->library, DLSUFFIX);
186 elog(
ERROR,
"could not find library \"%s\" for injection point \"%s\"",
189 injection_callback_local =
192 if (injection_callback_local == NULL)
193 elog(
ERROR,
"could not find function \"%s\" in library \"%s\" for injection point \"%s\"",
194 entry->function, path, entry->name);
197 return injection_point_cache_add(entry->name,
200 injection_callback_local,
201 entry->private_data);
209static InjectionPointCacheEntry *
210injection_point_cache_get(
const char *
name)
213 InjectionPointCacheEntry *entry;
216 if (InjectionPointCache == NULL)
219 entry = (InjectionPointCacheEntry *)
235#ifdef USE_INJECTION_POINTS
238 sz =
add_size(sz,
sizeof(InjectionPointsCtl));
251#ifdef USE_INJECTION_POINTS
255 sizeof(InjectionPointsCtl),
261 for (
int i = 0;
i < MAX_INJECTION_POINTS;
i++)
276 const void *private_data,
277 int private_data_size)
279#ifdef USE_INJECTION_POINTS
280 InjectionPointEntry *entry;
286 elog(
ERROR,
"injection point name %s too long (maximum of %u characters)",
288 if (strlen(library) >= INJ_LIB_MAXLEN)
289 elog(
ERROR,
"injection point library %s too long (maximum of %u characters)",
290 library, INJ_LIB_MAXLEN - 1);
291 if (strlen(
function) >= INJ_FUNC_MAXLEN)
292 elog(
ERROR,
"injection point function %s too long (maximum of %u characters)",
294 if (private_data_size > INJ_PRIVATE_MAXLEN)
295 elog(
ERROR,
"injection point data too long (maximum of %u bytes)",
306 for (
int idx = 0;
idx < max_inuse;
idx++)
308 entry = &ActiveInjectionPoints->entries[
idx];
310 if (generation % 2 == 0)
319 else if (strcmp(entry->name,
name) == 0)
324 if (max_inuse == MAX_INJECTION_POINTS)
325 elog(
ERROR,
"too many injection points");
326 free_idx = max_inuse;
328 entry = &ActiveInjectionPoints->entries[free_idx];
330 Assert(generation % 2 == 0);
334 strlcpy(entry->library, library,
sizeof(entry->library));
336 if (private_data != NULL)
337 memcpy(entry->private_data, private_data, private_data_size);
342 if (free_idx + 1 > max_inuse)
348 elog(
ERROR,
"injection points are not supported by this build");
360#ifdef USE_INJECTION_POINTS
369 for (
idx = max_inuse - 1;
idx >= 0; --
idx)
371 InjectionPointEntry *entry = &ActiveInjectionPoints->entries[
idx];
375 if (generation % 2 == 0)
378 if (strcmp(entry->name,
name) == 0)
388 if (found &&
idx == max_inuse - 1)
392 InjectionPointEntry *entry = &ActiveInjectionPoints->entries[
idx];
396 if (generation % 2 != 0)
405 elog(
ERROR,
"Injection points are not supported by this build");
410#ifdef USE_INJECTION_POINTS
417static InjectionPointCacheEntry *
418InjectionPointCacheRefresh(
const char *
name)
422 InjectionPointEntry local_copy;
423 InjectionPointCacheEntry *cached;
434 if (InjectionPointCache)
437 InjectionPointCache = NULL;
446 cached = injection_point_cache_get(
name);
449 int idx = cached->slot_idx;
450 InjectionPointEntry *entry = &ActiveInjectionPoints->entries[
idx];
457 injection_point_cache_remove(
name);
470 namelen = strlen(
name);
471 for (
int idx = 0;
idx < max_inuse;
idx++)
473 InjectionPointEntry *entry = &ActiveInjectionPoints->entries[
idx];
482 if (generation % 2 == 0)
487 if (memcmp(entry->name,
name, namelen + 1) != 0)
496 memcpy(&local_copy, entry,
sizeof(InjectionPointEntry));
514 return injection_point_cache_load(&local_copy,
idx, generation);
530#ifdef USE_INJECTION_POINTS
531 InjectionPointCacheRefresh(
name);
533 elog(
ERROR,
"Injection points are not supported by this build");
543#ifdef USE_INJECTION_POINTS
544 InjectionPointCacheEntry *cache_entry;
546 cache_entry = InjectionPointCacheRefresh(
name);
548 cache_entry->callback(
name, cache_entry->private_data,
arg);
550 elog(
ERROR,
"Injection points are not supported by this build");
560#ifdef USE_INJECTION_POINTS
561 InjectionPointCacheEntry *cache_entry;
563 cache_entry = injection_point_cache_get(
name);
565 cache_entry->callback(
name, cache_entry->private_data,
arg);
567 elog(
ERROR,
"Injection points are not supported by this build");
577#ifdef USE_INJECTION_POINTS
578 return InjectionPointCacheRefresh(
name) != NULL;
580 elog(
ERROR,
"Injection points are not supported by this build");
593#ifdef USE_INJECTION_POINTS
603 InjectionPointEntry *entry;
607 entry = &ActiveInjectionPoints->entries[
idx];
611 if (generation % 2 == 0)
618 inj_points =
lappend(inj_points, inj_point);
626 elog(
ERROR,
"Injection points are not supported by this build");
Datum idx(PG_FUNCTION_ARGS)
static void pg_atomic_write_u64(volatile pg_atomic_uint64 *ptr, uint64 val)
#define pg_read_barrier()
static void pg_atomic_init_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
#define pg_write_barrier()
static void pg_atomic_write_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
static void pg_atomic_init_u64(volatile pg_atomic_uint64 *ptr, uint64 val)
static uint64 pg_atomic_read_u64(volatile pg_atomic_uint64 *ptr)
#define PG_USED_FOR_ASSERTS_ONLY
void * load_external_function(const char *filename, const char *funcname, bool signalNotFound, void **filehandle)
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
HTAB * hash_create(const char *tabname, int64 nelem, const HASHCTL *info, int flags)
void hash_destroy(HTAB *hashp)
bool pg_file_exists(const char *name)
#define palloc0_object(type)
char pkglib_path[MAXPGPATH]
Assert(PointerIsAligned(start, uint64))
void InjectionPointShmemInit(void)
Size InjectionPointShmemSize(void)
void InjectionPointLoad(const char *name)
bool InjectionPointDetach(const char *name)
List * InjectionPointList(void)
void InjectionPointRun(const char *name, void *arg)
bool IsInjectionPointAttached(const char *name)
void InjectionPointAttach(const char *name, const char *library, const char *function, const void *private_data, int private_data_size)
void InjectionPointCached(const char *name, void *arg)
void(* InjectionPointCallback)(const char *name, const void *private_data, void *arg)
List * lappend(List *list, void *datum)
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
void LWLockRelease(LWLock *lock)
char * pstrdup(const char *in)
MemoryContext TopMemoryContext
on_exit_nicely_callback function
size_t strlcpy(char *dst, const char *src, size_t siz)
Size add_size(Size s1, Size s2)
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
static void callback(struct sockaddr *addr, struct sockaddr *mask, void *unused)