PostgreSQL Source Code  git master
injection_point.h File Reference
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define INJECTION_POINT(name)   ((void) name)
 

Typedefs

typedef void(* InjectionPointCallback) (const char *name)
 

Functions

Size InjectionPointShmemSize (void)
 
void InjectionPointShmemInit (void)
 
void InjectionPointAttach (const char *name, const char *library, const char *function)
 
void InjectionPointRun (const char *name)
 
void InjectionPointDetach (const char *name)
 

Macro Definition Documentation

◆ INJECTION_POINT

#define INJECTION_POINT (   name)    ((void) name)

Definition at line 20 of file injection_point.h.

Typedef Documentation

◆ InjectionPointCallback

typedef void(* InjectionPointCallback) (const char *name)

Definition at line 26 of file injection_point.h.

Function Documentation

◆ InjectionPointAttach()

void InjectionPointAttach ( const char *  name,
const char *  library,
const char *  function 
)

Definition at line 187 of file injection_point.c.

190 {
191 #ifdef USE_INJECTION_POINTS
192  InjectionPointEntry *entry_by_name;
193  bool found;
194 
195  if (strlen(name) >= INJ_NAME_MAXLEN)
196  elog(ERROR, "injection point name %s too long (maximum of %u)",
198  if (strlen(library) >= INJ_LIB_MAXLEN)
199  elog(ERROR, "injection point library %s too long (maximum of %u)",
200  library, INJ_LIB_MAXLEN);
201  if (strlen(function) >= INJ_FUNC_MAXLEN)
202  elog(ERROR, "injection point function %s too long (maximum of %u)",
203  function, INJ_FUNC_MAXLEN);
204 
205  /*
206  * Allocate and register a new injection point. A new point should not
207  * exist. For testing purposes this should be fine.
208  */
209  LWLockAcquire(InjectionPointLock, LW_EXCLUSIVE);
210  entry_by_name = (InjectionPointEntry *)
211  hash_search(InjectionPointHash, name,
212  HASH_ENTER, &found);
213  if (found)
214  {
215  LWLockRelease(InjectionPointLock);
216  elog(ERROR, "injection point \"%s\" already defined", name);
217  }
218 
219  /* Save the entry */
220  strlcpy(entry_by_name->name, name, sizeof(entry_by_name->name));
221  entry_by_name->name[INJ_NAME_MAXLEN - 1] = '\0';
222  strlcpy(entry_by_name->library, library, sizeof(entry_by_name->library));
223  entry_by_name->library[INJ_LIB_MAXLEN - 1] = '\0';
224  strlcpy(entry_by_name->function, function, sizeof(entry_by_name->function));
225  entry_by_name->function[INJ_FUNC_MAXLEN - 1] = '\0';
226 
227  LWLockRelease(InjectionPointLock);
228 
229 #else
230  elog(ERROR, "injection points are not supported by this build");
231 #endif
232 }
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:955
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:224
@ HASH_ENTER
Definition: hsearch.h:114
#define INJ_NAME_MAXLEN
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1170
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1783
@ LW_EXCLUSIVE
Definition: lwlock.h:114
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
const char * name

References elog, ERROR, HASH_ENTER, hash_search(), INJ_NAME_MAXLEN, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), name, and strlcpy().

Referenced by injection_points_attach().

◆ InjectionPointDetach()

void InjectionPointDetach ( const char *  name)

Definition at line 238 of file injection_point.c.

239 {
240 #ifdef USE_INJECTION_POINTS
241  bool found;
242 
243  LWLockAcquire(InjectionPointLock, LW_EXCLUSIVE);
244  hash_search(InjectionPointHash, name, HASH_REMOVE, &found);
245  LWLockRelease(InjectionPointLock);
246 
247  if (!found)
248  elog(ERROR, "injection point \"%s\" not found", name);
249 
250 #else
251  elog(ERROR, "Injection points are not supported by this build");
252 #endif
253 }
@ HASH_REMOVE
Definition: hsearch.h:115

References elog, ERROR, HASH_REMOVE, hash_search(), LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), and name.

Referenced by injection_points_cleanup(), and injection_points_detach().

◆ InjectionPointRun()

void InjectionPointRun ( const char *  name)

Definition at line 262 of file injection_point.c.

