/* Copyright (C) 2014 InfiniDB, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /****************************************************************************************** * $Id: idberrorinfo.cpp 3626 2013-03-11 15:36:08Z xlou $ * ******************************************************************************************/ #include <iostream> #include <iomanip> #include <string> #include <iterator> #include <sstream> #include <stdexcept> #include <map> #include <fstream> using namespace std; #include <boost/format.hpp> #include <boost/tokenizer.hpp> #include <boost/thread.hpp> using namespace boost; #include "mcsconfig.h" #include "configcpp.h" using namespace config; #include "loggingid.h" #include "logger.h" #include "idberrorinfo.h" #include "installdir.h" namespace logging { IDBErrorInfo* IDBErrorInfo::fInstance = 0; boost::mutex mx; IDBErrorInfo* IDBErrorInfo::instance() { boost::mutex::scoped_lock lk(mx); if (!fInstance) fInstance = new IDBErrorInfo(); return fInstance; } IDBErrorInfo::IDBErrorInfo() { Config* cf = Config::makeConfig(); string configFile(cf->getConfig("SystemConfig", "ErrorMessageFile")); if (configFile.length() == 0) configFile = std::string(MCSSYSCONFDIR) + "/columnstore/ErrorMessage.txt"; ifstream msgFile(configFile.c_str()); while (msgFile.good()) { stringbuf* sb = new stringbuf; msgFile.get(*sb); string m = sb->str(); delete sb; if (m.length() > 0 && m[0] != '#') { typedef boost::tokenizer<boost::char_separator<char> > tokenizer; boost::char_separator<char> sep("\t"); tokenizer tokens(m, sep); tokenizer::iterator tok_iter = tokens.begin(); if (tok_iter != tokens.end()) { int msgid = atoi(tok_iter->c_str()); ++tok_iter; if (tok_iter != tokens.end()) { ++tok_iter; if (tok_iter != tokens.end()) { string msgtext = *tok_iter; fErrMap[msgid] = msgtext; } } } } ios_base::iostate st = msgFile.rdstate(); if ((st & ios_base::failbit) && !(st & ios_base::eofbit)) msgFile.clear(); (void)msgFile.get(); } } IDBErrorInfo::~IDBErrorInfo() { } string IDBErrorInfo::errorMsg(const unsigned eid, const Message::Args& args) { string errMsg = lookupError(eid); format(errMsg, args); return errMsg; } string IDBErrorInfo::errorMsg(const unsigned eid) { string errMsg = lookupError(eid); Message::Args args; // empty args format(errMsg, args); return errMsg; } string IDBErrorInfo::errorMsg(const unsigned eid, int i) { string errMsg = lookupError(eid); Message::Args args; args.add(i); format(errMsg, args); return errMsg; } string IDBErrorInfo::errorMsg(const unsigned eid, const string& s) { string errMsg = lookupError(eid); Message::Args args; args.add(s); format(errMsg, args); return errMsg; } string IDBErrorInfo::logError(const logging::LOG_TYPE logLevel, const logging::LoggingID logid, const unsigned eid, const logging::Message::Args& args) { Logger logger(logid.fSubsysID); Message message(errorMsg(eid, args)); return logger.logMessage(logLevel, message, logid); } void IDBErrorInfo::format(string& errMsg, const Message::Args& args) { Message::Args::AnyVec::const_iterator iter = args.args().begin(); Message::Args::AnyVec::const_iterator end = args.args().end(); boost::format fmt(errMsg); fmt.exceptions(boost::io::no_error_bits); while (iter != end) { if (iter->type() == typeid(long)) { long l = any_cast<long>(*iter); fmt % l; } else if (iter->type() == typeid(uint64_t)) { uint64_t u64 = any_cast<uint64_t>(*iter); fmt % u64; } else if (iter->type() == typeid(double)) { double d = any_cast<double>(*iter); fmt % d; } else if (iter->type() == typeid(string)) { string s = any_cast<string>(*iter); fmt % s; } else { throw logic_error("IDBErrorInfo::format: unexpected type in argslist"); } ++iter; } errMsg = fmt.str(); } /* static */ string IDBErrorInfo::lookupError(const unsigned eid) { string msgstr; ErrorMap::const_iterator iter = fErrMap.find(eid); if (iter == fErrMap.end()) msgstr = "Unknown Error %1% %2% %3% %4% %5%"; else msgstr = iter->second; ostringstream oss; oss << "IDB-" << setw(4) << setfill('0') << eid << ": " << msgstr; return oss.str(); } }