Add InjectionPointList() to retrieve list of injection points
authorMichael Paquier <[email protected]>
Wed, 2 Jul 2025 23:41:25 +0000 (08:41 +0900)
committerMichael Paquier <[email protected]>
Wed, 2 Jul 2025 23:41:25 +0000 (08:41 +0900)
This routine has come as a useful piece to be able to know the list of
injection points currently attached in a system.  One area would be to
use it in a set-returning function, or just let out-of-core code play
with it.

This hides the internals of the shared memory array lookup holding the
information about the injection points (point name, library and function
name), allocating the result in a palloc'd List consumable by the
caller.

Reviewed-by: Jeff Davis <[email protected]>
Reviewed-by: Hayato Kuroda <[email protected]>
Reviewed-by: Rahila Syed <[email protected]>
Discussion: https://postgr.es/m/[email protected]
Discussion: https://postgr.es/m/[email protected]

src/backend/utils/misc/injection_point.c
src/include/utils/injection_point.h
src/tools/pgindent/typedefs.list

index f58ebc8ee522d2262600965a9478d83a55c4cc30..83b887b69780731d164fe68d5878b2405993a19c 100644 (file)
@@ -584,3 +584,49 @@ IsInjectionPointAttached(const char *name)
    return false;               /* silence compiler */
 #endif
 }
+
+/*
+ * Retrieve a list of all the injection points currently attached.
+ *
+ * This list is palloc'd in the current memory context.
+ */
+List *
+InjectionPointList(void)
+{
+#ifdef USE_INJECTION_POINTS
+   List       *inj_points = NIL;
+   uint32      max_inuse;
+
+   LWLockAcquire(InjectionPointLock, LW_SHARED);
+
+   max_inuse = pg_atomic_read_u32(&ActiveInjectionPoints->max_inuse);
+
+   for (uint32 idx = 0; idx < max_inuse; idx++)
+   {
+       InjectionPointEntry *entry;
+       InjectionPointData *inj_point;
+       uint64      generation;
+
+       entry = &ActiveInjectionPoints->entries[idx];
+       generation = pg_atomic_read_u64(&entry->generation);
+
+       /* skip free slots */
+       if (generation % 2 == 0)
+           continue;
+
+       inj_point = (InjectionPointData *) palloc0(sizeof(InjectionPointData));
+       inj_point->name = pstrdup(entry->name);
+       inj_point->library = pstrdup(entry->library);
+       inj_point->function = pstrdup(entry->function);
+       inj_points = lappend(inj_points, inj_point);
+   }
+
+   LWLockRelease(InjectionPointLock);
+
+   return inj_points;
+
+#else
+   elog(ERROR, "Injection points are not supported by this build");
+   return NIL;                 /* keep compiler quiet */
+#endif
+}
index a37958e1835fd144dac262aad5eeaf7352e2cefa..fd5bc061b7bdf5ac84c5dce13aded933f2124207 100644 (file)
 #ifndef INJECTION_POINT_H
 #define INJECTION_POINT_H
 
+#include "nodes/pg_list.h"
+
+/*
+ * Injection point data, used when retrieving a list of all the attached
+ * injection points.
+ */
+typedef struct InjectionPointData
+{
+   const char *name;
+   const char *library;
+   const char *function;
+} InjectionPointData;
+
 /*
  * Injection points require --enable-injection-points.
  */
@@ -47,6 +60,9 @@ extern void InjectionPointCached(const char *name, void *arg);
 extern bool IsInjectionPointAttached(const char *name);
 extern bool InjectionPointDetach(const char *name);
 
+/* Get the current set of injection points attached */
+extern List *InjectionPointList(void);
+
 #ifdef EXEC_BACKEND
 extern PGDLLIMPORT struct InjectionPointsCtl *ActiveInjectionPoints;
 #endif
index baf636a7643975a52bad4033e5c94a2f7f8d0d3a..66c5782688a23978891f59eb6d38d29bb8155684 100644 (file)
@@ -1291,6 +1291,7 @@ InjectionPointCacheEntry
 InjectionPointCallback
 InjectionPointCondition
 InjectionPointConditionType
+InjectionPointData
 InjectionPointEntry
 InjectionPointSharedState
 InjectionPointsCtl