Logo Search packages:      
Sourcecode: ibutils version File versions  Download package

msgmgr.cpp

/*
 * Copyright (c) 2004 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.
 *
 * $Id$
 */

#include "msgmgr.h"
#include <string>
#include <stdio.h>
#include <string.h>

using namespace std;

//
// MESSAGE TYPE CLASS
//
msgType::msgType(char s, string &fmt, string ctx, string mod)
{
  severity = s;
  format = fmt;
  context = ctx;
  module = mod;

  // calc the number of fields
  int pos = 0;
  numFields = 0;
  while ((pos = 1 + format.find('$', pos)) > 0) numFields++;

  // limit to 6 :
  if (numFields > 6)
  {
    cerr << "-E- msgManager too many fields (>6) in msgType:" << fmt << endl;
    numFields = 6;
  }
}

//
// MESSAGE MANAGER CLASS
//

string msgManager::msg2string(
  msgObj msg,
  int externalVerbosity, // if not 0 will be used as the verbosity
  int errFatals)  // if not 0 will cerr any  FATAL err
{
  // find the message format:
  int_mtype_map::const_iterator mTypeI = types.find(msg.typeId);
  if (mTypeI == types.end())
  {
    cerr << "-E- Fail to find message type by id:" << msg.typeId << endl;
    return "";
  }

  msgType t = (*mTypeI).second;

  int vl;
  if (externalVerbosity == 0)
    vl = getVerbLevel(t.module);
  else
    vl = externalVerbosity;

  // filter by verbose level:
  if ( (t.severity == 'F' && (vl & MsgShowFatal)) ||
       (t.severity == 'E' && (vl & MsgShowError)) ||
       (t.severity == 'W' && (vl & MsgShowWarning)) ||
       (t.severity == 'I' && (vl & MsgShowInfo)) ||
       (t.severity == 'M' && (vl & MsgShowMads)) ||
       (t.severity == 'R' && (vl & MsgShowFrames)) ||
       (t.severity == 'V' && (vl & MsgShowVerbose)))
  {

    char res[1024];
    char tmp[1024];

    res[0] = '\0';

    // add time if required
    if (vl & MsgShowTime)
      sprintf(res, "[%09ld:%09ld]", msg.when.tv_sec, (long)msg.when.tv_usec);

    // start with severity
    sprintf(tmp, "-%c-", t.severity);
    strcat(res, tmp);

    // include parenthesis if either context or source
    if ((vl & MsgShowContext) || (vl & MsgShowSource) || (vl & MsgShowModule) )
      strcat(res,"(");

    // append the module if required:
    if (vl & MsgShowModule)
    {
      strcat(res, t.module.c_str());
      strcat(res, " ");
    }

    // append the context if required:
    if (vl & MsgShowContext)
      strcat(res, t.context.c_str());

    // append file and line if required:
    if (vl & MsgShowSource)
    {
      sprintf(tmp, " %s,%d", msg.inFile.c_str(), msg.lineNum);
      strcat(res, tmp);
    }

    // close the parent system or space
    if ((vl & MsgShowContext) || (vl & MsgShowSource) || (vl & MsgShowModule))
      strcat(res,") ");
    else
      strcat(res," ");

    // go over the format:
    int pos = 0, nextPos = 0;
    int numFields = 0;
    while ((nextPos = t.format.find('$', pos)) >= 0)
    {
      strcat(res,t.format.substr(pos,nextPos - pos).c_str());
      switch (++numFields)
      {
      case 1: strcat(res, msg.f1.c_str()); break;
      case 2: strcat(res, msg.f2.c_str()); break;
      case 3: strcat(res, msg.f3.c_str()); break;
      case 4: strcat(res, msg.f4.c_str()); break;
      case 5: strcat(res, msg.f5.c_str()); break;
      case 6: strcat(res, msg.f6.c_str()); break;
      }
      pos = nextPos + 1;
    }

    strcat(res, t.format.substr(pos).c_str());
    strcat(res, "\n");

    // send FATAL errors directly to the stderr
    if (errFatals && (t.severity == 'F') && (vl & MsgShowFatal))
      cerr << res;

    return res;
  }
  return "";
}

// get number of outstanding messages of the given severity
int msgManager::outstandingMsgCount(int vl) {
  // go over all messages past the pendingMsgsI iterator and count them if
  // match the given verbose level
  int cnt = 0;

  unsigned int I = pendingMsgsI;
  msgType t;
  pthread_mutex_lock(&lock);
  while (I < log.size())
  {
    // get the message type obj:
    t = types[(log[I]).typeId];
    if ( (t.severity == 'F' && (vl & MsgShowFatal)) ||
         (t.severity == 'E' && (vl & MsgShowError)) ||
         (t.severity == 'W' && (vl & MsgShowWarning)) ||
         (t.severity == 'I' && (vl & MsgShowInfo)) ||
         (t.severity == 'M' && (vl & MsgShowMads)) ||
         (t.severity == 'R' && (vl & MsgShowFrames)) ||
         (t.severity == 'V' && (vl & MsgShowVerbose)) ) cnt++;
    I++;
  }
  pthread_mutex_unlock(&lock);
  return cnt;
}

