31 #ifdef USE_INJECTION_POINTS
34 #define INJ_NAME_MAXLEN 64
35 #define INJ_LIB_MAXLEN 128
36 #define INJ_FUNC_MAXLEN 128
37 #define INJ_PRIVATE_MAXLEN 1024
40 typedef struct InjectionPointEntry
63 char library[INJ_LIB_MAXLEN];
64 char function[INJ_FUNC_MAXLEN];
70 char private_data[INJ_PRIVATE_MAXLEN];
71 } InjectionPointEntry;
73 #define MAX_INJECTION_POINTS 128
82 typedef struct InjectionPointsCtl
85 InjectionPointEntry entries[MAX_INJECTION_POINTS];
94 typedef struct InjectionPointCacheEntry
97 char private_data[INJ_PRIVATE_MAXLEN];
107 } InjectionPointCacheEntry;
109 static HTAB *InjectionPointCache = NULL;
116 static InjectionPointCacheEntry *
117 injection_point_cache_add(
const char *
name,
121 const void *private_data)
123 InjectionPointCacheEntry *entry;
127 if (InjectionPointCache == NULL)
132 hash_ctl.
entrysize =
sizeof(InjectionPointCacheEntry);
135 InjectionPointCache =
hash_create(
"InjectionPoint cache hash",
136 MAX_INJECTION_POINTS,
141 entry = (InjectionPointCacheEntry *)
146 entry->slot_idx = slot_idx;
147 entry->generation = generation;
149 memcpy(entry->private_data, private_data, INJ_PRIVATE_MAXLEN);
162 injection_point_cache_remove(
const char *
name)
175 static InjectionPointCacheEntry *
176 injection_point_cache_load(InjectionPointEntry *entry,
int slot_idx, uint64 generation)
179 void *injection_callback_local;
182 entry->library, DLSUFFIX);
185 elog(
ERROR,
"could not find library \"%s\" for injection point \"%s\"",
188 injection_callback_local = (
void *)
191 if (injection_callback_local == NULL)
192 elog(
ERROR,
"could not find function \"%s\" in library \"%s\" for injection point \"%s\"",
193 entry->function, path, entry->name);
196 return injection_point_cache_add(entry->name,
199 injection_callback_local,
200 entry->private_data);
208 static InjectionPointCacheEntry *
209 injection_point_cache_get(
const char *
name)
212 InjectionPointCacheEntry *entry;
215 if (InjectionPointCache == NULL)
218 entry = (InjectionPointCacheEntry *)
234 #ifdef USE_INJECTION_POINTS
237 sz =
add_size(sz,
sizeof(InjectionPointsCtl));
250 #ifdef USE_INJECTION_POINTS
254 sizeof(InjectionPointsCtl),
260 for (
int i = 0;
i < MAX_INJECTION_POINTS;
i++)
274 const char *
function,
275 const void *private_data,
276 int private_data_size)
278 #ifdef USE_INJECTION_POINTS
279 InjectionPointEntry *entry;
285 elog(
ERROR,
"injection point name %s too long (maximum of %u)",
287 if (strlen(library) >= INJ_LIB_MAXLEN)
288 elog(
ERROR,
"injection point library %s too long (maximum of %u)",
289 library, INJ_LIB_MAXLEN);
290 if (strlen(
function) >= INJ_FUNC_MAXLEN)
291 elog(
ERROR,
"injection point function %s too long (maximum of %u)",
292 function, INJ_FUNC_MAXLEN);
293 if (private_data_size >= INJ_PRIVATE_MAXLEN)
294 elog(
ERROR,
"injection point data too long (maximum of %u)",
305 for (
int idx = 0;
idx < max_inuse;
idx++)
307 entry = &ActiveInjectionPoints->entries[
idx];
309 if (generation % 2 == 0)
318 else if (strcmp(entry->name,
name) == 0)
323 if (max_inuse == MAX_INJECTION_POINTS)
324 elog(
ERROR,
"too many injection points");
325 free_idx = max_inuse;
327 entry = &ActiveInjectionPoints->entries[free_idx];
329 Assert(generation % 2 == 0);
334 strlcpy(entry->library, library,
sizeof(entry->library));
335 entry->library[INJ_LIB_MAXLEN - 1] =
'\0';
336 strlcpy(entry->function,
function,
sizeof(entry->function));
337 entry->function[INJ_FUNC_MAXLEN - 1] =
'\0';
338 if (private_data != NULL)
339 memcpy(entry->private_data, private_data, private_data_size);
344 if (free_idx + 1 > max_inuse)
350 elog(
ERROR,
"injection points are not supported by this build");
362 #ifdef USE_INJECTION_POINTS
371 for (
idx = max_inuse - 1;
idx >= 0; --
idx)
373 InjectionPointEntry *entry = &ActiveInjectionPoints->entries[
idx];
377 if (generation % 2 == 0)
380 if (strcmp(entry->name,
name) == 0)
390 if (found &&
idx == max_inuse - 1)
394 InjectionPointEntry *entry = &ActiveInjectionPoints->entries[
idx];
398 if (generation % 2 != 0)
407 elog(
ERROR,
"Injection points are not supported by this build");
412 #ifdef USE_INJECTION_POINTS
419 static InjectionPointCacheEntry *
420 InjectionPointCacheRefresh(
const char *
name)
424 InjectionPointEntry local_copy;
425 InjectionPointCacheEntry *cached;
436 if (InjectionPointCache)
439 InjectionPointCache = NULL;
448 cached = injection_point_cache_get(
name);
451 int idx = cached->slot_idx;
452 InjectionPointEntry *entry = &ActiveInjectionPoints->entries[
idx];
459 injection_point_cache_remove(
name);
472 namelen = strlen(
name);
473 for (
int idx = 0;
idx < max_inuse;
idx++)
475 InjectionPointEntry *entry = &ActiveInjectionPoints->entries[
idx];
484 if (generation % 2 == 0)
489 if (memcmp(entry->name,
name, namelen + 1) != 0)
498 memcpy(&local_copy, entry,
sizeof(InjectionPointEntry));
516 return injection_point_cache_load(&local_copy,
idx, generation);
532 #ifdef USE_INJECTION_POINTS
533 InjectionPointCacheRefresh(
name);
535 elog(
ERROR,
"Injection points are not supported by this build");
545 #ifdef USE_INJECTION_POINTS
546 InjectionPointCacheEntry *cache_entry;
548 cache_entry = InjectionPointCacheRefresh(
name);
550 cache_entry->callback(
name, cache_entry->private_data);
552 elog(
ERROR,
"Injection points are not supported by this build");
562 #ifdef USE_INJECTION_POINTS
563 InjectionPointCacheEntry *cache_entry;
565 cache_entry = injection_point_cache_get(
name);
567 cache_entry->callback(
name, cache_entry->private_data);
569 elog(
ERROR,
"Injection points are not supported by this build");
579 #ifdef USE_INJECTION_POINTS
580 return InjectionPointCacheRefresh(
name) != NULL;
582 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
#define Assert(condition)
void * load_external_function(const char *filename, const char *funcname, bool signalNotFound, void **filehandle)
void hash_destroy(HTAB *hashp)
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
bool pg_file_exists(const char *name)
char pkglib_path[MAXPGPATH]
void InjectionPointShmemInit(void)
Size InjectionPointShmemSize(void)
void InjectionPointCached(const char *name)
void InjectionPointLoad(const char *name)
bool InjectionPointDetach(const char *name)
void InjectionPointRun(const char *name)
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(* InjectionPointCallback)(const char *name, const void *private_data)
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
void LWLockRelease(LWLock *lock)
MemoryContext TopMemoryContext
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)