Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TMessageHandler.cxx
Go to the documentation of this file.
1 // @(#)root/base:$Id$
2 // Author: Rene Brun 11/11/99
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 /** \class TMessageHandler
13 
14 \ingroup Base
15 Handle messages that might be generated by the system.
16 By default a handler only keeps track of the different messages
17 generated for a specific class. By deriving from this class and
18 overriding Notify() one can implement custom message handling.
19 In Notify() one has access to the message id and the object
20 generating the message. One can install more than one message
21 handler per class. A message handler can be removed or again
22 added when needed.
23 
24  - All Root "Warnings" are logged as message 1001
25  - All Root "Errors" are logged as message 1002
26  - All Root "SysErrors" are logged as message 1003
27  - All Root "Fatals" are logged as message 1004
28 */
29 
30 #include "TMessageHandler.h"
31 #include "TClass.h"
32 #include "TROOT.h"
33 #include "TVirtualMutex.h"
34 
35 ClassImp(TMessageHandler);
36 
37 ////////////////////////////////////////////////////////////////////////////////
38 /// Create a new message handler for class cl and add it to the list
39 /// of message handlers.
40 
41 TMessageHandler::TMessageHandler(const TClass *cl, Bool_t derived)
42 {
43  fClass = cl;
44  fMessObj = 0;
45  fMessId = 0;
46  fSize = 0;
47  fCnts = 0;
48  fMessIds = 0;
49  fDerived = derived;
50 
51  if (fClass)
52  SetName(fClass->GetName());
53  else
54  SetName("DefaultMessageHandler");
55 
56  Add();
57 }
58 
59 ////////////////////////////////////////////////////////////////////////////////
60 /// Create a new message handler for class named cl and add it to the list
61 /// of message handlers.
62 
63 TMessageHandler::TMessageHandler(const char *cl, Bool_t derived)
64 {
65  fClass = TClass::GetClass(cl);
66  fMessObj = 0;
67  fMessId = 0;
68  fSize = 0;
69  fCnts = 0;
70  fMessIds = 0;
71  fDerived = derived;
72 
73  SetName(cl);
74 
75  SetName(fClass->GetName());
76  Add();
77 }
78 
79 ////////////////////////////////////////////////////////////////////////////////
80 /// Clean up the message handler.
81 
82 TMessageHandler:: ~TMessageHandler()
83 {
84  Remove();
85  if (fSize <= 0) return;
86  delete [] fCnts;
87  delete [] fMessIds;
88 }
89 
90 ////////////////////////////////////////////////////////////////////////////////
91 /// Add this message handler to the list of messages handlers.
92 
93 void TMessageHandler::Add()
94 {
95  R__LOCKGUARD(gROOTMutex);
96  gROOT->GetListOfMessageHandlers()->Add(this);
97  if (fClass) {
98  // don't emit signal when the default message handler is added
99  // as this happens in the TROOT ctor and the TQObject stuff is
100  // not yet properly initialized on some platforms
101  Added(); // emit Added() signal
102  }
103 }
104 
105 ////////////////////////////////////////////////////////////////////////////////
106 /// Return counter for message with ID=messid.
107 
108 Int_t TMessageHandler::GetMessageCount(Int_t messId) const
109 {
110  if (fSize <= 0) return 0;
111  for (Int_t i = 0; i < fSize; i++) {
112  if (fMessIds[i] == messId) return fCnts[i];
113  }
114  return 0;
115 }
116 
117 ////////////////////////////////////////////////////////////////////////////////
118 /// Return total number of messages.
119 
120 Int_t TMessageHandler::GetTotalMessageCount() const
121 {
122  if (fSize <= 0) return 0;
123  Int_t count = 0;
124  for (Int_t i = 0; i < fSize; i++) {
125  count += fCnts[i];
126  }
127  return count;
128 }
129 
130 ////////////////////////////////////////////////////////////////////////////////
131 /// Store message origin, keep statistics and call Notify().
132 
133 void TMessageHandler::HandleMessage(Int_t id, const TObject *obj)
134 {
135  // check if message must be managed by this message handler
136  if (fClass) {
137  if (fDerived) {
138  if(!obj->InheritsFrom(fClass)) return;
139  } else {
140  if (obj->IsA() != fClass) return;
141  }
142  }
143 
144  fMessId = id;
145  fMessObj = obj;
146 
147  Notify();
148 
149  // increment statistics
150  Int_t i;
151  // first message
152  if (fSize <= 0) {
153  fSize = 1;
154  fCnts = new Int_t[fSize];
155  fMessIds = new Int_t[fSize];
156  } else {
157  // already existing message
158  for (i = 0; i < fSize; i++) {
159  if (fMessIds[i] == fMessId) {
160  fCnts[i]++;
161  return;
162  }
163  }
164  // new message
165  fSize++;
166  Int_t *newCnts = new Int_t[fSize];
167  Int_t *newMessIds = new Int_t[fSize];
168  for (i = 0; i < fSize-1; i++) {
169  newCnts[i] = fCnts[i];
170  newMessIds[i] = fMessIds[i];
171  }
172  delete [] fCnts;
173  delete [] fMessIds;
174  fCnts = newCnts;
175  fMessIds = newMessIds;
176  }
177  fCnts[fSize-1] = 1;
178  fMessIds[fSize-1] = fMessId;
179 }
180 
181 ////////////////////////////////////////////////////////////////////////////////
182 /// This method must be overridden to handle object notification.
183 
184 Bool_t TMessageHandler::Notify()
185 {
186  if (fClass) return kFALSE;
187  // case of default handler
188  // encode class number in message id
189  if (!fMessObj) return kFALSE;
190  Int_t uid = Int_t(fMessObj->IsA()->GetUniqueID());
191  fMessId += 10000*uid;
192  fMessId = -fMessId;
193  Notified(); // emit Notified() signal
194  return kFALSE;
195 }
196 
197 ////////////////////////////////////////////////////////////////////////////////
198 /// Print statistics for this message handler.
199 
200 void TMessageHandler::Print(Option_t *) const
201 {
202  printf("\n ****** Message Handler: %s has a total of %d messages\n",GetName(),GetTotalMessageCount());
203  if (fSize <= 0) return;
204  Int_t id, uid;
205  const TClass *cl;
206  TIter next(gROOT->GetListOfClasses());
207  for (Int_t i = 0; i < fSize; i++) {
208  id = fMessIds[i];
209  cl = fClass;
210  if (id < 0) {
211  id = -id;
212  uid = id/10000;
213  id = id%10000;
214  next.Reset();
215  while ((cl = (TClass*)next())) {
216  if (cl->GetUniqueID() == UInt_t(uid)) break;
217  }
218  }
219  if (!cl) cl = gROOT->IsA();
220  if (id == 1001) {
221  printf(" Class: %-20s WARNINGs has %d counts\n",cl->GetName(),fCnts[i]);
222  continue;
223  }
224  if (id == 1002) {
225  printf(" Class: %-20s ERRORs has %d counts\n",cl->GetName(),fCnts[i]);
226  continue;
227  }
228  printf(" Class: %-20s MessID = %5d has %d counts\n",cl->GetName(),id,fCnts[i]);
229  }
230 }
231 
232 ////////////////////////////////////////////////////////////////////////////////
233 /// Remove this message handler from the list of messages handlers.
234 
235 void TMessageHandler::Remove()
236 {
237  R__LOCKGUARD(gROOTMutex);
238  gROOT->GetListOfMessageHandlers()->Remove(this);
239  Removed(); // emit Removed() signal
240 }