Skip to content

Commit 9938d11

Browse files
committed
pgbench: doExecuteCommand -> executeMetaCommand
The new function is only in charge of meta commands, not SQL commands. This change makes the code a little clearer: now all the state changes are effected by advanceConnectionState. It also removes one indent level, which makes the diff look bulkier than it really is. Author: Fabien Coelho Reviewed-by: Kirk Jamison Discussion: https://postgr.es/m/alpine.DEB.2.21.1811240904500.12627@lancre
1 parent a51cc7e commit 9938d11

File tree

1 file changed

+151
-148
lines changed

1 file changed

+151
-148
lines changed

src/bin/pgbench/pgbench.c

Lines changed: 151 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -607,8 +607,8 @@ static void setIntValue(PgBenchValue *pv, int64 ival);
607607
static void setDoubleValue(PgBenchValue *pv, double dval);
608608
static bool evaluateExpr(TState *thread, CState *st, PgBenchExpr *expr,
609609
PgBenchValue *retval);
610-
static instr_time doExecuteCommand(TState *thread, CState *st,
611-
instr_time now);
610+
static ConnectionStateEnum executeMetaCommand(TState *thread, CState *st,
611+
instr_time *now);
612612
static void doLog(TState *thread, CState *st,
613613
StatsData *agg, bool skipped, double latency, double lag);
614614
static void processXactStats(TState *thread, CState *st, instr_time *now,
@@ -802,7 +802,7 @@ strtoint64(const char *str, bool errorOK, int64 *result)
802802
invalid_syntax:
803803
if (!errorOK)
804804
fprintf(stderr,
805-
"invalid input syntax for type bigint: \"%s\"\n",str);
805+
"invalid input syntax for type bigint: \"%s\"\n", str);
806806
return false;
807807
}
808808

