00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <iostream>
00012 #include <sstream>
00013 #include <errno.h>
00014 #include <unistd.h>
00015 #include <stdlib.h>
00016 #include <time.h>
00017 #include <math.h>
00018 #include <sysexits.h>
00019
00020 #include "ers/ers.h"
00021 #include "ers/HumanStream.h"
00022 #include <cstring>
00023 #include <typeinfo>
00024 #define BUFFER_SIZE 256
00025
00026 #define ISSUE_VALUE_SET_SCALAR(table,key,value) { std::ostringstream stream ; stream << value ; table[key] = stream.str(); }
00027
00032 namespace {
00033 ers::Issue *create_issue() { return new ers::Issue(); }
00034 bool registered = ers::IssueFactory::instance()->register_issue(ers::Issue::ISSUE_CLASS_NAME,create_issue) ;
00035 }
00036
00037 using namespace ers ;
00038
00039 const char* const Issue::CLASS_KEY = "ISSUE_CLASS" ;
00040 const char* const Issue::COMPILATION_TIME_KEY = "COMPILATION_TIME" ;
00041 const char* const Issue::COMPILATION_TARGET_KEY = "COMPILATION_TARGET" ;
00042 const char* const Issue::COMPILATION_DEBUG_LVL_KEY = "COMPILATION_DEBUG_LVL" ;
00043 const char* const Issue::COMPILER_KEY = "COMPILER" ;
00044 const char* const Issue::CPP_CLASS_KEY = "ISSUE_CPP_CLASS" ;
00045 const char* const Issue::ERS_VERSION_KEY = "ERS_VERSION" ;
00046 const char* const Issue::HOST_NAME_KEY = "HOST_NAME" ;
00047 const char* const Issue::HOST_TYPE_KEY = "HOST_TYPE" ;
00048 const char* const Issue::HOST_IP_ADDR_KEY = "HOST_IP" ;
00049 const char* const Issue::MESSAGE_KEY = "MESSAGE" ;
00050 const char* const Issue::PROCESS_ID_KEY = "PROCESS_ID" ;
00051 const char* const Issue::PROCESS_PWD_KEY = "PROCESS_PWD" ;
00052 const char* const Issue::PROGRAM_NAME_KEY = "PROGRAM_NAME";
00053 const char* const Issue::RESPONSIBILITY_KEY = "RESPONSIBILITY" ;
00054 const char* const Issue::SEVERITY_KEY = "SEVERITY" ;
00055 const char* const Issue::SOURCE_POSITION_KEY = "SOURCE_POSITION" ;
00056 const char* const Issue::SOURCE_PACKAGE_KEY = "SOURCE_PACKAGE" ;
00057 const char* const Issue::TIME_KEY = "TIME" ;
00058 const char* const Issue::TRANSIENCE_KEY = "TRANSIENCE" ;
00059 const char* const Issue::USER_ID_KEY = "USER_ID" ;
00060 const char* const Issue::USER_NAME_KEY = "USER_NAME" ;
00061 const char* const Issue::CAUSE_TEXT_KEY = "CAUSE_TEXT" ;
00062 const char* const Issue::CAUSE_PSEUDO_KEY = "CAUSE" ;
00063 const char* const Issue::QUALIFIER_LIST_KEY = "QUALIFIERS" ;
00064 const char* const Issue::EXIT_VALUE_KEY = "EXIT_VALUE" ;
00065
00066 const char* const Issue::ISSUE_CLASS_NAME = "ers::issue" ;
00067
00068
00069
00070
00074 Issue::Issue() {
00075 m_human_description.clear() ;
00076 m_cause = 0 ;
00077 }
00078
00085 Issue::Issue(const Issue &issue) : std::exception() {
00086 m_value_table = issue.m_value_table ;
00087 m_human_description = issue.m_human_description ;
00088 if (issue.m_cause) {
00089 this->m_cause = issue.m_cause->clone();
00090 } else {
00091 this->m_cause = 0 ;
00092 }
00093 }
00094
00099 Issue::Issue(const string_map_type &values) {
00100 cause();
00101 set_values(values);
00102 m_human_description.clear();
00103 }
00104
00105
00112 Issue::Issue(const Context &context, severity_t s, const std::string &m) {
00113 cause();
00114 setup_common(&context);
00115 severity(s);
00116 finish_setup(m);
00117 }
00118
00121 Issue::Issue(const Context &context, severity_t s) {
00122 cause();
00123 setup_common(&context);
00124 severity(s);
00125 }
00126
00133 Issue::Issue(const Context &context, severity_t s, const std::exception *cause_exception) {
00134 ERS_PRE_CHECK_PTR(cause_exception);
00135 cause(cause_exception);
00136 setup_common(&context);
00137 severity(s);
00138 finish_setup(cause_exception->what());
00139 }
00140
00145 Issue::~Issue() throw() {
00146 if (m_cause) delete m_cause ;
00147 m_cause = 0 ;
00148 }
00149
00150
00151
00152
00153
00154
00160 Issue *Issue::clone() const {
00161 return IssueFactory::instance()->build(this) ;
00162 }
00163
00164
00165 Issue::operator std::string() const {
00166 std::string s = human_description();
00167 return s ;
00168 }
00169
00176 Issue Issue::operator=(const Issue &source) {
00177 Issue target(source);
00178 return target ;
00179 }
00180
00186 bool Issue::operator==(const Issue &other) const throw() {
00187 if (m_value_table != other.m_value_table) return false ;
00188 if (m_cause == other.m_cause) return true ;
00189 return (*m_cause) == *(other.m_cause) ;
00190 }
00191
00198 const std::string & Issue::operator[](const std::string &key) const throw() {
00199 return get_value(key,"");
00200 }
00201
00202
00203
00204
00205
00206
00207
00208
00215 std::ostream& ers::operator<<(std::ostream& s, const Issue& i) {
00216 return s << i.human_description() ;
00217 }
00218
00226 Stream& ers::operator<<(Stream& s, const Issue& i) {
00227 s.send(&i);
00228 return s ;
00229 }
00230
00231
00232
00233
00234
00235
00240 const Issue *Issue::cause() const throw() {
00241 return m_cause ;
00242 }
00243
00252 void Issue::cause(const std::exception *c) {
00253 if (c==0) {
00254 m_cause = 0 ;
00255 return ;
00256 }
00257 const Issue *i = dynamic_cast<const Issue *>(c) ;
00258 if (i) {
00259 m_cause = i->clone();
00260 } else {
00261 m_cause = 0 ;
00262 }
00263 set_value(CAUSE_TEXT_KEY,c->what());
00264 }
00265
00266
00267
00268
00269
00274 const string_map_type* Issue::get_value_table() const {
00275 return &m_value_table ;
00276 }
00277
00283 const std::string &Issue::get_value(const std::string &key, const std::string &def) const throw() {
00284 string_map_type::const_iterator pos = m_value_table.find(key);
00285 if (pos!=m_value_table.end()) {
00286 return pos->second ;
00287 }
00288 return def ;
00289 }
00290
00294 const std::string &Issue::get_value(const std::string &key) const throw() {
00295 return get_value(key,Core::empty_string) ;
00296 }
00297
00298
00305 int Issue::get_int_value(const std::string &key, int def) const throw() {
00306 std::string v = get_value(key) ;
00307 if (! v.empty()) {
00308 std::istringstream in(v) ;
00309 int n ;
00310 in >> n ;
00311 return n ;
00312
00313 } else {
00314 return def ;
00315 }
00316 }
00317
00318
00325 long Issue::get_long_value(const std::string &key, long def) const throw() {
00326 std::string v = get_value(key) ;
00327 if (! v.empty()) {
00328 std::istringstream in(v) ;
00329 long n ;
00330 in >> n ;
00331 return n ;
00332
00333 } else {
00334 return def ;
00335 }
00336 }
00337
00344 double Issue::get_double_value(const std::string key, double def=nan("")) const throw() {
00345 std::string v = get_value(key) ;
00346 if (! v.empty()) {
00347 std::istringstream in(v) ;
00348 double n ;
00349 in >> n ;
00350 return n ;
00351
00352 } else {
00353 return def ;
00354 }
00355 }
00356
00357
00362 void Issue::set_values(const string_map_type &values) throw() {
00363 m_value_table = values ;
00364 }
00365
00371 void Issue::set_value(const std::string &key, uint8_t value) throw() {
00372 ISSUE_VALUE_SET_SCALAR(m_value_table,key,value);
00373 }
00374
00377 void Issue::set_value(const std::string &key, uint16_t value) throw() {
00378 ISSUE_VALUE_SET_SCALAR(m_value_table,key,value);
00379 }
00380
00383 void Issue::set_value(const std::string &key, uint32_t value) throw() {
00384 ISSUE_VALUE_SET_SCALAR(m_value_table,key,value);
00385 }
00386
00389 void Issue::set_value(const std::string &key, uint64_t value) throw() {
00390 ISSUE_VALUE_SET_SCALAR(m_value_table,key,value);
00391 }
00392
00395 void Issue::set_value(const std::string &key, int8_t value) throw() {
00396 ISSUE_VALUE_SET_SCALAR(m_value_table,key,value);
00397 }
00398
00401 void Issue::set_value(const std::string &key, int16_t value) throw() {
00402 ISSUE_VALUE_SET_SCALAR(m_value_table,key,value);
00403 }
00404
00407 void Issue::set_value(const std::string &key, int32_t value) throw() {
00408 ISSUE_VALUE_SET_SCALAR(m_value_table,key,value);
00409 }
00410
00413 void Issue::set_value(const std::string &key, int64_t value) throw() {
00414 ISSUE_VALUE_SET_SCALAR(m_value_table,key,value);
00415 }
00416
00422 void Issue::set_value(const std::string &key, double value) throw() {
00423 std::ostringstream stream ;
00424 stream << value ;
00425 m_value_table[key] = stream.str();
00426 }
00427
00433 void Issue::set_value(const std::string &key, const std::string &value) throw() {
00434 if (! value.empty()) {
00435 m_value_table[key] = value ;
00436 }
00437 }
00438
00444 void Issue::set_value(const std::string &key, const char* value) throw() {
00445 if (value) {
00446 std::string value_str = std::string(value) ;
00447 set_value(key,value_str);
00448 }
00449 }
00450
00457 void Issue::set_value(const std::string &key, const void* ptr) throw() {
00458 std::ostringstream stream ;
00459 stream.setf(std::ios::hex,std::ios::basefield);
00460 stream << (unsigned long) ptr ;
00461 m_value_table[key] = stream.str();
00462 }
00463
00464
00469 int Issue::values_number() const {
00470 return m_value_table.size();
00471 }
00472
00473
00474
00475
00476
00481 void Issue::insert(const Context *context) throw() {
00482 if (context) {
00483 set_value(SOURCE_POSITION_KEY,context->position()) ;
00484 set_value(SOURCE_PACKAGE_KEY,context->package_name());
00485 set_value(COMPILER_KEY,context->compiler()) ;
00486 set_value(COMPILATION_TIME_KEY,context->compilation()) ;
00487 set_value(COMPILATION_TARGET_KEY,context->host_type()) ;
00488 int lvl = ers::Context::debug_level();
00489 if (lvl>=0) {
00490 set_value(COMPILATION_DEBUG_LVL_KEY,lvl);
00491 }
00492 int frame_number = context->stack_frames();
00493 for(int i=0;i<frame_number;i++) {
00494 char key_buffer[256] ;
00495 snprintf(key_buffer,sizeof(key_buffer),"SOURCE-STACK-%03x",i);
00496 set_value(key_buffer,context->stack_frame(i));
00497 }
00498 std::vector<std::string> qualifs = context->qualifiers() ;
00499 std::vector<std::string>::const_iterator pos ;
00500 for(pos=qualifs.begin();pos!=qualifs.end();pos++) {
00501 add_qualifier(*pos) ;
00502 }
00503 }
00504 }
00505
00509 void Issue::insert_time() throw() {
00510 time_t now ;
00511 time(&now);
00512 char time_buffer[BUFFER_SIZE] ;
00513 ctime_r(&now,time_buffer) ;
00514 char *cr = strchr(time_buffer,'\n');
00515 if (cr) {
00516 *cr = '\0' ;
00517 }
00518 set_value(TIME_KEY,time_buffer);
00519 }
00520
00521
00522
00523
00524
00535 void Issue::setup_common(const Context *context) throw() {
00536 const int errno_copy = errno ;
00537 insert(context);
00538 insert_time();
00539 errno = errno_copy ;
00540 }
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00568 void Issue::finish_setup(const std::string &msg) throw() {
00569
00570 set_value(CLASS_KEY, get_class_name()) ;
00571 set_value(MESSAGE_KEY,msg);
00572 }
00573
00574
00575
00576
00577
00578
00579
00587 const char*Issue::get_class_name() const throw() {
00588 if (m_class_name.empty()) {
00589 const Issue *p = this ;
00590 m_class_name = ers::Core::umangle_gcc_class_name((typeid(*p)).name()).c_str();
00591 if (m_class_name.empty()) {
00592 m_class_name=ISSUE_CLASS_NAME ;
00593 }
00594 }
00595 return m_class_name.c_str() ;
00596 }
00597
00602 severity_t Issue::severity() const throw() {
00603 std::string value = get_value(SEVERITY_KEY);
00604 return ers::Core::parse_severity(value);
00605 }
00606
00611 void Issue::severity(severity_t s) {
00612 set_value(SEVERITY_KEY,ers::Core::to_string(s));
00613 }
00614
00619 bool Issue::is_error() {
00620 severity_t s = severity();
00621 return (s==ers::error || s== ers::fatal) ;
00622 }
00623
00628 std::string Issue::severity_message() const {
00629 return get_value(SEVERITY_KEY);
00630 }
00631
00632
00637 responsibility_t Issue::responsibility() const throw() {
00638 std::string value = this->get_value(RESPONSIBILITY_KEY);
00639 return ers::Core::parse_responsibility(value);
00640 }
00641
00646 void Issue::responsibility(responsibility_t r) {
00647 set_value(RESPONSIBILITY_KEY,ers::Core::to_string(r)) ;
00648 }
00649
00650
00655 void Issue::transience(bool tr) {
00656 set_value(TRANSIENCE_KEY,ers::Core::to_string(tr)) ;
00657 }
00658
00662 int Issue::transience() const throw () {
00663 std::string value = this->get_value(TRANSIENCE_KEY);
00664 return ers::Core::parse_boolean(value.c_str());
00665 }
00666
00667
00672 const std::string &Issue::human_description() const throw() {
00673 if (m_human_description.empty()) {
00674 m_human_description = HumanStream::to_string(this) ;
00675 }
00676 return m_human_description ;
00677 }
00678
00684 const char *Issue::what() const throw() {
00685 std::string desr = human_description() ;
00686 return desr.c_str();
00687 }
00688
00689 const std::string &Issue::message() const throw() {
00690 return get_value(MESSAGE_KEY) ;
00691 }
00692
00693 int Issue::exit_value() const throw() {
00694 int v = 1 ;
00695 if (transience()==1) v = EX_TEMPFAIL ;
00696 return get_int_value(EXIT_VALUE_KEY,v);
00697 }
00698
00703 void Issue::add_qualifier(const std::string &qualif) {
00704 const std::string &qualif_s = get_value(QUALIFIER_LIST_KEY) ;
00705 std::string::size_type pos = qualif_s.find(qualif);
00706 if (pos!=std::string::npos) return ;
00707 std::string n_qualif = qualif_s+qualif + " " ;
00708 set_value(QUALIFIER_LIST_KEY,n_qualif);
00709 }
00710
00715 std::vector<std::string> Issue::qualifiers() const {
00716 const std::string &qualif_s = get_value(QUALIFIER_LIST_KEY) ;
00717 return ers::Core::tokenize(qualif_s,", \t");
00718 }
00719
00720
00721
00722
00723
00724
00725