12910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner/*
2fd4c0076b7470f5962ff462bae9cd9f208e059b7David Turner * QError Module
32910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner *
42910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner * Copyright (C) 2009 Red Hat Inc.
52910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner *
62910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner * Authors:
72910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner *  Luiz Capitulino <lcapitulino@redhat.com>
82910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner *
92910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
102910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner * See the COPYING.LIB file in the top-level directory.
112910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner */
12fd4c0076b7470f5962ff462bae9cd9f208e059b7David Turner
136af6765e2f3bc930d0dce21d752bea570a1b1362David 'Digit' Turner#include "monitor/monitor.h"
141c31e3e43ce4cca85a707dfff631e5e102fdecedDavid 'Digit' Turner#include "qapi/qmp/qjson.h"
151c31e3e43ce4cca85a707dfff631e5e102fdecedDavid 'Digit' Turner#include "qapi/qmp/qerror.h"
162910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner#include "qemu-common.h"
172910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
182910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turnerstatic void qerror_destroy_obj(QObject *obj);
192910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
202910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turnerstatic const QType qerror_type = {
212910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    .code = QTYPE_QERROR,
222910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    .destroy = qerror_destroy_obj,
232910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner};
242910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
252910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner/**
262910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner * qerror_new(): Create a new QError
272910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner *
282910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner * Return strong reference.
292910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner */
30910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turnerstatic QError *qerror_new(void)
312910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner{
322910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    QError *qerr;
332910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
34aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    qerr = g_malloc0(sizeof(*qerr));
352910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    QOBJECT_INIT(qerr, &qerror_type);
362910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
372910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    return qerr;
382910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner}
392910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
402910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner/**
412910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner * qerror_from_info(): Create a new QError from error information
422910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner *
432910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner * Return strong reference.
442910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner */
45910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turnerstatic QError * GCC_FMT_ATTR(2, 0)
46910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turnerqerror_from_info(ErrorClass err_class, const char *fmt, va_list *va)
472910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner{
482910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    QError *qerr;
492910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
502910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    qerr = qerror_new();
51fd4c0076b7470f5962ff462bae9cd9f208e059b7David Turner    loc_save(&qerr->loc);
522910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
53910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner    qerr->err_msg = g_strdup_vprintf(fmt, *va);
54910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner    qerr->err_class = err_class;
552910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
562910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    return qerr;
572910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner}
582910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
592910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner/**
602910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner * qerror_human(): Format QError data into human-readable string.
612910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner */
622910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' TurnerQString *qerror_human(const QError *qerror)
632910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner{
64910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner    return qstring_from_str(qerror->err_msg);
652910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner}
662910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
672910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner/**
682910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner * qerror_print(): Print QError data
692910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner *
702910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner * This function will print the member 'desc' of the specified QError object,
71fd4c0076b7470f5962ff462bae9cd9f208e059b7David Turner * it uses error_report() for this, so that the output is routed to the right
722910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner * place (ie. stderr or Monitor's device).
732910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner */
74910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turnerstatic void qerror_print(QError *qerror)
752910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner{
762910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    QString *qstring = qerror_human(qerror);
77fd4c0076b7470f5962ff462bae9cd9f208e059b7David Turner    loc_push_restore(&qerror->loc);
78fd4c0076b7470f5962ff462bae9cd9f208e059b7David Turner    error_report("%s", qstring_get_str(qstring));
79fd4c0076b7470f5962ff462bae9cd9f208e059b7David Turner    loc_pop(&qerror->loc);
802910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    QDECREF(qstring);
812910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner}
822910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
83910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turnervoid qerror_report(ErrorClass eclass, const char *fmt, ...)
84fd4c0076b7470f5962ff462bae9cd9f208e059b7David Turner{
85fd4c0076b7470f5962ff462bae9cd9f208e059b7David Turner    va_list va;
86fd4c0076b7470f5962ff462bae9cd9f208e059b7David Turner    QError *qerror;
87fd4c0076b7470f5962ff462bae9cd9f208e059b7David Turner
88fd4c0076b7470f5962ff462bae9cd9f208e059b7David Turner    va_start(va, fmt);
89910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner    qerror = qerror_from_info(eclass, fmt, &va);
90fd4c0076b7470f5962ff462bae9cd9f208e059b7David Turner    va_end(va);
91fd4c0076b7470f5962ff462bae9cd9f208e059b7David Turner
92fd4c0076b7470f5962ff462bae9cd9f208e059b7David Turner    if (monitor_cur_is_qmp()) {
93fd4c0076b7470f5962ff462bae9cd9f208e059b7David Turner        monitor_set_error(cur_mon, qerror);
94fd4c0076b7470f5962ff462bae9cd9f208e059b7David Turner    } else {
95fd4c0076b7470f5962ff462bae9cd9f208e059b7David Turner        qerror_print(qerror);
96fd4c0076b7470f5962ff462bae9cd9f208e059b7David Turner        QDECREF(qerror);
97fd4c0076b7470f5962ff462bae9cd9f208e059b7David Turner    }
98fd4c0076b7470f5962ff462bae9cd9f208e059b7David Turner}
99fd4c0076b7470f5962ff462bae9cd9f208e059b7David Turner
100910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner/* Evil... */
101910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turnerstruct Error
102910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner{
103910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner    char *msg;
104910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner    ErrorClass err_class;
105910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner};
106910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner
107910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turnervoid qerror_report_err(Error *err)
108910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner{
109910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner    QError *qerr;
110910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner
111910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner    qerr = qerror_new();
112910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner    loc_save(&qerr->loc);
113910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner    qerr->err_msg = g_strdup(err->msg);
114910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner    qerr->err_class = err->err_class;
115910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner
116910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner    if (monitor_cur_is_qmp()) {
117910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner        monitor_set_error(cur_mon, qerr);
118910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner    } else {
119910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner        qerror_print(qerr);
120910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner        QDECREF(qerr);
121910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner    }
122910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner}
123910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner
124910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turnervoid assert_no_error(Error *err)
125910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner{
126910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner    if (err) {
127910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner        qerror_report_err(err);
128910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner        abort();
129910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner    }
130910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner}
131910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner
1322910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner/**
1332910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner * qobject_to_qerror(): Convert a QObject into a QError
1342910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner */
135910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turnerstatic QError *qobject_to_qerror(const QObject *obj)
1362910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner{
1372910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    if (qobject_type(obj) != QTYPE_QERROR) {
1382910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        return NULL;
1392910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    }
1402910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
1412910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    return container_of(obj, QError, base);
1422910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner}
1432910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
1442910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner/**
1452910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner * qerror_destroy_obj(): Free all memory allocated by a QError
1462910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner */
1472910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turnerstatic void qerror_destroy_obj(QObject *obj)
1482910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner{
1492910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    QError *qerr;
1502910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
1512910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    assert(obj != NULL);
1522910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    qerr = qobject_to_qerror(obj);
1532910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
154910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner    g_free(qerr->err_msg);
155aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    g_free(qerr);
1562910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner}
157