Codebase list ibutils / upstream/1.5.7+0.2.gbd7e502 ibmgtsim / src / msgmgr.h
upstream/1.5.7+0.2.gbd7e502

Tree @upstream/1.5.7+0.2.gbd7e502 (Download .tar.gz)

msgmgr.h @upstream/1.5.7+0.2.gbd7e502

c3ebda3
687b2d8
c3ebda3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
687b2d8
c3ebda3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
687b2d8
c3ebda3
 
 
 
 
 
 
 
 
 
 
 
687b2d8
c3ebda3
687b2d8
c3ebda3
687b2d8
 
c3ebda3
687b2d8
 
c3ebda3
 
687b2d8
 
c3ebda3
 
687b2d8
 
 
c3ebda3
687b2d8
 
c3ebda3
 
687b2d8
c3ebda3
 
687b2d8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c3ebda3
 
687b2d8
c3ebda3
 
687b2d8
 
 
 
 
 
 
c3ebda3
 
687b2d8
 
 
 
 
 
 
 
 
 
 
c3ebda3
 
687b2d8
c3ebda3
 
 
687b2d8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c3ebda3
 
687b2d8
c3ebda3
 
 
 
 
687b2d8
 
 
 
 
 
 
 
 
 
 
 
 
c3ebda3
 
 
687b2d8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c3ebda3
687b2d8
 
 
 
 
 
c3ebda3
687b2d8
c3ebda3
687b2d8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c3ebda3
 
687b2d8
 
 
c3ebda3
687b2d8
 
c3ebda3
687b2d8
 
c3ebda3
687b2d8
 
c3ebda3
687b2d8
 
c3ebda3
687b2d8
 
c3ebda3
687b2d8
 
 
 
c3ebda3
687b2d8
 
c3ebda3
 
687b2d8
c3ebda3
 
 
687b2d8
c3ebda3
687b2d8
/*
 * Copyright (c) 2004-2010 Mellanox Technologies LTD. All rights reserved.
 *
 * This software is available to you under a choice of one of two
 * licenses.  You may choose to be licensed under the terms of the GNU
 * General Public License (GPL) Version 2, available from the file
 * COPYING in the main directory of this source tree, or the
 * OpenIB.org BSD license below:
 *
 *     Redistribution and use in source and binary forms, with or
 *     without modification, are permitted provided that the following
 *     conditions are met:
 *
 *      - Redistributions of source code must retain the above
 *        copyright notice, this list of conditions and the following
 *        disclaimer.
 *
 *      - Redistributions in binary form must reproduce the above
 *        copyright notice, this list of conditions and the following
 *        disclaimer in the documentation and/or other materials
 *        provided with the distribution.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 */


///////////////////////////////////////////////////////////////////////////
//
// Message Manager -
//
// A centralized way for error warning info verbose etc messaging.
//
// The main idea:
// 1. An application register each new message type (providing a module name, and a
//    parameterized msg string) using msgMan.reg which returns the msgType object
// 2. An application then uses msgType.msg method to send the message providing
//    only the message arguments.
//
// EXAMPLE CODE:
//
// 0. The following flags define the verbosity level:
//    MsgShowFatal   - show fatal errors
//    MsgShowError   - show algorithmic or data non fatal errors
//    MsgShowWarning - show warnings
//    MsgShowInfo    - show info massages
//    MsgShowVerbose - show verbose messages
//    MsgShowMads    - show MAD messages contents
//    MsgShowContext - show the context info for the message (normally the function name)
//    MsgShowSource  - show the file name and line of the message
//    MsgShowAll     - all the above
//    MsgDefault     - MsgShowContext | MsgShowFatal | MsgShowError | MsgShowWarning | MsgShowInfo
//
// 1. Get a ref to the massage manager
//    NOTE: on the first call it's out stream and verbosity is defined.
//    msgMgr(MsgDefault, &cout)
//
// 2. Define some message templates:
//
//    static int errMsg1 = msgMgr().reg(
//     'E',                                        // severity
//     "Fail to find node:$ for inst:$ of type:$", // actual format
//     "myProcedure"                               // context
//     "myModule"                                  // module name
//     );
//
// 3. Send a message (using the predefined type errMsg1):
//    msgMgr().send(errMsg1,__FILE__,__LINE__,"n18","i1","output");
//
// 4. You can control the verbosity of each module:
//    msgMgr().setVerbLevel(MsgShowAll, "myModule");
//    NOTE: Even if the global verbosity is set to errors only a verbose message
//          of type with module "myModule" will be shown.
//
//    For simplicity we provide macro versions:
//
//    MSGREG(varName, verbosity, msgTemplate, module) - register new type for current module
//
//    MSGSND(varName, "parameter1", "parameter2", ...) - send the message
//
//    The example above will look like:
//    MSGREG(errMsg1, 'E', "Fail to find node:$ for inst:$ of type:$","myModule");
//    MSGSND(errMsg1, "n18","i1","output");
//
// HACK: currently I use max f 6 optional fields
///////////////////////////////////////////////////////////////////////////


