⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ncbidiag.cpp

📁 ncbi源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/* * =========================================================================== * PRODUCTION $Log: ncbidiag.cpp,v $ * PRODUCTION Revision 1000.4  2004/06/01 19:08:57  gouriano * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.80 * PRODUCTION * =========================================================================== *//*  $Id: ncbidiag.cpp,v 1000.4 2004/06/01 19:08:57 gouriano Exp $ * =========================================================================== * *                            PUBLIC DOMAIN NOTICE *               National Center for Biotechnology Information * *  This software/database is a "United States Government Work" under the *  terms of the United States Copyright Act.  It was written as part of *  the author's official duties as a United States Government employee and *  thus cannot be copyrighted.  This software/database is freely available *  to the public for use. The National Library of Medicine and the U.S. *  Government have not placed any restriction on its use or reproduction. * *  Although all reasonable efforts have been taken to ensure the accuracy *  and reliability of the software and data, the NLM and the U.S. *  Government do not and cannot warrant the performance or results that *  may be obtained by using this software or data. The NLM and the U.S. *  Government disclaim all warranties, express or implied, including *  warranties of performance, merchantability or fitness for any particular *  purpose. * *  Please cite the author in any work or product based on this material. * * =========================================================================== * * Author:  Denis Vakatov * * File Description: *   NCBI C++ diagnostic API * */#include <ncbi_pch.hpp>#include <ncbiconf.h>#include <corelib/ncbidiag.hpp>#include <corelib/ncbithr.hpp>#include <corelib/ncbimtx.hpp>#include <corelib/ncbi_safe_static.hpp>#include <corelib/ncbiexpt.hpp>#include <stdlib.h>#include <time.h>#include <stack>#if defined(NCBI_OS_MAC)#  include <corelib/ncbi_os_mac.hpp>#endifBEGIN_NCBI_SCOPEDEFINE_STATIC_MUTEX(s_DiagMutex);#if defined(NCBI_POSIX_THREADS) && defined(HAVE_PTHREAD_ATFORK)#include <unistd.h> // for pthread_atfork()extern "C" {    static void s_NcbiDiagPreFork(void)    {        s_DiagMutex.Lock();    }    static void s_NcbiDiagPostFork(void)    {        s_DiagMutex.Unlock();    }}#endif/////////////////////////////////////////////////////////  CDiagRecycler::class CDiagRecycler {public:    CDiagRecycler(void)    {#if defined(NCBI_POSIX_THREADS) && defined(HAVE_PTHREAD_ATFORK)        pthread_atfork(s_NcbiDiagPreFork,   // before                       s_NcbiDiagPostFork,  // after in parent                       s_NcbiDiagPostFork); // after in child#endif    }    ~CDiagRecycler(void)    {        SetDiagHandler(0, false);        SetDiagErrCodeInfo(0, false);    }};static CSafeStaticPtr<CDiagRecycler> s_DiagRecycler;/////////////////////////////////////////////////////////  CDiagBuffer::#if defined(NDEBUG)EDiagSev       CDiagBuffer::sm_PostSeverity       = eDiag_Error;#elseEDiagSev       CDiagBuffer::sm_PostSeverity       = eDiag_Warning;#endif /* else!NDEBUG */EDiagSevChange CDiagBuffer::sm_PostSeverityChange = eDiagSC_Unknown;                                                  // to be set on first requestTDiagPostFlags CDiagBuffer::sm_PostFlags          =    eDPF_Prefix | eDPF_Severity | eDPF_ErrCode | eDPF_ErrSubCode |     eDPF_ErrCodeMessage | eDPF_ErrCodeExplanation | eDPF_ErrCodeUseSeverity;TDiagPostFlags CDiagBuffer::sm_TraceFlags         = eDPF_Trace;EDiagSev       CDiagBuffer::sm_DieSeverity        = eDiag_Fatal;EDiagTrace     CDiagBuffer::sm_TraceDefault       = eDT_Default;bool           CDiagBuffer::sm_TraceEnabled;     // to be set on first requestconst char*    CDiagBuffer::sm_SeverityName[eDiag_Trace+1] = {    "Info", "Warning", "Error", "Critical", "Fatal", "Trace" };// Use s_DefaultHandler only for purposes of comparison, as installing// another handler will normally delete it.CDiagHandler*      s_DefaultHandler = new CStreamDiagHandler(&NcbiCerr);CDiagHandler*      CDiagBuffer::sm_Handler = s_DefaultHandler;bool               CDiagBuffer::sm_CanDeleteHandler = true;CDiagErrCodeInfo*  CDiagBuffer::sm_ErrCodeInfo = 0;bool               CDiagBuffer::sm_CanDeleteErrCodeInfo = false;CDiagBuffer::CDiagBuffer(void)    : m_Stream(new CNcbiOstrstream){    m_Diag = 0;}CDiagBuffer::~CDiagBuffer(void){#if (_DEBUG > 1)    if (m_Diag  ||  dynamic_cast<CNcbiOstrstream*>(m_Stream)->pcount())        Abort();#endif    delete m_Stream;    m_Stream = 0;}void CDiagBuffer::DiagHandler(SDiagMessage& mess){    if ( CDiagBuffer::sm_Handler ) {        CMutexGuard LOCK(s_DiagMutex);        if ( CDiagBuffer::sm_Handler ) {            mess.m_Prefix = GetDiagBuffer().m_PostPrefix.empty() ?                0 : GetDiagBuffer().m_PostPrefix.c_str();            CDiagBuffer::sm_Handler->Post(mess);        }    }}bool CDiagBuffer::SetDiag(const CNcbiDiag& diag){    if ( !m_Stream ) {        return false;    }    // Check severity level change status    if ( sm_PostSeverityChange == eDiagSC_Unknown ) {        GetSeverityChangeEnabledFirstTime();    }    if (diag.GetSeverity() < sm_PostSeverity  ||        (diag.GetSeverity() == eDiag_Trace  &&  !GetTraceEnabled())) {        return false;    }    if (m_Diag != &diag) {        if ( dynamic_cast<CNcbiOstrstream*>(m_Stream)->pcount() ) {            Flush();        }        m_Diag = &diag;    }    return true;}void CDiagBuffer::Flush(void){    if ( !m_Diag )        return;    CNcbiOstrstream* ostr = dynamic_cast<CNcbiOstrstream*>(m_Stream);    EDiagSev sev = m_Diag->GetSeverity();    if ( ostr->pcount() ) {        const char* message = ostr->str();        size_t size = ostr->pcount();        ostr->rdbuf()->freeze(false);        TDiagPostFlags flags = m_Diag->GetPostFlags();        if (sev == eDiag_Trace) {            flags |= sm_TraceFlags;        } else if (sev == eDiag_Fatal) {            // normally only happens once, so might as well pull everything            // in for the record...            flags |= sm_TraceFlags | eDPF_Trace;        }        string dest;        if (IsSetDiagPostFlag(eDPF_PreMergeLines, flags)) {            string src(message,0,size);            NStr::Replace(NStr::Replace(src,"\r",""),"\n",";", dest);            message = dest.c_str();            size = dest.length();        }        SDiagMessage mess            (sev, message, size,             m_Diag->GetFile(), m_Diag->GetLine(), flags,             0, m_Diag->GetErrorCode(), m_Diag->GetErrorSubCode());        DiagHandler(mess);#if defined(NCBI_COMPILER_KCC)        // KCC's implementation of "freeze(false)" makes the ostrstream buffer        // stuck.  We need to replace the frozen stream with the new one.        delete ostr;        m_Stream = new CNcbiOstrstream;#endif        Reset(*m_Diag);    }    if (sev >= sm_DieSeverity  &&  sev != eDiag_Trace) {        m_Diag = 0;#if defined(NCBI_OS_MAC)        if ( g_Mac_SpecialEnvironment ) {            throw runtime_error("Application aborted.");        }#endif        Abort();    }}bool CDiagBuffer::GetTraceEnabledFirstTime(void){    CMutexGuard LOCK(s_DiagMutex);    const char* str = ::getenv(DIAG_TRACE);    if (str  &&  *str) {        sm_TraceDefault = eDT_Enable;    } else {        sm_TraceDefault = eDT_Disable;    }    sm_TraceEnabled = (sm_TraceDefault == eDT_Enable);    return sm_TraceEnabled;}bool CDiagBuffer::GetSeverityChangeEnabledFirstTime(void){    CMutexGuard LOCK(s_DiagMutex);    if ( sm_PostSeverityChange != eDiagSC_Unknown ) {        return sm_PostSeverityChange == eDiagSC_Enable;    }    const char* str = ::getenv(DIAG_POST_LEVEL);    EDiagSev sev;    if (str  &&  *str  &&  CNcbiDiag::StrToSeverityLevel(str, sev)) {        SetDiagFixedPostLevel(sev);    } else {        sm_PostSeverityChange = eDiagSC_Enable;    }    return sm_PostSeverityChange == eDiagSC_Enable;}void CDiagBuffer::UpdatePrefix(void){    m_PostPrefix.erase();    ITERATE(TPrefixList, prefix, m_PrefixList) {        if (prefix != m_PrefixList.begin()) {            m_PostPrefix += "::";        }        m_PostPrefix += *prefix;    }}/////////////////////////////////////////////////////////  CDiagMessage::void SDiagMessage::Write(string& str, TDiagWriteFlags flags) const{    CNcbiOstrstream ostr;    Write(ostr, flags);    ostr.put('\0');    str = ostr.str();    ostr.rdbuf()->freeze(false);}CNcbiOstream& SDiagMessage::Write(CNcbiOstream&   os,                                  TDiagWriteFlags flags) const{    if (IsSetDiagPostFlag(eDPF_MergeLines, m_Flags)) {        CNcbiOstrstream ostr;        string src, dest;        x_Write(ostr, fNoEndl);        ostr.put('\0');        src = ostr.str();        ostr.rdbuf()->freeze(false);        NStr::Replace(NStr::Replace(src,"\r",""),"\n","", dest);        os << dest;        if ((flags & fNoEndl) == 0) {            os << NcbiEndl;        }        return os;    } else {        return x_Write(os, flags);    }}CNcbiOstream& SDiagMessage::x_Write(CNcbiOstream& os,                                    TDiagWriteFlags flags) const{    // Date & time    if (IsSetDiagPostFlag(eDPF_DateTime, m_Flags)) {        static const char timefmt[] = "%D %T ";        time_t t = time(0);        char datetime[32];        struct tm* tm;#ifdef HAVE_LOCALTIME_R        struct tm temp;        localtime_r(&t, &temp);        tm = &temp;#else        tm = localtime(&t);#endif /*HAVE_LOCALTIME_R*/        NStr::strftime(datetime, sizeof(datetime), timefmt, tm);        os << datetime;    }    // "<file>"    bool print_file = (m_File  &&  *m_File  &&                       IsSetDiagPostFlag(eDPF_File, m_Flags));    if ( print_file ) {        const char* x_file = m_File;        if ( !IsSetDiagPostFlag(eDPF_LongFilename, m_Flags) ) {            for (const char* s = m_File;  *s;  s++) {                if (*s == '/'  ||  *s == '\\'  ||  *s == ':')                    x_file = s + 1;            }        }        os << '"' << x_file << '"';    }    // , line <line>    bool print_line = (m_Line  &&  IsSetDiagPostFlag(eDPF_Line, m_Flags));    if ( print_line )        os << (print_file ? ", line " : "line ") << m_Line;    // :    if (print_file  ||  print_line)        os << ": ";    // Get error code description    bool have_description = false;    SDiagErrCodeDescription description;    if ((m_ErrCode  ||  m_ErrSubCode)  &&        (IsSetDiagPostFlag(eDPF_ErrCodeMessage, m_Flags)  ||          IsSetDiagPostFlag(eDPF_ErrCodeExplanation, m_Flags)  ||         IsSetDiagPostFlag(eDPF_ErrCodeUseSeverity, m_Flags))  &&         IsSetDiagErrCodeInfo()) {        CDiagErrCodeInfo* info = GetDiagErrCodeInfo();        if ( info  &&              info->GetDescription(ErrCode(m_ErrCode, m_ErrSubCode),                                   &description) ) {            have_description = true;            if (IsSetDiagPostFlag(eDPF_ErrCodeUseSeverity, m_Flags) &&                 description.m_Severity != -1 )                m_Severity = (EDiagSev)description.m_Severity;        }    }    // <severity>:    if (IsSetDiagPostFlag(eDPF_Severity, m_Flags)  &&        (m_Severity != eDiag_Info || !IsSetDiagPostFlag(eDPF_OmitInfoSev)))        os << CNcbiDiag::SeverityName(m_Severity) << ": ";    // (<err_code>.<err_subcode>) or (err_text)    if ((m_ErrCode  ||  m_ErrSubCode || m_ErrText)  &&        IsSetDiagPostFlag(eDPF_ErrCode, m_Flags)) {        os << '(';        if (m_ErrText) {            os << m_ErrText;        } else {            os << m_ErrCode;            if ( IsSetDiagPostFlag(eDPF_ErrSubCode, m_Flags)) {                os << '.' << m_ErrSubCode;            }        }        os << ") ";    }    // [<prefix1>::<prefix2>::.....]    if (m_Prefix  &&  *m_Prefix  &&  IsSetDiagPostFlag(eDPF_Prefix, m_Flags))        os << '[' << m_Prefix << "] ";    // <message>    if (m_BufferLen)        os.write(m_Buffer, m_BufferLen);    // <err_code_message> and <err_code_explanation>    if (have_description) {        if (IsSetDiagPostFlag(eDPF_ErrCodeMessage, m_Flags) &&            !description.m_Message.empty())            os << NcbiEndl << description.m_Message << ' ';        if (IsSetDiagPostFlag(eDPF_ErrCodeExplanation, m_Flags) &&            !description.m_Explanation.empty())            os << NcbiEndl << description.m_Explanation;    }    // Endl    if ((flags & fNoEndl) == 0) {        os << NcbiEndl;    }    return os;}/////////////////////////////////////////////////////////  CDiagAutoPrefix::CDiagAutoPrefix::CDiagAutoPrefix(const string& prefix){    PushDiagPostPrefix(prefix.c_str());}CDiagAutoPrefix::CDiagAutoPrefix(const char* prefix){    PushDiagPostPrefix(prefix);}CDiagAutoPrefix::~CDiagAutoPrefix(void){    PopDiagPostPrefix();}/////////////////////////////////////////////////////////  EXTERNstatic TDiagPostFlags s_SetDiagPostAllFlags(TDiagPostFlags& flags,                                            TDiagPostFlags  new_flags){    CMutexGuard LOCK(s_DiagMutex);    TDiagPostFlags prev_flags = flags;    if (new_flags & eDPF_Default) {        new_flags |= prev_flags;        new_flags &= ~eDPF_Default;    }    flags = new_flags;    return prev_flags;}static void s_SetDiagPostFlag(TDiagPostFlags& flags, EDiagPostFlag flag){    if (flag == eDPF_Default)        return;    CMutexGuard LOCK(s_DiagMutex);    flags |= flag;}static void s_UnsetDiagPostFlag(TDiagPostFlags& flags, EDiagPostFlag flag){    if (flag == eDPF_Default)        return;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -