source: trunk/FACT++/src/MessageDim.cc@ 11702

Last change on this file since 11702 was 11395, checked in by tbretz, 13 years ago
Set the Dim timestamp to the given time.
File size: 6.0 KB
Line 
1#include "MessageDim.h"
2
3#include "tools.h"
4#include "Time.h"
5
6using namespace std;
7
8// **************************************************************************
9/** @class MessageDimTX
10
11@brief Based on MessageImp, redirects log-output to a Dim service MESSAGE
12
13This is a special DimService which offers SERVER/MESSAGE to the DimNetwork
14and redirects output issued via its base-class MessageImp to the Dim
15service. The severity of the message is send as qualiy of service of
16the service message.
17
18@section Examples
19
20 - A simple and usefull example can be found in \ref log.cc and \ref logtime.cc
21
22**/
23// **************************************************************************
24
25// --------------------------------------------------------------------------
26//
27//! Constructs a DimService with the name SERVER/MESSAGE. And passes the
28//! given ostream down to the MessageImp base.
29//!
30//! @param name
31//! Name of the message server to which we want to subscribe, e.g. DRIVE
32//!
33//! @param out
34//! ostream passed to MessageImp. It is used to redirect the output to.
35//
36MessageDimTX::MessageDimTX(const std::string &name, std::ostream &out)
37 : DimDescribedService((name + "/MESSAGE").c_str(), const_cast<char*>(""),
38 "A general logging service providing a quality of service (severity)"
39 "|Message[string]:The message"),
40MessageImp(out), fDebug(false)
41{
42 // This is a message which will never arrive because
43 // the time to establish a client-sever connection is
44 // too short.
45 Message("MessageDimTX started.");
46}
47
48// --------------------------------------------------------------------------
49//
50//!
51//
52MessageDimTX::~MessageDimTX()
53{
54 Message("MessageDimTX shutting down..");
55}
56
57// --------------------------------------------------------------------------
58//
59//! First calls MessageImp::Write to output the message tobe transmitted
60//! also to a local logging stream. Then the Dim service is updated.
61//! If sending of the message failed a message is written to the
62//! logging stream stored in MessageImp. It is intentionally not
63//! output through Update to make it look different than usual
64//! transmitted messages.
65//
66int MessageDimTX::Write(const Time &t, const string &txt, int qos)
67{
68 MessageImp::Write(t, txt, qos);
69
70
71 // We cannot use our own mutex here because it can create dead-locks
72 // in a hand-shake with the global dim-mutex if a service is
73 // updated from within a dimHandler (dim-mutex already locked)
74 // and at the same time another thread tries to lock the mutex.
75 //
76 // Thread 1: Lock global Dim mutex and call infoHandler
77 //
78 // Thread 2: CALL Write
79 // Thread 2: LOCK Write-mutex
80 // Thread 2: setQuality will try to lock global Dim mutex
81 // (since Thread1!=Thread2 this results in a wait)
82 //
83 // Thread 1: CALL Write from within the infoHandler
84 // Thread 1: LOCK Write-mutex
85 // (since Thread2 now waits for the infoHandler to finish
86 // and the infoHandler has to wait for the Write-mutex
87 // we have a dead-lock)
88 //
89 dim_lock();
90
91 // We have to use setData to make sure the DimService will
92 // hold a local copy of the data.
93 setTimestamp(t.Time_t(), t.ms());
94 setData(const_cast<char*>(txt.c_str()));
95 setQuality(qos);
96
97 const int rc = updateService();
98
99 dim_unlock();
100
101 if (rc==0 && fDebug)
102 Out() << " !! " << t.GetAsStr() << " - Sending failed!" << endl;
103
104 return rc;
105}
106
107// **************************************************************************
108/** @class MessageDimRX
109
110@brief Based on MessageImp, subscribes to a MESSAGE service in the Dim network
111
112This is a special DimInfoHandler. It subscribes to a service SERVER/MESSAGE
113on the DimNetwork and redirects all received output to its base class
114MessageImp view MessageImp::Write. the quality of service received with
115each service update is passed as severity.
116
117@section Examples
118
119 - A simple and usefull example can be found in \ref log.cc and \ref logtime.cc
120
121 @todo Maybe it is not a good idea that MessageImp is a base class,
122 maybe it should be a reference given in the constructor
123
124**/
125// **************************************************************************
126
127// --------------------------------------------------------------------------
128//
129//! Setup a DimStamedInfo service subscription for SERVER/MESSAGE
130//!
131//! @param name
132//! the name of the SERVER
133//!
134//! @param imp
135//! A reference to MessageImo to which messages will be redirected
136//
137MessageDimRX::MessageDimRX(const std::string &name, MessageImp &imp)
138: fMinLogLevel(0), fConnected(false), fMsg(imp),
139fDimMessage((name+"/MESSAGE").c_str(), (void*)NULL, 0, this)
140{
141}
142
143// --------------------------------------------------------------------------
144//
145//! If the server has been disconnected write a simple log-message.
146//! Skip all received messages which have a severity smaller than
147//! fMinLogLevel. Write any other message with MessageImp::Write.
148//
149void MessageDimRX::infoHandler()
150{
151 if (getInfo()!=&fDimMessage)
152 return;
153
154 const string name = fDimMessage.getName();
155 const string server = name.substr(0, name.find_first_of('/'));
156
157 fConnected = fDimMessage.getSize()!=0;
158
159 // The server is diconnected. Do nothing
160 if (!fConnected)
161 {
162 // We cannot print this message because it is produced by
163 // every server which doesn't have the MESSAGE service, too.
164 //fMsg.Message(server+": Disconnected.");
165 return;
166 }
167
168 // skip all messages with a severity smaller than the minimum log level
169 if (fDimMessage.getQuality()<fMinLogLevel)
170 return;
171
172 stringstream msg;
173 msg << server << ": " << fDimMessage.getString();
174
175 // Make sure getTimestamp is called _before_ getTimestampMillisecs
176 // Must be in exactly this order!
177 const int tsec = fDimMessage.getTimestamp();
178 const int tms = fDimMessage.getTimestampMillisecs();
179
180 // Write the received message to the output
181 fMsg.Write(Time(tsec, tms*1000), msg.str().c_str(), fDimMessage.getQuality());
182}
Note: See TracBrowser for help on using the repository browser.