Revision 940cc30d monitor.c
b/monitor.c | ||
---|---|---|
76 | 76 |
* |
77 | 77 |
*/ |
78 | 78 |
|
79 |
typedef struct MonitorCompletionData MonitorCompletionData; |
|
80 |
struct MonitorCompletionData { |
|
81 |
Monitor *mon; |
|
82 |
void (*user_print)(Monitor *mon, const QObject *data); |
|
83 |
}; |
|
84 |
|
|
79 | 85 |
typedef struct mon_cmd_t { |
80 | 86 |
const char *name; |
81 | 87 |
const char *args_type; |
... | ... | |
85 | 91 |
union { |
86 | 92 |
void (*info)(Monitor *mon); |
87 | 93 |
void (*info_new)(Monitor *mon, QObject **ret_data); |
94 |
int (*info_async)(Monitor *mon, MonitorCompletion *cb, void *opaque); |
|
88 | 95 |
void (*cmd)(Monitor *mon, const QDict *qdict); |
89 | 96 |
void (*cmd_new)(Monitor *mon, const QDict *params, QObject **ret_data); |
97 |
int (*cmd_async)(Monitor *mon, const QDict *params, |
|
98 |
MonitorCompletion *cb, void *opaque); |
|
90 | 99 |
} mhandler; |
100 |
int async; |
|
91 | 101 |
} mon_cmd_t; |
92 | 102 |
|
93 | 103 |
/* file descriptors passed via SCM_RIGHTS */ |
... | ... | |
255 | 265 |
return cmd->user_print != NULL; |
256 | 266 |
} |
257 | 267 |
|
268 |
static inline bool monitor_handler_is_async(const mon_cmd_t *cmd) |
|
269 |
{ |
|
270 |
return cmd->async != 0; |
|
271 |
} |
|
272 |
|
|
258 | 273 |
static inline int monitor_has_error(const Monitor *mon) |
259 | 274 |
{ |
260 | 275 |
return mon->error != NULL; |
... | ... | |
453 | 468 |
} |
454 | 469 |
} |
455 | 470 |
|
471 |
static void user_monitor_complete(void *opaque, QObject *ret_data) |
|
472 |
{ |
|
473 |
MonitorCompletionData *data = (MonitorCompletionData *)opaque; |
|
474 |
|
|
475 |
if (ret_data) { |
|
476 |
data->user_print(data->mon, ret_data); |
|
477 |
} |
|
478 |
monitor_resume(data->mon); |
|
479 |
qemu_free(data); |
|
480 |
} |
|
481 |
|
|
482 |
static void qmp_monitor_complete(void *opaque, QObject *ret_data) |
|
483 |
{ |
|
484 |
monitor_protocol_emitter(opaque, ret_data); |
|
485 |
} |
|
486 |
|
|
487 |
static void qmp_async_cmd_handler(Monitor *mon, const mon_cmd_t *cmd, |
|
488 |
const QDict *params) |
|
489 |
{ |
|
490 |
cmd->mhandler.cmd_async(mon, params, qmp_monitor_complete, mon); |
|
491 |
} |
|
492 |
|
|
493 |
static void qmp_async_info_handler(Monitor *mon, const mon_cmd_t *cmd) |
|
494 |
{ |
|
495 |
cmd->mhandler.info_async(mon, qmp_monitor_complete, mon); |
|
496 |
} |
|
497 |
|
|
498 |
static void user_async_cmd_handler(Monitor *mon, const mon_cmd_t *cmd, |
|
499 |
const QDict *params) |
|
500 |
{ |
|
501 |
int ret; |
|
502 |
|
|
503 |
MonitorCompletionData *cb_data = qemu_malloc(sizeof(*cb_data)); |
|
504 |
cb_data->mon = mon; |
|
505 |
cb_data->user_print = cmd->user_print; |
|
506 |
monitor_suspend(mon); |
|
507 |
ret = cmd->mhandler.cmd_async(mon, params, |
|
508 |
user_monitor_complete, cb_data); |
|
509 |
if (ret < 0) { |
|
510 |
monitor_resume(mon); |
|
511 |
qemu_free(cb_data); |
|
512 |
} |
|
513 |
} |
|
514 |
|
|
515 |
static void user_async_info_handler(Monitor *mon, const mon_cmd_t *cmd) |
|
516 |
{ |
|
517 |
int ret; |
|
518 |
|
|
519 |
MonitorCompletionData *cb_data = qemu_malloc(sizeof(*cb_data)); |
|
520 |
cb_data->mon = mon; |
|
521 |
cb_data->user_print = cmd->user_print; |
|
522 |
monitor_suspend(mon); |
|
523 |
ret = cmd->mhandler.info_async(mon, user_monitor_complete, cb_data); |
|
524 |
if (ret < 0) { |
|
525 |
monitor_resume(mon); |
|
526 |
qemu_free(cb_data); |
|
527 |
} |
|
528 |
} |
|
529 |
|
|
456 | 530 |
static void do_info(Monitor *mon, const QDict *qdict, QObject **ret_data) |
457 | 531 |
{ |
458 | 532 |
const mon_cmd_t *cmd; |
... | ... | |
476 | 550 |
goto help; |
477 | 551 |
} |
478 | 552 |
|
479 |
if (monitor_handler_ported(cmd)) { |
|
553 |
if (monitor_handler_is_async(cmd)) { |
|
554 |
if (monitor_ctrl_mode(mon)) { |
|
555 |
qmp_async_info_handler(mon, cmd); |
|
556 |
} else { |
|
557 |
user_async_info_handler(mon, cmd); |
|
558 |
} |
|
559 |
/* |
|
560 |
* Indicate that this command is asynchronous and will not return any |
|
561 |
* data (not even empty). Instead, the data will be returned via a |
|
562 |
* completion callback. |
|
563 |
*/ |
|
564 |
*ret_data = qobject_from_jsonf("{ '__mon_async': 'return' }"); |
|
565 |
} else if (monitor_handler_ported(cmd)) { |
|
480 | 566 |
cmd->mhandler.info_new(mon, ret_data); |
481 | 567 |
|
482 | 568 |
if (!monitor_ctrl_mode(mon)) { |
... | ... | |
3588 | 3674 |
mon->error = NULL; |
3589 | 3675 |
} |
3590 | 3676 |
|
3677 |
static int is_async_return(const QObject *data) |
|
3678 |
{ |
|
3679 |
return data && qdict_haskey(qobject_to_qdict(data), "__mon_async"); |
|
3680 |
} |
|
3681 |
|
|
3591 | 3682 |
static void monitor_call_handler(Monitor *mon, const mon_cmd_t *cmd, |
3592 | 3683 |
const QDict *params) |
3593 | 3684 |
{ |
... | ... | |
3595 | 3686 |
|
3596 | 3687 |
cmd->mhandler.cmd_new(mon, params, &data); |
3597 | 3688 |
|
3598 |
if (monitor_ctrl_mode(mon)) { |
|
3689 |
if (is_async_return(data)) { |
|
3690 |
/* |
|
3691 |
* Asynchronous commands have no initial return data but they can |
|
3692 |
* generate errors. Data is returned via the async completion handler. |
|
3693 |
*/ |
|
3694 |
if (monitor_ctrl_mode(mon) && monitor_has_error(mon)) { |
|
3695 |
monitor_protocol_emitter(mon, NULL); |
|
3696 |
} |
|
3697 |
} else if (monitor_ctrl_mode(mon)) { |
|
3599 | 3698 |
/* Monitor Protocol */ |
3600 | 3699 |
monitor_protocol_emitter(mon, data); |
3601 | 3700 |
} else { |
... | ... | |
3620 | 3719 |
|
3621 | 3720 |
qemu_errors_to_mon(mon); |
3622 | 3721 |
|
3623 |
if (monitor_handler_ported(cmd)) { |
|
3722 |
if (monitor_handler_is_async(cmd)) { |
|
3723 |
user_async_cmd_handler(mon, cmd, qdict); |
|
3724 |
} else if (monitor_handler_ported(cmd)) { |
|
3624 | 3725 |
monitor_call_handler(mon, cmd, qdict); |
3625 | 3726 |
} else { |
3626 | 3727 |
cmd->mhandler.cmd(mon, qdict); |
... | ... | |
4082 | 4183 |
goto err_out; |
4083 | 4184 |
} |
4084 | 4185 |
|
4085 |
monitor_call_handler(mon, cmd, args); |
|
4186 |
if (monitor_handler_is_async(cmd)) { |
|
4187 |
qmp_async_cmd_handler(mon, cmd, args); |
|
4188 |
} else { |
|
4189 |
monitor_call_handler(mon, cmd, args); |
|
4190 |
} |
|
4086 | 4191 |
goto out; |
4087 | 4192 |
|
4088 | 4193 |
err_input: |
Also available in: Unified diff