#ifndef __MSG_MGR_H__
#define __MSG_MGR_H__

#include <sys/time.h>
#include <inttypes.h>
#include <pthread.h>
#include <vector>
#include <string>
#include <iostream>
#include <list>
#include <map>


#define MSGREG(varName, verbosity, msgTemplate, module) \
        static int varName = msgMgr().reg(verbosity, msgTemplate, __FUNCTION__, module);

#define MSGGLBREG(varName, verbosity, msgTemplate, module)  \
        static int varName = msgMgr().reg(verbosity, msgTemplate, "Global", module);

#define MSGSND(varName, ...)    \
        msgMgr().send(varName ,__FILE__,__LINE__,##__VA_ARGS__);

extern int msgMgrEnterFunc;
#define MSG_ENTER_FUNC  \
        msgMgr().send(msgMgrEnterFunc ,__FILE__,__LINE__,__FUNCTION__);

extern int msgMgrLeaveFunc;
#define MSG_EXIT_FUNC   \
        msgMgr().send(msgMgrLeaveFunc ,__FILE__,__LINE__,__FUNCTION__);

#if 0
    #define MSG_ENTER_FUNC
    #define MSG_EXIT_FUNC
#endif


// we use specialization of strings to support casting of various types:
class msgStr {
private:

public:
    std::string s;
    msgStr(const msgStr &os) {s = os.s;};
    msgStr(const char cp[]);
    msgStr(const std::string str) {s = str;};
    msgStr(const int i);
    msgStr(const long int i);
    msgStr(const float i);
    msgStr(const double i);
    msgStr(const unsigned int i);
    msgStr(const unsigned long int i);
    msgStr(const unsigned short int i);
    msgStr(const unsigned long long i);

    //msgStr operator+ (const char cp[]) { s += std::string(cp);};
    msgStr operator+ (const char cp1[]) {
        msgStr tmp(*this);
        tmp.s += std::string(cp1);
        return tmp;
    }
    // msgStr operator+ (const msgStr os) { s += os.s;};
};


// a single message object
class msgObj {
private:
    // the message fields
    std::string f1,f2,f3,f4,f5,f6;
    int         lineNum;
    std::string inFile;
    int         typeId;
    struct timeval when;

 public:
    inline msgObj() {typeId = 0;};
    msgObj(int t,
            std::string i1, std::string i2, std::string i3, std::string i4, std::string i5, std::string i6,
            std::string fn = "", int ln = 0) {
        struct timezone tz; // we need it temporarily
        typeId = t; f1 = i1; f2 = i2; f3 = i3; f4 = i4; f5 = i5; f6 = i6;
        inFile = fn; lineNum = ln;
        gettimeofday( &when, &tz );
    }
    // ~msgObj();
    friend class msgManager;
};


// Each message has an associated type.The type defines the format of the message
// and the module it belongs to.
class msgType {
private:
    char severity;
    std::string format;     // format string is "<any string> $ <any string> $ ...."
    int numFields;          // number of fields in the format
    std::string context;    // the context (the function) of the message
    std::string module;     // the module name - message filtering can be done in module granularity

public:
    msgType() { severity = 'U'; numFields = 0; context = ""; module = "";};
    msgType(char s, std::string &fmt, std::string ctx = "", std::string mod = "");

    // ~msgType(); // NOTE it will not be removed from the mgr list of generators!

    // generate a msg object and send it to the manager
    // HACK WE CURRENTLY LIMIT THE NUMBER OF FIELDS TO 6
    // string send(string f1 = "", string f2 = "", string f3 = "",
    // string f4 = "", string f5 = "", string f6 = "");
    friend class msgManager;
};


#define msg_vec              std::vector<msgObj>
#define int_mtype_map        std::map<int, msgType, std::less<int> >
#define module_verbosity_map std::map< std::string, int, std::less<std::string> >

// modes of verbose
const int MsgShowFatal   = 0x01;
const int MsgShowError   = 0x02;
const int MsgShowWarning = 0x04;
const int MsgShowInfo    = 0x08;
const int MsgShowVerbose = 0x10;
const int MsgShowContext = 0x20;
const int MsgShowSource  = 0x40;
const int MsgShowTime    = 0x80;
const int MsgShowModule  = 0x100;
const int MsgShowMads    = 0x200;
const int MsgShowFrames  = 0x400;
const int MsgShowAll     = 0xffff;
const int MsgDefault     = 0x62f;

// This is the manager class
class msgManager {
private:
    msg_vec         log;            // hold all messages in generation order
    int_mtype_map   types;          // hold all generators declared
    std::ostream *  outStreamP;     // target stream
    pthread_mutex_t lock;           // need to lock the log vectors during push/pop

    // verbLevel - controls the msg verbosity.
    module_verbosity_map  verbLevel;

    unsigned int pendingMsgsI;

    // will use the module verbosity of the message type if the
    // external verbosity is not defined.
    std::string msg2string(msgObj msg, int externalVerbosity = 0,
            int errFatals = 0); // produce a message string.

public:
    // default constructor in any case ...
    msgManager() {
        verbLevel[std::string("")] = MsgDefault;
        outStreamP = & std::cout;
        pendingMsgsI = 0;
        pthread_mutex_init(&lock, NULL);
    };

    // The constructor
    msgManager(const int vl, std::ostream *o = & std::cout) {
        verbLevel[std::string("")] = vl; outStreamP = o; pendingMsgsI = 0;
        // Initialize the lock object
        pthread_mutex_init(&lock, NULL);
    };

    ~msgManager();

    // get
    inline int getVerbLevel(std::string module = "") {
        module_verbosity_map::iterator vI = verbLevel.find(module);
        if (vI != verbLevel.end()) {
            return((*vI).second);
        } else {
            return(verbLevel[std::string("")]);
        };
    };
    // clr
    inline int clrVerbLevel(std::string module = "") {
        if (module.size() == 0) return 0;
        module_verbosity_map::iterator vI = verbLevel.find(module);
        if (vI != verbLevel.end())
            verbLevel.erase(vI);
        return 0;
    };

    inline void setVerbLevel(int vl, std::string module = "") {verbLevel[module] = vl;};
    inline std::ostream *getOutStream() {return outStreamP;};
    inline void setOutStream(std::ostream * o) {outStreamP = o;};

    // get number of outstanding messages of the given severity
    int outstandingMsgCount(int vl = MsgShowFatal | MsgShowError);

    // get all outstanding messages
    std::string outstandingMsgs(int vl = MsgShowFatal | MsgShowError);

    // return the next message string
    std::string getNextMessage();

    // null the list of outstanding messages:
    void nullOutstandingMsgs();

    // declare a new message type - return the generator id:
    int reg(char s, std::string fmt, std::string ctx = "", std::string mod = "");

    // get a new message and do something with it
    int send(int typeId, std::string fn = "", int ln = 0,
            msgStr i1="",msgStr i2="",msgStr i3="",msgStr i4="",
            msgStr i5="",msgStr i6="");

    // FUTURE:
    // Other fancy utilities like summary, sorting of messages etc.
};


// we want to have a singleton massage manager
msgManager &msgMgr(int vl = MsgDefault, std::ostream *o = & std::cout);


#endif