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