-
Notifications
You must be signed in to change notification settings - Fork 28
Injection points SMGR v17 #914
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: REL_17_STABLE_neon
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,6 +16,7 @@ | |
| */ | ||
|
|
||
| #include "postgres.h" | ||
| #include <time.h> | ||
|
|
||
| #include "fmgr.h" | ||
| #include "miscadmin.h" | ||
|
|
@@ -59,6 +60,8 @@ typedef struct InjectionPointCondition | |
|
|
||
| /* ID of the process where the injection point is allowed to run */ | ||
| int pid; | ||
| /* probability in [0,1], 1.0 = always */ | ||
| double prob; | ||
| } InjectionPointCondition; | ||
|
|
||
| /* | ||
|
|
@@ -88,13 +91,16 @@ static InjectionPointSharedState *inj_state = NULL; | |
|
|
||
| extern PGDLLEXPORT void injection_error(const char *name, | ||
| const void *private_data); | ||
| extern PGDLLEXPORT void injection_error_prob(const char *name, | ||
| const void *private_data); | ||
| extern PGDLLEXPORT void injection_notice(const char *name, | ||
| const void *private_data); | ||
| extern PGDLLEXPORT void injection_wait(const char *name, | ||
| const void *private_data); | ||
|
|
||
| /* track if injection points attached in this process are linked to it */ | ||
| static bool injection_point_local = false; | ||
| static double action2prob(const char *action, int pos); | ||
|
|
||
| /* | ||
| * Callback for shared memory area initialization. | ||
|
|
@@ -185,6 +191,21 @@ injection_error(const char *name, const void *private_data) | |
| elog(ERROR, "error triggered for injection point %s", name); | ||
| } | ||
|
|
||
| void | ||
| injection_error_prob(const char *name, const void *private_data) | ||
| { | ||
| InjectionPointCondition *condition = (InjectionPointCondition *) private_data; | ||
|
|
||
| if (!injection_point_allowed(condition)) | ||
| return; | ||
|
|
||
| /* Use the probability stored in the condition. */ | ||
| if ((double) rand() / (double) RAND_MAX > condition->prob) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not store condition->prob as fraction of RAND_MAX? That way, we wouldn't have to do expensive double division and compare operations every time this injection point is hit. So, |
||
| return; | ||
|
|
||
| elog(ERROR, "error triggered for injection point %s", name); | ||
| } | ||
|
|
||
| void | ||
| injection_notice(const char *name, const void *private_data) | ||
| { | ||
|
|
@@ -278,6 +299,11 @@ injection_points_attach(PG_FUNCTION_ARGS) | |
| function = "injection_notice"; | ||
| else if (strcmp(action, "wait") == 0) | ||
| function = "injection_wait"; | ||
| else if (strncmp(action, "error-prob-", 11) == 0) | ||
| { | ||
| condition.prob = action2prob(action, 11); | ||
| function = "injection_error_prob"; | ||
| } | ||
|
Comment on lines
+302
to
+306
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why Additionally, couldn't we just pass a pointer to the expected numeric suffix of the action ( |
||
| else | ||
| elog(ERROR, "incorrect action \"%s\" for injection point creation", action); | ||
|
|
||
|
|
@@ -402,3 +428,30 @@ injection_points_detach(PG_FUNCTION_ARGS) | |
|
|
||
| PG_RETURN_VOID(); | ||
| } | ||
|
|
||
| /* | ||
| * Coverts the action name into probability | ||
| */ | ||
| static double action2prob(const char *action, const int pos) | ||
| { | ||
| /* | ||
| * Simple parser: convert "0-01" -> "0.01" then strtod(). | ||
| */ | ||
| const char *p = action + pos; /* points to "0-01" */ | ||
| double prob; | ||
| char *endptr; | ||
| char buf[32]; | ||
| int i, | ||
| j; | ||
|
|
||
| for (i = 0, j = 0; p[i] != '\0' && j < (int) sizeof(buf) - 1; i++) | ||
| { | ||
| buf[j++] = (p[i] == '-') ? '.' : p[i]; | ||
| } | ||
| buf[j] = '\0'; | ||
| errno = 0; | ||
| prob = strtod(buf, &endptr); | ||
| if (errno != 0 || endptr == buf || prob < 0.0 || prob > 1.0) | ||
| elog(ERROR, "invalid probability in action \"%s\"", action); | ||
| return prob; | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's this used for?