/* Only 1 job is allowed at any time
* A job includes *all* monitor commands, even those just querying
* information, not merely actions */
typedef enum {
QEMU_JOB_NONE = 0, /* Always set to 0 for easy if (jobActive) conditions */
QEMU_JOB_QUERY, /* Doesn't change any state */
QEMU_JOB_DESTROY, /* Destroys the domain (cannot be masked out) */
QEMU_JOB_SUSPEND, /* Suspends (stops vCPUs) the domain */
QEMU_JOB_MODIFY, /* May change state */
QEMU_JOB_ABORT, /* Abort current async job */
QEMU_JOB_MIGRATION_OP, /* Operation influencing outgoing migration */
/* The following two items must always be the last items before JOB_LAST */
QEMU_JOB_ASYNC, /* Asynchronous job */
QEMU_JOB_ASYNC_NESTED, /* Normal job within an async job */
QEMU_JOB_LAST
} qemuDomainJob;
qemuDomainJobObj
qemuDomainJobObj是描述任务的数据结构,抽象了所有同步、异步、嵌套异步任务的信息。
struct _qemuDomainJobObj {
/* 同步任务信号量,当VM有同步任务在执行时
* 新发起的任务会等待在该信号量上,直到当前任务结束后被唤醒
* */
virCond cond; /* Use to coordinate jobs */
/* The following members are for QEMU_JOB_* */
/* 保存当前虚机正在执行的同步任务,如果没有,为QEMU_JOB_NONE */
qemuDomainJob active; /* Currently running job */
/* 执行当前任务的线程ID */
unsigned long long owner; /* Thread id which set current job */
const char *ownerAPI; /* The API which owns the job */
/* 开始执行该任务的时间戳 */
unsigned long long started; /* When the current job started */
......
}
接口
qemuDomainObjBeginJob —— 标记同步任务开始
int qemuDomainObjBeginJob(virQEMUDriverPtr driver,
virDomainObjPtr obj,
qemuDomainJob job)
/* Async job consists of a series of jobs that may change state. Independent
* jobs that do not change state (and possibly others if explicitly allowed by
* current async job) are allowed to be run even if async job is active.
*/
typedef enum {
QEMU_ASYNC_JOB_NONE = 0,
/* 迁移任务:迁出 */
QEMU_ASYNC_JOB_MIGRATION_OUT,
/* 迁移任务:迁入 */
QEMU_ASYNC_JOB_MIGRATION_IN,
QEMU_ASYNC_JOB_SAVE,
QEMU_ASYNC_JOB_DUMP,
/* 快照任务 */
QEMU_ASYNC_JOB_SNAPSHOT,
QEMU_ASYNC_JOB_START,
QEMU_ASYNC_JOB_BACKUP,
QEMU_ASYNC_JOB_LAST
} qemuDomainAsyncJob;
qemuDomainJobObj
qemuDomainJobObj中除了定义同步任务,还包含了异步任务的信息,如下:
struct _qemuDomainJobObj {
......
/* The following members are for QEMU_ASYNC_JOB_* */
/* 异步任务信号量,当VM上有异步任务在执行时
* 新发起的任务如果不在当前任务允许并发执行的列表里,需要等待在该信号量上直到当前任务结束
* */
virCond asyncCond; /* Use to coordinate with async jobs */
/* 保存当前正在执行的异步任务 */
qemuDomainAsyncJob asyncJob; /* Currently active async job */
/* 异步任务的线程ID */
unsigned long long asyncOwner; /* Thread which set current async job */
const char *asyncOwnerAPI; /* The API which owns the async job */
/* 异步任务开始时间戳 */
unsigned long long asyncStarted; /* When the current async job started */
int phase; /* Job phase (mainly for migrations) */
/* 异步任务执行过程中,允许并发执行其它任务的任务白名单*/
unsigned long long mask; /* Jobs allowed during async job */
/* 异步任务信息 */
qemuDomainJobInfoPtr current; /* async job progress data */
qemuDomainJobInfoPtr completed; /* statistics data of a recently completed job */
......
}
typedef struct _qemuDomainJobInfo qemuDomainJobInfo;
struct _qemuDomainJobInfo {
/* 任务状态 */
qemuDomainJobStatus status;
virDomainJobOperation operation;
/* 任务开始时间戳 */
unsigned long long started; /* When the async job started */
unsigned long long stopped; /* When the domain's CPUs were stopped */
unsigned long long sent; /* When the source sent status info to the
destination (only for migrations). */
unsigned long long received; /* When the destination host received status
info from the source (migrations only). */
/* Computed values */
unsigned long long timeElapsed;
long long timeDelta; /* delta = received - sent, i.e., the difference
between the source and the destination time plus
the time between the end of Perform phase on the
source and the beginning of Finish phase on the
destination. */
bool timeDeltaSet;
/* Raw values from QEMU */
/* 任务统计信息类型 */
qemuDomainJobStatsType statsType;
union {
qemuMonitorMigrationStats mig;
qemuMonitorDumpStats dump;
qemuDomainBackupStats backup;
} stats;
qemuDomainMirrorStats mirrorStats;
......
}
接口
qemuDomainObjBeginAsyncJob —— 标记异步任务开始
int qemuDomainObjBeginAsyncJob(virQEMUDriverPtr driver,
virDomainObjPtr obj,
qemuDomainAsyncJob asyncJob,
virDomainJobOperation operation,
unsigned long apiFlags)
void qemuDomainObjEndJob(virQEMUDriverPtr driver, virDomainObjPtr obj)
{
qemuDomainObjPrivatePtr priv = obj->privateData;
qemuDomainJob job = priv->job.active;
priv->jobs_queued--;
/* 复位同步任务 */
qemuDomainObjResetJob(&priv->job);
if (qemuDomainTrackJob(job))
qemuDomainObjSaveStatus(driver, obj);
/* We indeed need to wake up ALL threads waiting because
* grabbing a job requires checking more variables. */
/* 唤醒所有等待在同步任务信号量上的线程 */
virCondBroadcast(&priv->job.cond);
}