On 01/29/2018 12:17 PM, Kevin Wolf wrote:
> Am 27.01.2018 um 03:05 hat John Snow geschrieben:
>> The state transition table has mostly been implied. We're about to make
>> it a bit more complex, so let's make the STM explicit instead.
>>
>> Perform state transitions with a function that for now just asserts the
>> transition is appropriate.
>>
>> undefined: May only transition to 'created'.
>> created: May only transition to 'running'.
>>          It cannot transition to pause directly, but if a created job
>>          is requested to pause prior to starting, it will transition
>>          synchronously to 'running' and then to 'paused'.
>> running: May transition either to 'paused' or 'ready'.
>> paused: May transition to either 'running' or 'ready', but only in
>>         terms of returning to that prior state.
>>         p->r->y is not possible, but this is not encapsulated by the
>>         STM table.
> 
> Do you mean y->p->r->y here? If not, I don't understand.

Whoops, Yes, I mean to say that Y->P->R is not possible.

That is, a paused state can only return to where it came from, but the
STM doesn't show this restriction. Really, this hints at there being
*two* paused states, but I didn't want to go through the trouble of
adding a new one.

> 
>> ready: May transition to paused.

I swear my script used to add blank lines for me here. *shrug*

>> Signed-off-by: John Snow <js...@redhat.com>
>> ---
>>  blockjob.c | 39 ++++++++++++++++++++++++++++++++++-----
>>  1 file changed, 34 insertions(+), 5 deletions(-)
>>
>> diff --git a/blockjob.c b/blockjob.c
>> index 6eb783a354..d084a1e318 100644
>> --- a/blockjob.c
>> +++ b/blockjob.c
>> @@ -42,6 +42,35 @@
>>   * block_job_enter. */
>>  static QemuMutex block_job_mutex;
>>  
>> +/* BlockJob State Transition Table */
>> +bool BlockJobSTT[BLOCK_JOB_STATUS__MAX][BLOCK_JOB_STATUS__MAX] = {
>> +                                          /* U, C, R, P, Y */
>> +    /* U: */ [BLOCK_JOB_STATUS_UNDEFINED] = {0, 1, 0, 0, 0},
>> +    /* C: */ [BLOCK_JOB_STATUS_CREATED]   = {0, 0, 1, 0, 0},
>> +    /* R: */ [BLOCK_JOB_STATUS_RUNNING]   = {0, 0, 0, 1, 1},
>> +    /* P: */ [BLOCK_JOB_STATUS_PAUSED]    = {0, 0, 1, 0, 1},
>> +    /* Y: */ [BLOCK_JOB_STATUS_READY]     = {0, 0, 0, 1, 0},
>> +};
>> +
>> +static void block_job_state_transition(BlockJob *job, BlockJobStatus s1)
>> +{
>> +    BlockJobStatus s0 = job->status;
>> +    if (s0 == s1) {
>> +        return;
>> +    }
>> +    assert(s1 >= 0 && s1 <= BLOCK_JOB_STATUS__MAX);
>> +    assert(BlockJobSTT[s0][s1]);
>> +    switch (s1) {
>> +    case BLOCK_JOB_STATUS_WAITING:
>> +    case BLOCK_JOB_STATUS_PENDING:
>> +    case BLOCK_JOB_STATUS_CONCLUDED:
>> +        assert(job->manual);
>> +    default:
>> +        break;
>> +    }
> 
> This doesn't compile because the constants don't exist yet.
> 

*cough* oops.

> Apart from that, I think the assertion is misguided, too. Which states a
> job goes through shouldn't depend on whether the client wants to
> complete the job manually or have it completed automatically. The
> difference should only be which state transitions are automatic.
> > In other words, WAITING/PENDING/CONCLUDED may never be visible in
> query-block-job for automatically completed jobs, but the jobs should
> still (synchronously) go through all of these states.
> 

Hmm. OK, I can look at doing it in this way. I will probably also have
it omit the events in this case too, though.

>> +    job->status = s1;
>> +}
>> +
> 
> Kevin
> 

Thanks!

Reply via email to