const char *args_type;
const char *params;
const char *help;
- void (*user_print)(Monitor *mon, const QObject *data);
union {
- void (*info)(Monitor *mon);
void (*cmd)(Monitor *mon, const QDict *qdict);
- int (*cmd_new)(Monitor *mon, const QDict *params, QObject **ret_data);
- int (*cmd_async)(Monitor *mon, const QDict *params,
- MonitorCompletion *cb, void *opaque);
+ void (*cmd_new)(QDict *params, QObject **ret_data, Error **errp);
} mhandler;
- int flags;
+ /* @sub_table is a list of 2nd level of commands. If it do not exist,
+ * mhandler should be used. If it exist, sub_table[?].mhandler should be
+ * used, and mhandler of 1st level plays the role of help function.
+ */
+ struct mon_cmd_t *sub_table;
+ void (*command_completion)(ReadLineState *rs, int nb_args, const char *str);
} mon_cmd_t;
/*
}
}
-static inline int monitor_has_error(const Monitor *mon) {
- return mon->error != NULL;
-}
-
-static QDict *build_qmp_error_dict(const QError *err) {
+static QDict *build_qmp_error_dict(Error *err) {
QObject *obj = qobject_from_jsonf(
- "{ 'error': { 'class': %s, 'desc': %p } }",
- ErrorClass_lookup[err->err_class], qerror_human(err));
+ "{ 'error': { 'class': %s, 'desc': %s } }",
+ ErrorClass_lookup[error_get_class(err)], error_get_pretty(err));
return qobject_to_qdict(obj);
}
}
static void ecs_protocol_emitter(ECS_Client *clii, const char* type,
- QObject *data) {
+ QObject *data, Error *err) {
QDict *qmp;
QObject *obj;
TRACE("ecs_protocol_emitter called.\n");
//trace_monitor_protocol_emitter(clii->cs->mon);
- if (!monitor_has_error(clii->cs->mon)) {
+ if (!err) {
/* success response */
qmp = qdict_new();
if (data) {
} else {
/* error response */
- qmp = build_qmp_error_dict(clii->cs->mon->error);
- QDECREF(clii->cs->mon->error);
- clii->cs->mon->error = NULL;
+ qmp = build_qmp_error_dict(err);
}
ecs_json_emitter(clii, QOBJECT(qmp));
QDECREF(qmp);
}
-static void qmp_monitor_complete(void *opaque, QObject *ret_data) {
- // ecs_protocol_emitter(opaque, ret_data);
-}
-
-static int ecs_qmp_async_cmd_handler(ECS_Client *clii, const mon_cmd_t *cmd,
- const QDict *params) {
- return cmd->mhandler.cmd_async(clii->cs->mon, params, qmp_monitor_complete,
- clii);
-}
-
static void ecs_qmp_call_cmd(ECS_Client *clii, Monitor *mon, const char* type,
- const mon_cmd_t *cmd, const QDict *params) {
- int ret;
+ const mon_cmd_t *cmd, QDict *params) {
QObject *data = NULL;
+ Error *local_err = NULL;
- ret = cmd->mhandler.cmd_new(mon, params, &data);
- if (ret && !monitor_has_error(mon)) {
- qerror_report(QERR_UNDEFINED_ERROR);
- }
- ecs_protocol_emitter(clii, type, data);
+ cmd->mhandler.cmd_new(params, &data, &local_err);
+ ecs_protocol_emitter(clii, type, data, local_err);
qobject_decref(data);
}
-static inline bool handler_is_async(const mon_cmd_t *cmd) {
- return cmd->flags & MONITOR_CMD_ASYNC;
-}
-
-static void monitor_user_noop(Monitor *mon, const QObject *data) {
-}
-
-static int client_migrate_info(Monitor *mon, const QDict *qdict,
- MonitorCompletion cb, void *opaque) {
- return 0;
-}
-
-static int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data) {
- return 0;
+static void qmp_device_add(QDict *qdict, QObject **ret_data, Error **errp) {
}
-static int do_qmp_capabilities(Monitor *mon, const QDict *params,
- QObject **ret_data) {
- return 0;
+static void qmp_capabilities(QDict *params, QObject **ret_data, Error **errp) {
}
static const mon_cmd_t qmp_cmds[] = {
#include "qmp-commands-old.h"
{ /* NULL */}, };
-static int check_mandatory_args(const QDict *cmd_args, const QDict *client_args,
- int *flags) {
+static void check_mandatory_args(const QDict *cmd_args, const QDict *client_args,
+ int *flags, Error **errp)
+{
const QDictEntry *ent;
for (ent = qdict_first(cmd_args); ent; ent = qdict_next(cmd_args, ent)) {
} else if (qstring_get_str(type)[0] != '-'
&& qstring_get_str(type)[1] != '?'
&& !qdict_haskey(client_args, cmd_arg_name)) {
- qerror_report(QERR_MISSING_PARAMETER, cmd_arg_name);
- return -1;
+ error_setg(errp, QERR_MISSING_PARAMETER, cmd_arg_name);
+ return;
}
}
-
- return 0;
}
-static int check_client_args_type(const QDict *client_args,
- const QDict *cmd_args, int flags) {
+static void check_client_args_type(const QDict *client_args,
+ const QDict *cmd_args, int flags, Error **errp)
+{
const QDictEntry *ent;
for (ent = qdict_first(client_args); ent;
if (flags & QMP_ACCEPT_UNKNOWNS) {
continue;
}
- qerror_report(QERR_INVALID_PARAMETER, client_arg_name);
- return -1;
+ error_setg(errp, QERR_INVALID_PARAMETER, client_arg_name);
+ return;
}
arg_type = qobject_to_qstring(obj);
case 'B':
case 's':
if (qobject_type(client_arg) != QTYPE_QSTRING) {
- qerror_report(QERR_INVALID_PARAMETER_TYPE, client_arg_name,
- "string");
- return -1;
+ error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
+ client_arg_name, "string");
+ return;
}
break;
case 'i':
case 'M':
case 'o':
if (qobject_type(client_arg) != QTYPE_QINT) {
- qerror_report(QERR_INVALID_PARAMETER_TYPE, client_arg_name,
- "int");
- return -1;
+ error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
+ client_arg_name, "int");
+ return;
}
break;
case 'T':
if (qobject_type(client_arg) != QTYPE_QINT
&& qobject_type(client_arg) != QTYPE_QFLOAT) {
- qerror_report(QERR_INVALID_PARAMETER_TYPE, client_arg_name,
- "number");
- return -1;
+ error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
+ client_arg_name, "number");
+ return;
}
break;
case 'b':
case '-':
if (qobject_type(client_arg) != QTYPE_QBOOL) {
- qerror_report(QERR_INVALID_PARAMETER_TYPE, client_arg_name,
- "bool");
- return -1;
+ error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
+ client_arg_name, "bool");
+ return;
}
break;
case 'O':
abort();
}
}
-
- return 0;
}
static QDict *qdict_from_args_type(const char *args_type) {
out: return qdict;
}
-static int qmp_check_client_args(const mon_cmd_t *cmd, QDict *client_args) {
- int flags, err;
+static void qmp_check_client_args(const mon_cmd_t *cmd, QDict *client_args, Error **errp)
+{
+ Error *err = NULL;
+ int flags;
QDict *cmd_args;
cmd_args = qdict_from_args_type(cmd->args_type);
flags = 0;
- err = check_mandatory_args(cmd_args, client_args, &flags);
+ check_mandatory_args(cmd_args, client_args, &flags, &err);
if (err) {
goto out;
}
- err = check_client_args_type(client_args, cmd_args, flags);
+ check_client_args_type(client_args, cmd_args, flags, &err);
- out:
+out:
+ error_propagate(errp, err);
QDECREF(cmd_args);
- return err;
}
-static QDict *qmp_check_input_obj(QObject *input_obj) {
+static QDict *qmp_check_input_obj(QObject *input_obj, Error **errp) {
const QDictEntry *ent;
int has_exec_key = 0;
QDict *input_dict;
if (qobject_type(input_obj) != QTYPE_QDICT) {
- qerror_report(QERR_QMP_BAD_INPUT_OBJECT, "object");
+ error_setg(errp, QERR_QMP_BAD_INPUT_OBJECT, "object");
return NULL;
}
if (!strcmp(arg_name, "execute")) {
if (qobject_type(arg_obj) != QTYPE_QSTRING) {
- qerror_report(QERR_QMP_BAD_INPUT_OBJECT_MEMBER, "execute",
- "string");
+ error_setg(errp, QERR_QMP_BAD_INPUT_OBJECT_MEMBER,
+ "execute", "string");
return NULL;
}
has_exec_key = 1;
} else if (!strcmp(arg_name, "arguments")) {
if (qobject_type(arg_obj) != QTYPE_QDICT) {
- qerror_report(QERR_QMP_BAD_INPUT_OBJECT_MEMBER, "arguments",
- "object");
+ error_setg(errp, QERR_QMP_BAD_INPUT_OBJECT_MEMBER,
+ "arguments", "object");
return NULL;
}
} else if (!strcmp(arg_name, "id")) {
+ /* Any string is acceptable as "id", so nothing to check */
} else if (!strcmp(arg_name, "type")) {
} else {
- qerror_report(QERR_QMP_EXTRA_MEMBER, arg_name);
+ error_setg(errp, QERR_QMP_EXTRA_MEMBER, arg_name);
return NULL;
}
}
if (!has_exec_key) {
- qerror_report(QERR_QMP_BAD_INPUT_OBJECT, "execute");
+ error_setg(errp, QERR_QMP_BAD_INPUT_OBJECT, "execute");
return NULL;
}
void handle_qmp_command(JSONMessageParser *parser, QList *tokens,
void *opaque) {
- int err;
+ Error *local_err = NULL;
QObject *obj;
QDict *input, *args;
const mon_cmd_t *cmd;
obj = json_parser_parse(tokens, NULL);
if (!obj) {
// FIXME: should be triggered in json_parser_parse()
- qerror_report(QERR_JSON_PARSING);
+ error_setg(&local_err, QERR_JSON_PARSING);
goto err_out;
}
- input = qmp_check_input_obj(obj);
+ input = qmp_check_input_obj(obj, &local_err);
if (!input) {
qobject_decref(obj);
goto err_out;
cmd = qmp_find_cmd(cmd_name);
if (!cmd) {
- qerror_report(QERR_COMMAND_NOT_FOUND, cmd_name);
+ error_set(&local_err, ERROR_CLASS_COMMAND_NOT_FOUND,
+ "The command %s has not been found", cmd_name);
goto err_out;
}
QINCREF(args);
}
- err = qmp_check_client_args(cmd, args);
- if (err < 0) {
+ qmp_check_client_args(cmd, args, &local_err);
+ if (local_err) {
goto err_out;
}
- if (handler_is_async(cmd)) {
- err = ecs_qmp_async_cmd_handler(clii, cmd, args);
- if (err) {
- /* emit the error response */
- goto err_out;
- }
- } else {
- ecs_qmp_call_cmd(clii, mon, type_name, cmd, args);
- }
+ ecs_qmp_call_cmd(clii, mon, type_name, cmd, args);
goto out;
err_out:
- ecs_protocol_emitter(clii, NULL, NULL);
+ ecs_protocol_emitter(clii, NULL, NULL, local_err);
out:
QDECREF(input);
QDECREF(args);