// get outstanding messages of the given severity
string msgManager::outstandingMsgs(int vl) {
  // go over all messages past the pendingMsgsI iterator and collect
  // match the given verbose level
  string res = "";

  pthread_mutex_lock(&lock);
  unsigned int I = pendingMsgsI;

  msgType t;
  while (I < log.size())
  {
    // get the message type obj:
    t = types[(log[I]).typeId];
    if ( (t.severity == 'F' && (vl & MsgShowFatal)) ||
         (t.severity == 'E' && (vl & MsgShowError)) ||
         (t.severity == 'W' && (vl & MsgShowWarning)) ||
         (t.severity == 'I' && (vl & MsgShowInfo)) ||
         (t.severity == 'M' && (vl & MsgShowMads)) ||
         (t.severity == 'R' && (vl & MsgShowFrames)) ||
         (t.severity == 'V' && (vl & MsgShowVerbose)) )
      res += msg2string(log[I], vl);
    I++;
  }
  pthread_mutex_unlock(&lock);
  return res;
}

// return the next message string if included in the given types
string msgManager::getNextMessage() {
  string res("");

  pthread_mutex_lock(&lock);

  if (pendingMsgsI == log.size() - 1)
    res = msg2string(log[pendingMsgsI++]);

  pthread_mutex_unlock(&lock);
  return res;
}

void  msgManager::nullOutstandingMsgs() {
  pthread_mutex_lock(&lock);

  if (log.size() == 0)
    pendingMsgsI = 0;
  else
    pendingMsgsI = log.size();

  pthread_mutex_unlock(&lock);

}

// declare a new message type - return the generator id:
int msgManager::reg(char s, string fmt, string ctx, string mod) {
  msgType t(s,fmt,ctx,mod); // create a msg type
  pthread_mutex_lock(&lock);
  int id = types.size() + 1;
  types[id] = t; // store in map
  pthread_mutex_unlock(&lock);
  return id;
}

// get a new message and do something with it
int msgManager::send(int typeId, string fn , int ln, msgStr i1 ,msgStr i2 ,msgStr i3 ,
                 msgStr i4, msgStr i5 ,msgStr i6)
{

  // create a new message
  msgObj msg(typeId, i1.s,i2.s,i3.s,i4.s,i5.s,i6.s,fn,ln);

  // store in the log
  pthread_mutex_lock(&lock);

  // We store all messages in the log vector - but we can void that for now
  // log.push_back(msg);

  // if the message if Fatal send it to stderr if we are logging to file.
  int sendFatalsToCerr = 0;
  if ((*outStreamP != cout) && (*outStreamP != cerr))
    sendFatalsToCerr = 1;

  // handle the new message
  if (outStreamP) {
    // default verbosity, err on fatal
    (*outStreamP) << msg2string(msg, 0, sendFatalsToCerr);
    outStreamP->flush();
  }

  // if we unlock after we stream we serialize the display
  pthread_mutex_unlock(&lock);


  return 0;
}

msgStr::msgStr(const char cp[])           {if (cp) {s = string(cp);};}
msgStr::msgStr(const int i)               {char b[8];  sprintf(b, "%d", i); s = string(b);}
msgStr::msgStr(const long int i)          {char b[8];  sprintf(b, "%ld", i);s = string(b);}
msgStr::msgStr(const float i)             {char b[16]; sprintf(b, "%f", i); s = string(b);}
msgStr::msgStr(const double i)            {char b[16]; sprintf(b, "%f", i); s = string(b);}
msgStr::msgStr(const unsigned long int i) {char b[16]; sprintf(b, "%lu", i);s = string(b);}
msgStr::msgStr(const unsigned int i)      {char b[8];  sprintf(b, "%u", i); s = string(b);}
msgStr::msgStr(const unsigned short i)    {char b[8];  sprintf(b, "%u", i); s = string(b);}
msgStr::msgStr(const unsigned long long i){char b[20];  sprintf(b, "0x%016llx", i); s = string(b);}

msgManager &msgMgr(int vl, std::ostream *o)
{
  static msgManager *pMgr = NULL;
  if (pMgr == NULL)
  {
    pMgr = new msgManager(vl, o);
  }

  return (*pMgr);
};

// we provide two global definitions for entering and leaving functions:
int msgMgrEnterFunc = msgMgr().reg('R',"$ [", "top", "msg");
int msgMgrLeaveFunc = msgMgr().reg('R',"$ ]", "top", "msg");

#ifdef MSG_MGR_TEST

int main(int argc, string **argv)
{
  msgMgr( MsgShowFatal | MsgShowError | MsgShowWarning, &cerr);
  MSGREG(err1,
         'E',  // severity
         "Fail to find node:$ for inst:$ of type:$",
         "noModule"
         );
  MSGREG(verb1,'V', "This verbose with param:$ bla","");
  msgMgr().send(err1,__FILE__,__LINE__,"n18","i1","output");
  MSGSND(verb1,"pv1");
  MSGSND(err1,"node","inst","type");
  static int mod1Err = msgMgr().reg('V', "This is module param:$", "main", "myModule");
  MSGREG(mod2Err,'V', "This is another module param:$", "otherModule");

  msgMgr().setVerbLevel(MsgShowAll, "myModule");
  msgMgr().send(mod1Err,__FILE__,__LINE__,"PARAM1");
  MSGSND(mod2Err,"PARAM2");
  MSGREG(err3, 'E', "This is error no param", "mySecondModule");
  MSGSND(err3);

  cout << "Getting all messages..." <<endl;
  msgMgr().clrVerbLevel("myModule");
  msgMgr().send(mod1Err,__FILE__,__LINE__,"PARAM1");

  cout << msgMgr().outstandingMsgs(MsgShowAll);
}

#endif

Generated by  Doxygen 1.6.0   Back to index