@@ -827,7 +827,7 @@ strtodouble(const char *str, bool errorOK, double *dv)
827827
{
828828
if (!errorOK)
829829
fprintf(stderr,
830-
"invalid input syntax for type double: \"%s\"\n",str);
830+
"invalid input syntax for type double: \"%s\"\n", str);
831831
return false;
832832
}
833833
return true;
@@ -3012,6 +3012,8 @@ advanceConnectionState(TState *thread, CState *st, StatsData *agg)
30123012
*/
30133013
for (;;)
30143014
{
3015+
Command *command;
3016+
30153017
switch (st->state)
30163018
{
30173019
/* Select transaction (script) to run. */
@@ -3151,8 +3153,10 @@ advanceConnectionState(TState *thread, CState *st, StatsData *agg)
31513153
* Send a command to server (or execute a meta-command)
31523154
*/
31533155
case CSTATE_START_COMMAND:
3156+
command = sql_script[st->use_file].commands[st->command];
3157+
31543158
/* Transition to script end processing if done */
3155-
if (sql_script[st->use_file].commands[st->command] == NULL)
3159+
if (command == NULL)
31563160
{
31573161
st->state = CSTATE_END_TX;
31583162
break;
@@ -3164,7 +3168,28 @@ advanceConnectionState(TState *thread, CState *st, StatsData *agg)
31643168
INSTR_TIME_SET_CURRENT_LAZY(now);
31653169
st->stmt_begin = now;
31663170
}
3167-
now = doExecuteCommand(thread, st, now);
3171+
3172+
/* Execute the command */
3173+
if (command->type == SQL_COMMAND)
3174+
{
3175+
if (!sendCommand(st, command))
3176+
{
3177+
commandFailed(st, "SQL", "SQL command send failed");
3178+
st->state = CSTATE_ABORTED;
3179+
}
3180+
else
3181+
st->state = CSTATE_WAIT_RESULT;
3182+
}
3183+
else if (command->type == META_COMMAND)
3184+
{
3185+
/*-----
3186+
* Possible state changes when executing meta commands:
3187+
* - on errors CSTATE_ABORTED
3188+
* - on sleep CSTATE_SLEEP
3189+
* - else CSTATE_END_COMMAND
3190+
*/
3191+
st->state = executeMetaCommand(thread, st, &now);
3192+
}
31683193

31693194
/*
31703195
* We're now waiting for an SQL command to complete, or
@@ -3237,7 +3262,8 @@ advanceConnectionState(TState *thread, CState *st, StatsData *agg)
32373262
case IFSTATE_IGNORED:
32383263
case IFSTATE_ELSE_FALSE:
32393264
if (command->meta == META_IF)
3240-
conditional_stack_push(st->cstack, IFSTATE_IGNORED);
3265+
conditional_stack_push(st->cstack,
3266+
IFSTATE_IGNORED);
32413267
else if (command->meta == META_ENDIF)
32423268
{
32433269
Assert(!conditional_stack_empty(st->cstack));
@@ -3387,179 +3413,155 @@ advanceConnectionState(TState *thread, CState *st, StatsData *agg)
33873413
}
33883414

33893415
/*
3390-
* Subroutine for advanceConnectionState -- execute or initiate the current
3391-
* command, and transition to next state appropriately.
3416+
* Subroutine for advanceConnectionState -- initiate or execute the current
3417+
* meta command, and return the next state to set.
33923418
*
3393-
* Returns an updated timestamp from 'now', used to update 'now' at callsite.
3419+
* *now is updated to the current time, unless the command is expected to
3420+
* take no time to execute.
33943421
*/
3395-
static instr_time
3396-
doExecuteCommand(TState *thread, CState *st, instr_time now)
3422+
static ConnectionStateEnum
3423+
executeMetaCommand(TState *thread, CState *st, instr_time *now)
33973424
{
33983425
Command *command = sql_script[st->use_file].commands[st->command];
3426+
int argc;
3427+
char **argv;
3428+
3429+
Assert(command != NULL && command->type == META_COMMAND);
33993430

3400-
/* execute the command */
3401-
if (command->type == SQL_COMMAND)
3431+
argc = command->argc;
3432+
argv = command->argv;
3433+
3434+
if (debug)
34023435
{
3403-
if (!sendCommand(st, command))
3436+
fprintf(stderr, "client %d executing \\%s", st->id, argv[0]);
3437+
for (int i = 1; i < argc; i++)
3438+
fprintf(stderr, " %s", argv[i]);
3439+
fprintf(stderr, "\n");
3440+
}
3441+
3442+
if (command->meta == META_SLEEP)
3443+
{
3444+
int usec;
3445+
3446+
/*
3447+
* A \sleep doesn't execute anything, we just get the delay from the
3448+
* argument, and enter the CSTATE_SLEEP state. (The per-command
3449+
* latency will be recorded in CSTATE_SLEEP state, not here, after the
3450+
* delay has elapsed.)
3451+
*/
3452+
if (!evaluateSleep(st, argc, argv, &usec))
34043453
{
3405-
commandFailed(st, "SQL", "SQL command send failed");
3406-
st->state = CSTATE_ABORTED;
3454+
commandFailed(st, "sleep", "execution of meta-command failed");
3455+
return CSTATE_ABORTED;
34073456
}
3408-
else
3409-
st->state = CSTATE_WAIT_RESULT;
3457+
3458+
INSTR_TIME_SET_CURRENT_LAZY(*now);
3459+
st->sleep_until = INSTR_TIME_GET_MICROSEC(*now) + usec;
3460+
return CSTATE_SLEEP;
34103461
}
3411-
else if (command->type == META_COMMAND)
3462+
else if (command->meta == META_SET)
34123463
{
3413-
int argc = command->argc;
3414-
char **argv = command->argv;
3464+
PgBenchExpr *expr = command->expr;
3465+
PgBenchValue result;
34153466

3416-
if (debug)
3467+
if (!evaluateExpr(thread, st, expr, &result))
34173468
{
3418-
fprintf(stderr, "client %d executing \\%s",
3419-
st->id, argv[0]);
3420-
for (int i = 1; i < argc; i++)
3421-
fprintf(stderr, " %s", argv[i]);
3422-
fprintf(stderr, "\n");
3469+
commandFailed(st, argv[0], "evaluation of meta-command failed");
3470+
return CSTATE_ABORTED;
34233471
}
34243472

3425-
if (command->meta == META_SLEEP)
3473+
if (!putVariableValue(st, argv[0], argv[1], &result))
34263474
{
3427-
int usec;
3428-
3429-
/*
3430-
* A \sleep doesn't execute anything, we just get the delay from
3431-
* the argument, and enter the CSTATE_SLEEP state. (The
3432-
* per-command latency will be recorded in CSTATE_SLEEP state, not
3433-
* here, after the delay has elapsed.)
3434-
*/
3435-
if (!evaluateSleep(st, argc, argv, &usec))
3436-
{
3437-
commandFailed(st, "sleep", "execution of meta-command failed");
3438-
st->state = CSTATE_ABORTED;
3439-
return now;
3440-
}
3441-
3442-
INSTR_TIME_SET_CURRENT_LAZY(now);
3443-
3444-
st->sleep_until = INSTR_TIME_GET_MICROSEC(now) + usec;
3445-
st->state = CSTATE_SLEEP;
3446-
return now;
3475+
commandFailed(st, "set", "assignment of meta-command failed");
3476+
return CSTATE_ABORTED;
34473477
}
3448-
else if (command->meta == META_SET)
3449-
{
3450-
PgBenchExpr *expr = command->expr;
3451-
PgBenchValue result;
3452-
3453-
if (!evaluateExpr(thread, st, expr, &result))
3454-
{
3455-
commandFailed(st, argv[0], "evaluation of meta-command failed");
3456-
st->state = CSTATE_ABORTED;
3457-
return now;
3458-
}
3478+
}
3479+
else if (command->meta == META_IF)
3480+
{
3481+
/* backslash commands with an expression to evaluate */
3482+
PgBenchExpr *expr = command->expr;
3483+
PgBenchValue result;
3484+
bool cond;
34593485

3460-
if (!putVariableValue(st, argv[0], argv[1], &result))
3461-
{
3462-
commandFailed(st, "set", "assignment of meta-command failed");
3463-
st->state = CSTATE_ABORTED;
3464-
return now;
3465-
}
3466-
}
3467-
else if (command->meta == META_IF)
3486+
if (!evaluateExpr(thread, st, expr, &result))
34683487
{
3469-
/* backslash commands with an expression to evaluate */
3470-
PgBenchExpr *expr = command->expr;
3471-
PgBenchValue result;
3472-
bool cond;
3473-
3474-
if (!evaluateExpr(thread, st, expr, &result))
3475-
{
3476-
commandFailed(st, argv[0], "evaluation of meta-command failed");
3477-
st->state = CSTATE_ABORTED;
3478-
return now;
3479-
}
3480-
3481-
cond = valueTruth(&result);
3482-
conditional_stack_push(st->cstack, cond ? IFSTATE_TRUE : IFSTATE_FALSE);
3488+
commandFailed(st, argv[0], "evaluation of meta-command failed");
3489+
return CSTATE_ABORTED;
34833490
}
3484-
else if (command->meta == META_ELIF)
3485-
{
3486-
/* backslash commands with an expression to evaluate */
3487-
PgBenchExpr *expr = command->expr;
3488-
PgBenchValue result;
3489-
bool cond;
34903491

3491-
if (conditional_stack_peek(st->cstack) == IFSTATE_TRUE)
3492-
{
3493-
/*
3494-
* elif after executed block, skip eval and wait for endif.
3495-
*/
3496-
conditional_stack_poke(st->cstack, IFSTATE_IGNORED);
3497-
st->state = CSTATE_END_COMMAND;
3498-
return now;
3499-
}
3500-
3501-
if (!evaluateExpr(thread, st, expr, &result))
3502-
{
3503-
commandFailed(st, argv[0], "evaluation of meta-command failed");
3504-
st->state = CSTATE_ABORTED;
3505-
return now;
3506-
}
3492+
cond = valueTruth(&result);
3493+
conditional_stack_push(st->cstack, cond ? IFSTATE_TRUE : IFSTATE_FALSE);
3494+
}
3495+
else if (command->meta == META_ELIF)
3496+
{
3497+
/* backslash commands with an expression to evaluate */
3498+
PgBenchExpr *expr = command->expr;
3499+
PgBenchValue result;
3500+
bool cond;
35073501

3508-
cond = valueTruth(&result);
3509-
Assert(conditional_stack_peek(st->cstack) == IFSTATE_FALSE);
3510-
conditional_stack_poke(st->cstack, cond ? IFSTATE_TRUE : IFSTATE_FALSE);
3502+
if (conditional_stack_peek(st->cstack) == IFSTATE_TRUE)
3503+
{
3504+
/* elif after executed block, skip eval and wait for endif. */
3505+
conditional_stack_poke(st->cstack, IFSTATE_IGNORED);
3506+
return CSTATE_END_COMMAND;
35113507
}
3512-
else if (command->meta == META_ELSE)
3508+
3509+
if (!evaluateExpr(thread, st, expr, &result))
35133510
{
3514-
switch (conditional_stack_peek(st->cstack))
3515-
{
3516-
case IFSTATE_TRUE:
3517-
conditional_stack_poke(st->cstack, IFSTATE_ELSE_FALSE);
3518-
break;
3519-
case IFSTATE_FALSE: /* inconsistent if active */
3520-
case IFSTATE_IGNORED: /* inconsistent if active */
3521-
case IFSTATE_NONE: /* else without if */
3522-
case IFSTATE_ELSE_TRUE: /* else after else */
3523-
case IFSTATE_ELSE_FALSE: /* else after else */
3524-
default:
3525-
/* dead code if conditional check is ok */
3526-
Assert(false);
3527-
}
3511+
commandFailed(st, argv[0], "evaluation of meta-command failed");
3512+
return CSTATE_ABORTED;
35283513
}
3529-
else if (command->meta == META_ENDIF)
3514+
3515+
cond = valueTruth(&result);
3516+
Assert(conditional_stack_peek(st->cstack) == IFSTATE_FALSE);
3517+
conditional_stack_poke(st->cstack, cond ? IFSTATE_TRUE : IFSTATE_FALSE);
3518+
}
3519+
else if (command->meta == META_ELSE)
3520+
{
3521+
switch (conditional_stack_peek(st->cstack))
35303522
{
3531-
Assert(!conditional_stack_empty(st->cstack));
3532-
conditional_stack_pop(st->cstack);
3523+
case IFSTATE_TRUE:
3524+
conditional_stack_poke(st->cstack, IFSTATE_ELSE_FALSE);
3525+
break;
3526+
case IFSTATE_FALSE: /* inconsistent if active */
3527+
case IFSTATE_IGNORED: /* inconsistent if active */
3528+
case IFSTATE_NONE: /* else without if */
3529+
case IFSTATE_ELSE_TRUE: /* else after else */
3530+
case IFSTATE_ELSE_FALSE: /* else after else */
3531+
default:
3532+
/* dead code if conditional check is ok */
3533+
Assert(false);
35333534
}
3534-
else if (command->meta == META_SETSHELL)
3535+
}
3536+
else if (command->meta == META_ENDIF)
3537+
{
3538+
Assert(!conditional_stack_empty(st->cstack));
3539+
conditional_stack_pop(st->cstack);
3540+
}
3541+
else if (command->meta == META_SETSHELL)
3542+
{
3543+
if (!runShellCommand(st, argv[1], argv + 2, argc - 2))
35353544
{
3536-
if (!runShellCommand(st, argv[1], argv + 2, argc - 2))
3537-
{
3538-
commandFailed(st, "setshell", "execution of meta-command failed");
3539-
st->state = CSTATE_ABORTED;
3540-
return now;
3541-
}
3545+
commandFailed(st, "setshell", "execution of meta-command failed");
3546+
return CSTATE_ABORTED;
35423547
}
3543-
else if (command->meta == META_SHELL)
3548+
}
3549+
else if (command->meta == META_SHELL)
3550+
{
3551+
if (!runShellCommand(st, NULL, argv + 1, argc - 1))
35443552
{
3545-
if (!runShellCommand(st, NULL, argv + 1, argc - 1))
3546-
{
3547-
commandFailed(st, "shell", "execution of meta-command failed");
3548-
st->state = CSTATE_ABORTED;
3549-
return now;
3550-
}
3553+
commandFailed(st, "shell", "execution of meta-command failed");
3554+
return CSTATE_ABORTED;
35513555
}
3552-
3553-
/*
3554-
* executing the expression or shell command might have taken a
3555-
* non-negligible amount of time, so reset 'now'
3556-
*/
3557-
INSTR_TIME_SET_ZERO(now);
3558-
3559-
st->state = CSTATE_END_COMMAND;
35603556
}
35613557

3562-
return now;
3558+
/*
3559+
* executing the expression or shell command might have taken a
3560+
* non-negligible amount of time, so reset 'now'
3561+
*/
3562+
INSTR_TIME_SET_ZERO(*now);
3563+
3564+
return CSTATE_END_COMMAND;
35633565
}
35643566

35653567
/*
@@ -4281,6 +4283,7 @@ free_command(Command *command)
42814283
pg_free(command->argv[i]);
42824284
if (command->varprefix)
42834285
pg_free(command->varprefix);
4286+
42844287
/*
42854288
* It should also free expr recursively, but this is currently not needed
42864289
* as only gset commands (which do not have an expression) are freed.

0 commit comments

Comments
 (0)