263 {
264 #ifdef USE_INJECTION_POINTS
265  InjectionPointEntry *entry_by_name;
266  bool found;
267  InjectionPointCallback injection_callback;
268 
269  LWLockAcquire(InjectionPointLock, LW_SHARED);
270  entry_by_name = (InjectionPointEntry *)
271  hash_search(InjectionPointHash, name,
272  HASH_FIND, &found);
273  LWLockRelease(InjectionPointLock);
274 
275  /*
276  * If not found, do nothing and remove it from the local cache if it
277  * existed there.
278  */
279  if (!found)
280  {
281  injection_point_cache_remove(name);
282  return;
283  }
284 
285  /*
286  * Check if the callback exists in the local cache, to avoid unnecessary
287  * external loads.
288  */
289  injection_callback = injection_point_cache_get(name);
290  if (injection_callback == NULL)
291  {
292  char path[MAXPGPATH];
293 
294  /* not found in local cache, so load and register */
295  snprintf(path, MAXPGPATH, "%s/%s%s", pkglib_path,
296  entry_by_name->library, DLSUFFIX);
297 
298  if (!pg_file_exists(path))
299  elog(ERROR, "could not find library \"%s\" for injection point \"%s\"",
300  path, name);
301 
302  injection_callback = (InjectionPointCallback)
303  load_external_function(path, entry_by_name->function, false, NULL);
304 
305  if (injection_callback == NULL)
306  elog(ERROR, "could not find function \"%s\" in library \"%s\" for injection point \"%s\"",
307  entry_by_name->function, path, name);
308 
309  /* add it to the local cache when found */
310  injection_point_cache_add(name, injection_callback);
311  }
312 
313  injection_callback(name);
314 #else
315  elog(ERROR, "Injection points are not supported by this build");
316 #endif
317 }
void * load_external_function(const char *filename, const char *funcname, bool signalNotFound, void **filehandle)
Definition: dfmgr.c:105
bool pg_file_exists(const char *name)
Definition: fd.c:503
char pkglib_path[MAXPGPATH]
Definition: globals.c:79
@ HASH_FIND
Definition: hsearch.h:113
void(* InjectionPointCallback)(const char *name)
@ LW_SHARED
Definition: lwlock.h:115
#define MAXPGPATH
#define snprintf
Definition: port.h:238

References elog, ERROR, HASH_FIND, hash_search(), load_external_function(), LW_SHARED, LWLockAcquire(), LWLockRelease(), MAXPGPATH, name, pg_file_exists(), pkglib_path, and snprintf.

◆ InjectionPointShmemInit()

void InjectionPointShmemInit ( void  )

Definition at line 167 of file injection_point.c.

168 {
169 #ifdef USE_INJECTION_POINTS
170  HASHCTL info;
171 
172  /* key is a NULL-terminated string */
173  info.keysize = sizeof(char[INJ_NAME_MAXLEN]);
174  info.entrysize = sizeof(InjectionPointEntry);
175  InjectionPointHash = ShmemInitHash("InjectionPoint hash",
176  INJECTION_POINT_HASH_INIT_SIZE,
177  INJECTION_POINT_HASH_MAX_SIZE,
178  &info,
180 #endif
181 }
#define HASH_STRINGS
Definition: hsearch.h:96
#define HASH_ELEM
Definition: hsearch.h:95
#define HASH_FIXED_SIZE
Definition: hsearch.h:105
HTAB * ShmemInitHash(const char *name, long init_size, long max_size, HASHCTL *infoP, int hash_flags)
Definition: shmem.c:332
Size keysize
Definition: hsearch.h:75
Size entrysize
Definition: hsearch.h:76

References HASHCTL::entrysize, HASH_ELEM, HASH_FIXED_SIZE, HASH_STRINGS, INJ_NAME_MAXLEN, HASHCTL::keysize, and ShmemInitHash().

Referenced by CreateOrAttachShmemStructs().

◆ InjectionPointShmemSize()

Size InjectionPointShmemSize ( void  )

Definition at line 150 of file injection_point.c.

151 {
152 #ifdef USE_INJECTION_POINTS
153  Size sz = 0;
154 
155  sz = add_size(sz, hash_estimate_size(INJECTION_POINT_HASH_MAX_SIZE,
156  sizeof(InjectionPointEntry)));
157  return sz;
158 #else
159  return 0;
160 #endif
161 }
size_t Size
Definition: c.h:605
Size hash_estimate_size(long num_entries, Size entrysize)
Definition: dynahash.c:783
Size add_size(Size s1, Size s2)
Definition: shmem.c:493

References add_size(), and hash_estimate_size().

Referenced by CalculateShmemSize().