#include "MessageDim.h" #include "tools.h" #include "Time.h" using namespace std; // ************************************************************************** /** @class MessageDimTX @brief Based on MessageImp, redirects log-output to a Dim service MESSAGE This is a special DimService which offers SERVER/MESSAGE to the DimNetwork and redirects output issued via its base-class MessageImp to the Dim service. The severity of the message is send as qualiy of service of the service message. @section Examples - A simple and usefull example can be found in \ref log.cc and \ref logtime.cc **/ // ************************************************************************** // -------------------------------------------------------------------------- // //! Constructs a DimService with the name SERVER/MESSAGE. And passes the //! given ostream down to the MessageImp base. //! //! @param name //! Name of the message server to which we want to subscribe, e.g. DRIVE //! //! @param out //! ostream passed to MessageImp. It is used to redirect the output to. // MessageDimTX::MessageDimTX(const std::string &name, std::ostream &out) : DimDescribedService((name + "/MESSAGE").c_str(), const_cast(""), "A general logging service providing a quality of service (severity)" "|Message[string]:The message"), MessageImp(out), fDebug(false) { // This is a message which will never arrive because // the time to establish a client-sever connection is // too short. Message("MessageDimTX started."); } // -------------------------------------------------------------------------- // //! // MessageDimTX::~MessageDimTX() { Message("MessageDimTX shutting down.."); } // -------------------------------------------------------------------------- // //! First calls MessageImp::Write to output the message tobe transmitted //! also to a local logging stream. Then the Dim service is updated. //! If sending of the message failed a message is written to the //! logging stream stored in MessageImp. It is intentionally not //! output through Update to make it look different than usual //! transmitted messages. // int MessageDimTX::Write(const Time &t, const string &txt, int qos) { MessageImp::Write(t, txt, qos); // We cannot use our own mutex here because it can create dead-locks // in a hand-shake with the global dim-mutex if a service is // updated from within a dimHandler (dim-mutex already locked) // and at the same time another thread tries to lock the mutex. // // Thread 1: Lock global Dim mutex and call infoHandler // // Thread 2: CALL Write // Thread 2: LOCK Write-mutex // Thread 2: setQuality will try to lock global Dim mutex // (since Thread1!=Thread2 this results in a wait) // // Thread 1: CALL Write from within the infoHandler // Thread 1: LOCK Write-mutex // (since Thread2 now waits for the infoHandler to finish // and the infoHandler has to wait for the Write-mutex // we have a dead-lock) // dim_lock(); // We have to use setData to make sure the DimService will // hold a local copy of the data. setQuality(qos); const int rc = DimDescribedService::Update(txt); dim_unlock(); if (rc==0 && fDebug) Out() << " !! " << t.GetAsStr() << " - Sending failed!" << endl; return rc; } // ************************************************************************** /** @class MessageDimRX @brief Based on MessageImp, subscribes to a MESSAGE service in the Dim network This is a special DimInfoHandler. It subscribes to a service SERVER/MESSAGE on the DimNetwork and redirects all received output to its base class MessageImp view MessageImp::Write. the quality of service received with each service update is passed as severity. @section Examples - A simple and usefull example can be found in \ref log.cc and \ref logtime.cc @todo Maybe it is not a good idea that MessageImp is a base class, maybe it should be a reference given in the constructor **/ // ************************************************************************** // -------------------------------------------------------------------------- // //! Setup a DimStamedInfo service subscription for SERVER/MESSAGE //! //! @param name //! the name of the SERVER //! //! @param imp //! A reference to MessageImo to which messages will be redirected // MessageDimRX::MessageDimRX(const std::string &name, MessageImp &imp) : fMinLogLevel(0), fConnected(false), fMsg(imp), fDimMessage((name+"/MESSAGE").c_str(), (void*)NULL, 0, this) { } // -------------------------------------------------------------------------- // //! If the server has been disconnected write a simple log-message. //! Skip all received messages which have a severity smaller than //! fMinLogLevel. Write any other message with MessageImp::Write. // void MessageDimRX::infoHandler() { if (getInfo()!=&fDimMessage) return; const string name = fDimMessage.getName(); const string server = name.substr(0, name.find_first_of('/')); fConnected = fDimMessage.getSize()!=0; // The server is diconnected. Do nothing if (!fConnected) { // We cannot print this message because it is produced by // every server which doesn't have the MESSAGE service, too. //fMsg.Message(server+": Disconnected."); return; } // skip all messages with a severity smaller than the minimum log level if (fDimMessage.getQuality()