aboutsummaryrefslogtreecommitdiff
path: root/job.c
diff options
context:
space:
mode:
authorKevin Wolf <kwolf@redhat.com>2018-04-13 17:19:31 +0200
committerKevin Wolf <kwolf@redhat.com>2018-05-23 14:30:49 +0200
commita50c2ab858fe613fb805e53b4f6b970ab936706d (patch)
tree06a64966236166b648e1c5bd1f08c240b34a0c00 /job.c
parente7c1d78bbd5867804debeb7159b137fd9a6c44d3 (diff)
job: Move state transitions to Job
This moves BlockJob.status and the closely related functions (block_)job_state_transition() and (block_)job_apply_verb to Job. The two QAPI enums are renamed to JobStatus and JobVerb. Signed-off-by: Kevin Wolf <kwolf@redhat.com> Reviewed-by: Max Reitz <mreitz@redhat.com> Reviewed-by: John Snow <jsnow@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com>
Diffstat (limited to 'job.c')
-rw-r--r--job.c56
1 files changed, 56 insertions, 0 deletions
diff --git a/job.c b/job.c
index e57303c6bb..b049a322cc 100644
--- a/job.c
+++ b/job.c
@@ -28,9 +28,63 @@
#include "qapi/error.h"
#include "qemu/job.h"
#include "qemu/id.h"
+#include "trace-root.h"
static QLIST_HEAD(, Job) jobs = QLIST_HEAD_INITIALIZER(jobs);
+/* Job State Transition Table */
+bool JobSTT[JOB_STATUS__MAX][JOB_STATUS__MAX] = {
+ /* U, C, R, P, Y, S, W, D, X, E, N */
+ /* U: */ [JOB_STATUS_UNDEFINED] = {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ /* C: */ [JOB_STATUS_CREATED] = {0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1},
+ /* R: */ [JOB_STATUS_RUNNING] = {0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0},
+ /* P: */ [JOB_STATUS_PAUSED] = {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
+ /* Y: */ [JOB_STATUS_READY] = {0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0},
+ /* S: */ [JOB_STATUS_STANDBY] = {0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0},
+ /* W: */ [JOB_STATUS_WAITING] = {0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0},
+ /* D: */ [JOB_STATUS_PENDING] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0},
+ /* X: */ [JOB_STATUS_ABORTING] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0},
+ /* E: */ [JOB_STATUS_CONCLUDED] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
+ /* N: */ [JOB_STATUS_NULL] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+};
+
+bool JobVerbTable[JOB_VERB__MAX][JOB_STATUS__MAX] = {
+ /* U, C, R, P, Y, S, W, D, X, E, N */
+ [JOB_VERB_CANCEL] = {0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0},
+ [JOB_VERB_PAUSE] = {0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0},
+ [JOB_VERB_RESUME] = {0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0},
+ [JOB_VERB_SET_SPEED] = {0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0},
+ [JOB_VERB_COMPLETE] = {0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0},
+ [JOB_VERB_FINALIZE] = {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0},
+ [JOB_VERB_DISMISS] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0},
+};
+
+/* TODO Make static once the whole state machine is in job.c */
+void job_state_transition(Job *job, JobStatus s1)
+{
+ JobStatus s0 = job->status;
+ assert(s1 >= 0 && s1 <= JOB_STATUS__MAX);
+ trace_job_state_transition(job, /* TODO re-enable: job->ret */ 0,
+ JobSTT[s0][s1] ? "allowed" : "disallowed",
+ JobStatus_str(s0), JobStatus_str(s1));
+ assert(JobSTT[s0][s1]);
+ job->status = s1;
+}
+
+int job_apply_verb(Job *job, JobVerb verb, Error **errp)
+{
+ JobStatus s0 = job->status;
+ assert(verb >= 0 && verb <= JOB_VERB__MAX);
+ trace_job_apply_verb(job, JobStatus_str(s0), JobVerb_str(verb),
+ JobVerbTable[verb][s0] ? "allowed" : "prohibited");
+ if (JobVerbTable[verb][s0]) {
+ return 0;
+ }
+ error_setg(errp, "Job '%s' in state '%s' cannot accept command verb '%s'",
+ job->id, JobStatus_str(s0), JobVerb_str(verb));
+ return -EPERM;
+}
+
JobType job_type(const Job *job)
{
return job->driver->job_type;
@@ -81,6 +135,8 @@ void *job_create(const char *job_id, const JobDriver *driver, Error **errp)
job->driver = driver;
job->id = g_strdup(job_id);
+ job_state_transition(job, JOB_STATUS_CREATED);
+
QLIST_INSERT_HEAD(&jobs, job, job_list);
return job;