Commit 9938d116 authored by Alvaro Herrera's avatar Alvaro Herrera

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
parent a51cc7e9
...@@ -607,8 +607,8 @@ static void setIntValue(PgBenchValue *pv, int64 ival); ...@@ -607,8 +607,8 @@ static void setIntValue(PgBenchValue *pv, int64 ival);
static void setDoubleValue(PgBenchValue *pv, double dval); static void setDoubleValue(PgBenchValue *pv, double dval);
static bool evaluateExpr(TState *thread, CState *st, PgBenchExpr *expr, static bool evaluateExpr(TState *thread, CState *st, PgBenchExpr *expr,
PgBenchValue *retval); PgBenchValue *retval);
static instr_time doExecuteCommand(TState *thread, CState *st, static ConnectionStateEnum executeMetaCommand(TState *thread, CState *st,
instr_time now); instr_time *now);
static void doLog(TState *thread, CState *st, static void doLog(TState *thread, CState *st,
StatsData *agg, bool skipped, double latency, double lag); StatsData *agg, bool skipped, double latency, double lag);
static void processXactStats(TState *thread, CState *st, instr_time *now, static void processXactStats(TState *thread, CState *st, instr_time *now,
...@@ -802,7 +802,7 @@ out_of_range: ...@@ -802,7 +802,7 @@ out_of_range:
invalid_syntax: invalid_syntax:
if (!errorOK) if (!errorOK)
fprintf(stderr, fprintf(stderr,
"invalid input syntax for type bigint: \"%s\"\n",str); "invalid input syntax for type bigint: \"%s\"\n", str);
return false; return false;
} }
...@@ -827,7 +827,7 @@ strtodouble(const char *str, bool errorOK, double *dv) ...@@ -827,7 +827,7 @@ strtodouble(const char *str, bool errorOK, double *dv)
{ {
if (!errorOK) if (!errorOK)
fprintf(stderr, fprintf(stderr,
"invalid input syntax for type double: \"%s\"\n",str); "invalid input syntax for type double: \"%s\"\n", str);
return false; return false;
} }
return true; return true;
...@@ -3012,6 +3012,8 @@ advanceConnectionState(TState *thread, CState *st, StatsData *agg) ...@@ -3012,6 +3012,8 @@ advanceConnectionState(TState *thread, CState *st, StatsData *agg)
*/ */
for (;;) for (;;)
{ {
Command *command;
switch (st->state) switch (st->state)
{ {
/* Select transaction (script) to run. */ /* Select transaction (script) to run. */
...@@ -3151,8 +3153,10 @@ advanceConnectionState(TState *thread, CState *st, StatsData *agg) ...@@ -3151,8 +3153,10 @@ advanceConnectionState(TState *thread, CState *st, StatsData *agg)
* Send a command to server (or execute a meta-command) * Send a command to server (or execute a meta-command)
*/ */
case CSTATE_START_COMMAND: case CSTATE_START_COMMAND:
command = sql_script[st->use_file].commands[st->command];
/* Transition to script end processing if done */ /* Transition to script end processing if done */
if (sql_script[st->use_file].commands[st->command] == NULL) if (command == NULL)
{ {
st->state = CSTATE_END_TX; st->state = CSTATE_END_TX;
break; break;
...@@ -3164,7 +3168,28 @@ advanceConnectionState(TState *thread, CState *st, StatsData *agg) ...@@ -3164,7 +3168,28 @@ advanceConnectionState(TState *thread, CState *st, StatsData *agg)
INSTR_TIME_SET_CURRENT_LAZY(now); INSTR_TIME_SET_CURRENT_LAZY(now);
st->stmt_begin = now; st->stmt_begin = now;
} }
now = doExecuteCommand(thread, st, now);
/* Execute the command */
if (command->type == SQL_COMMAND)
{
if (!sendCommand(st, command))
{
commandFailed(st, "SQL", "SQL command send failed");
st->state = CSTATE_ABORTED;
}
else
st->state = CSTATE_WAIT_RESULT;
}
else if (command->type == META_COMMAND)
{
/*-----
* Possible state changes when executing meta commands:
* - on errors CSTATE_ABORTED
* - on sleep CSTATE_SLEEP
* - else CSTATE_END_COMMAND
*/
st->state = executeMetaCommand(thread, st, &now);
}
/* /*
* We're now waiting for an SQL command to complete, or * We're now waiting for an SQL command to complete, or
...@@ -3237,7 +3262,8 @@ advanceConnectionState(TState *thread, CState *st, StatsData *agg) ...@@ -3237,7 +3262,8 @@ advanceConnectionState(TState *thread, CState *st, StatsData *agg)
case IFSTATE_IGNORED: case IFSTATE_IGNORED:
case IFSTATE_ELSE_FALSE: case IFSTATE_ELSE_FALSE:
if (command->meta == META_IF) if (command->meta == META_IF)
conditional_stack_push(st->cstack, IFSTATE_IGNORED); conditional_stack_push(st->cstack,
IFSTATE_IGNORED);
else if (command->meta == META_ENDIF) else if (command->meta == META_ENDIF)
{ {
Assert(!conditional_stack_empty(st->cstack)); Assert(!conditional_stack_empty(st->cstack));
...@@ -3387,36 +3413,27 @@ advanceConnectionState(TState *thread, CState *st, StatsData *agg) ...@@ -3387,36 +3413,27 @@ advanceConnectionState(TState *thread, CState *st, StatsData *agg)
} }
/* /*
* Subroutine for advanceConnectionState -- execute or initiate the current * Subroutine for advanceConnectionState -- initiate or execute the current
* command, and transition to next state appropriately. * meta command, and return the next state to set.
* *
* Returns an updated timestamp from 'now', used to update 'now' at callsite. * *now is updated to the current time, unless the command is expected to
* take no time to execute.
*/ */
static instr_time static ConnectionStateEnum
doExecuteCommand(TState *thread, CState *st, instr_time now) executeMetaCommand(TState *thread, CState *st, instr_time *now)
{ {
Command *command = sql_script[st->use_file].commands[st->command]; Command *command = sql_script[st->use_file].commands[st->command];
int argc;
char **argv;
/* execute the command */ Assert(command != NULL && command->type == META_COMMAND);
if (command->type == SQL_COMMAND)
{ argc = command->argc;
if (!sendCommand(st, command)) argv = command->argv;
{
commandFailed(st, "SQL", "SQL command send failed");
st->state = CSTATE_ABORTED;
}
else
st->state = CSTATE_WAIT_RESULT;
}
else if (command->type == META_COMMAND)
{
int argc = command->argc;
char **argv = command->argv;
if (debug) if (debug)
{ {
fprintf(stderr, "client %d executing \\%s", fprintf(stderr, "client %d executing \\%s", st->id, argv[0]);
st->id, argv[0]);
for (int i = 1; i < argc; i++) for (int i = 1; i < argc; i++)
fprintf(stderr, " %s", argv[i]); fprintf(stderr, " %s", argv[i]);
fprintf(stderr, "\n"); fprintf(stderr, "\n");
...@@ -3427,23 +3444,20 @@ doExecuteCommand(TState *thread, CState *st, instr_time now) ...@@ -3427,23 +3444,20 @@ doExecuteCommand(TState *thread, CState *st, instr_time now)
int usec; int usec;
/* /*
* A \sleep doesn't execute anything, we just get the delay from * A \sleep doesn't execute anything, we just get the delay from the
* the argument, and enter the CSTATE_SLEEP state. (The * argument, and enter the CSTATE_SLEEP state. (The per-command
* per-command latency will be recorded in CSTATE_SLEEP state, not * latency will be recorded in CSTATE_SLEEP state, not here, after the
* here, after the delay has elapsed.) * delay has elapsed.)
*/ */
if (!evaluateSleep(st, argc, argv, &usec)) if (!evaluateSleep(st, argc, argv, &usec))
{ {
commandFailed(st, "sleep", "execution of meta-command failed"); commandFailed(st, "sleep", "execution of meta-command failed");
st->state = CSTATE_ABORTED; return CSTATE_ABORTED;
return now;
} }
INSTR_TIME_SET_CURRENT_LAZY(now); INSTR_TIME_SET_CURRENT_LAZY(*now);
st->sleep_until = INSTR_TIME_GET_MICROSEC(*now) + usec;
st->sleep_until = INSTR_TIME_GET_MICROSEC(now) + usec; return CSTATE_SLEEP;
st->state = CSTATE_SLEEP;
return now;
} }
else if (command->meta == META_SET) else if (command->meta == META_SET)
{ {
...@@ -3453,15 +3467,13 @@ doExecuteCommand(TState *thread, CState *st, instr_time now) ...@@ -3453,15 +3467,13 @@ doExecuteCommand(TState *thread, CState *st, instr_time now)
if (!evaluateExpr(thread, st, expr, &result)) if (!evaluateExpr(thread, st, expr, &result))
{ {
commandFailed(st, argv[0], "evaluation of meta-command failed"); commandFailed(st, argv[0], "evaluation of meta-command failed");
st->state = CSTATE_ABORTED; return CSTATE_ABORTED;
return now;
} }
if (!putVariableValue(st, argv[0], argv[1], &result)) if (!putVariableValue(st, argv[0], argv[1], &result))
{ {
commandFailed(st, "set", "assignment of meta-command failed"); commandFailed(st, "set", "assignment of meta-command failed");
st->state = CSTATE_ABORTED; return CSTATE_ABORTED;
return now;
} }
} }
else if (command->meta == META_IF) else if (command->meta == META_IF)
...@@ -3474,8 +3486,7 @@ doExecuteCommand(TState *thread, CState *st, instr_time now) ...@@ -3474,8 +3486,7 @@ doExecuteCommand(TState *thread, CState *st, instr_time now)
if (!evaluateExpr(thread, st, expr, &result)) if (!evaluateExpr(thread, st, expr, &result))
{ {
commandFailed(st, argv[0], "evaluation of meta-command failed"); commandFailed(st, argv[0], "evaluation of meta-command failed");
st->state = CSTATE_ABORTED; return CSTATE_ABORTED;
return now;
} }
cond = valueTruth(&result); cond = valueTruth(&result);
...@@ -3490,19 +3501,15 @@ doExecuteCommand(TState *thread, CState *st, instr_time now) ...@@ -3490,19 +3501,15 @@ doExecuteCommand(TState *thread, CState *st, instr_time now)
if (conditional_stack_peek(st->cstack) == IFSTATE_TRUE) if (conditional_stack_peek(st->cstack) == IFSTATE_TRUE)
{ {
/* /* elif after executed block, skip eval and wait for endif. */
* elif after executed block, skip eval and wait for endif.
*/
conditional_stack_poke(st->cstack, IFSTATE_IGNORED); conditional_stack_poke(st->cstack, IFSTATE_IGNORED);
st->state = CSTATE_END_COMMAND; return CSTATE_END_COMMAND;
return now;
} }
if (!evaluateExpr(thread, st, expr, &result)) if (!evaluateExpr(thread, st, expr, &result))
{ {
commandFailed(st, argv[0], "evaluation of meta-command failed"); commandFailed(st, argv[0], "evaluation of meta-command failed");
st->state = CSTATE_ABORTED; return CSTATE_ABORTED;
return now;
} }
cond = valueTruth(&result); cond = valueTruth(&result);
...@@ -3536,8 +3543,7 @@ doExecuteCommand(TState *thread, CState *st, instr_time now) ...@@ -3536,8 +3543,7 @@ doExecuteCommand(TState *thread, CState *st, instr_time now)
if (!runShellCommand(st, argv[1], argv + 2, argc - 2)) if (!runShellCommand(st, argv[1], argv + 2, argc - 2))
{ {
commandFailed(st, "setshell", "execution of meta-command failed"); commandFailed(st, "setshell", "execution of meta-command failed");
st->state = CSTATE_ABORTED; return CSTATE_ABORTED;
return now;
} }
} }
else if (command->meta == META_SHELL) else if (command->meta == META_SHELL)
...@@ -3545,8 +3551,7 @@ doExecuteCommand(TState *thread, CState *st, instr_time now) ...@@ -3545,8 +3551,7 @@ doExecuteCommand(TState *thread, CState *st, instr_time now)
if (!runShellCommand(st, NULL, argv + 1, argc - 1)) if (!runShellCommand(st, NULL, argv + 1, argc - 1))
{ {
commandFailed(st, "shell", "execution of meta-command failed"); commandFailed(st, "shell", "execution of meta-command failed");
st->state = CSTATE_ABORTED; return CSTATE_ABORTED;
return now;
} }
} }
...@@ -3554,12 +3559,9 @@ doExecuteCommand(TState *thread, CState *st, instr_time now) ...@@ -3554,12 +3559,9 @@ doExecuteCommand(TState *thread, CState *st, instr_time now)
* executing the expression or shell command might have taken a * executing the expression or shell command might have taken a
* non-negligible amount of time, so reset 'now' * non-negligible amount of time, so reset 'now'
*/ */
INSTR_TIME_SET_ZERO(now); INSTR_TIME_SET_ZERO(*now);
st->state = CSTATE_END_COMMAND;
}
return now; return CSTATE_END_COMMAND;
} }
/* /*
...@@ -4281,6 +4283,7 @@ free_command(Command *command) ...@@ -4281,6 +4283,7 @@ free_command(Command *command)
pg_free(command->argv[i]); pg_free(command->argv[i]);
if (command->varprefix) if (command->varprefix)
pg_free(command->varprefix); pg_free(command->varprefix);
/* /*
* It should also free expr recursively, but this is currently not needed * It should also free expr recursively, but this is currently not needed
* as only gset commands (which do not have an expression) are freed. * as only gset commands (which do not have an expression) are freed.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment