2009-11-19 02:05:30 +01:00
|
|
|
/*
|
2010-05-12 21:34:42 +02:00
|
|
|
* QError Module
|
2009-11-19 02:05:30 +01:00
|
|
|
*
|
|
|
|
* Copyright (C) 2009 Red Hat Inc.
|
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* Luiz Capitulino <lcapitulino@redhat.com>
|
|
|
|
*
|
|
|
|
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
|
|
|
* See the COPYING.LIB file in the top-level directory.
|
|
|
|
*/
|
2010-03-22 10:29:05 +01:00
|
|
|
|
|
|
|
#include "monitor.h"
|
2009-11-19 02:05:30 +01:00
|
|
|
#include "qjson.h"
|
|
|
|
#include "qerror.h"
|
|
|
|
#include "qemu-common.h"
|
|
|
|
|
|
|
|
static void qerror_destroy_obj(QObject *obj);
|
|
|
|
|
|
|
|
static const QType qerror_type = {
|
|
|
|
.code = QTYPE_QERROR,
|
|
|
|
.destroy = qerror_destroy_obj,
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* qerror_new(): Create a new QError
|
|
|
|
*
|
|
|
|
* Return strong reference.
|
|
|
|
*/
|
2012-07-19 22:29:34 +02:00
|
|
|
static QError *qerror_new(void)
|
2009-11-19 02:05:30 +01:00
|
|
|
{
|
|
|
|
QError *qerr;
|
|
|
|
|
2011-08-21 05:09:37 +02:00
|
|
|
qerr = g_malloc0(sizeof(*qerr));
|
2009-11-19 02:05:30 +01:00
|
|
|
QOBJECT_INIT(qerr, &qerror_type);
|
|
|
|
|
|
|
|
return qerr;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* qerror_from_info(): Create a new QError from error information
|
|
|
|
*
|
|
|
|
* Return strong reference.
|
|
|
|
*/
|
2012-07-27 19:09:29 +02:00
|
|
|
static QError *qerror_from_info(ErrorClass err_class, const char *fmt,
|
|
|
|
va_list *va)
|
2009-11-19 02:05:30 +01:00
|
|
|
{
|
|
|
|
QError *qerr;
|
|
|
|
|
|
|
|
qerr = qerror_new();
|
2010-02-18 19:46:49 +01:00
|
|
|
loc_save(&qerr->loc);
|
2009-11-19 02:05:30 +01:00
|
|
|
|
2012-07-27 22:51:03 +02:00
|
|
|
qerr->err_msg = g_strdup_vprintf(fmt, *va);
|
2012-07-27 19:09:29 +02:00
|
|
|
qerr->err_class = err_class;
|
2009-11-19 02:05:30 +01:00
|
|
|
|
|
|
|
return qerr;
|
|
|
|
}
|
|
|
|
|
2011-06-01 19:14:47 +02:00
|
|
|
/**
|
|
|
|
* qerror_human(): Format QError data into human-readable string.
|
|
|
|
*/
|
|
|
|
QString *qerror_human(const QError *qerror)
|
|
|
|
{
|
2012-07-20 17:02:58 +02:00
|
|
|
return qstring_from_str(qerror->err_msg);
|
2011-06-01 19:14:47 +02:00
|
|
|
}
|
|
|
|
|
2009-12-07 21:37:16 +01:00
|
|
|
/**
|
|
|
|
* qerror_print(): Print QError data
|
|
|
|
*
|
|
|
|
* This function will print the member 'desc' of the specified QError object,
|
2010-02-18 17:25:24 +01:00
|
|
|
* it uses error_report() for this, so that the output is routed to the right
|
2009-12-07 21:37:16 +01:00
|
|
|
* place (ie. stderr or Monitor's device).
|
|
|
|
*/
|
2012-07-19 22:29:34 +02:00
|
|
|
static void qerror_print(QError *qerror)
|
2009-12-07 21:37:16 +01:00
|
|
|
{
|
|
|
|
QString *qstring = qerror_human(qerror);
|
2010-02-18 19:46:49 +01:00
|
|
|
loc_push_restore(&qerror->loc);
|
2010-02-18 17:25:24 +01:00
|
|
|
error_report("%s", qstring_get_str(qstring));
|
2010-02-18 19:46:49 +01:00
|
|
|
loc_pop(&qerror->loc);
|
2009-11-19 02:05:30 +01:00
|
|
|
QDECREF(qstring);
|
|
|
|
}
|
|
|
|
|
2012-07-27 19:09:29 +02:00
|
|
|
void qerror_report(ErrorClass eclass, const char *fmt, ...)
|
2010-03-22 10:29:05 +01:00
|
|
|
{
|
|
|
|
va_list va;
|
|
|
|
QError *qerror;
|
|
|
|
|
|
|
|
va_start(va, fmt);
|
2012-07-27 19:09:29 +02:00
|
|
|
qerror = qerror_from_info(eclass, fmt, &va);
|
2010-03-22 10:29:05 +01:00
|
|
|
va_end(va);
|
|
|
|
|
|
|
|
if (monitor_cur_is_qmp()) {
|
|
|
|
monitor_set_error(cur_mon, qerror);
|
|
|
|
} else {
|
|
|
|
qerror_print(qerror);
|
|
|
|
QDECREF(qerror);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-02 19:34:45 +02:00
|
|
|
/* Evil... */
|
|
|
|
struct Error
|
|
|
|
{
|
|
|
|
char *msg;
|
2012-07-27 19:09:29 +02:00
|
|
|
ErrorClass err_class;
|
2011-09-02 19:34:45 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
void qerror_report_err(Error *err)
|
|
|
|
{
|
|
|
|
QError *qerr;
|
|
|
|
|
|
|
|
qerr = qerror_new();
|
|
|
|
loc_save(&qerr->loc);
|
2012-07-20 18:43:37 +02:00
|
|
|
qerr->err_msg = g_strdup(err->msg);
|
2012-07-27 19:09:29 +02:00
|
|
|
qerr->err_class = err->err_class;
|
2011-09-02 19:34:45 +02:00
|
|
|
|
|
|
|
if (monitor_cur_is_qmp()) {
|
|
|
|
monitor_set_error(cur_mon, qerr);
|
|
|
|
} else {
|
|
|
|
qerror_print(qerr);
|
|
|
|
QDECREF(qerr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-14 10:19:53 +01:00
|
|
|
void assert_no_error(Error *err)
|
|
|
|
{
|
|
|
|
if (err) {
|
|
|
|
qerror_report_err(err);
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-11-19 02:05:30 +01:00
|
|
|
/**
|
|
|
|
* qobject_to_qerror(): Convert a QObject into a QError
|
|
|
|
*/
|
2012-07-19 22:29:34 +02:00
|
|
|
static QError *qobject_to_qerror(const QObject *obj)
|
2009-11-19 02:05:30 +01:00
|
|
|
{
|
|
|
|
if (qobject_type(obj) != QTYPE_QERROR) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return container_of(obj, QError, base);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* qerror_destroy_obj(): Free all memory allocated by a QError
|
|
|
|
*/
|
|
|
|
static void qerror_destroy_obj(QObject *obj)
|
|
|
|
{
|
|
|
|
QError *qerr;
|
|
|
|
|
|
|
|
assert(obj != NULL);
|
|
|
|
qerr = qobject_to_qerror(obj);
|
|
|
|
|
2012-07-20 17:02:58 +02:00
|
|
|
g_free(qerr->err_msg);
|
2011-08-21 05:09:37 +02:00
|
|
|
g_free(qerr);
|
2009-11-19 02:05:30 +01:00
|
|
|
}
|