1    	//////////////////////////////////////////////////////////////////////////
2    	//                                                                      //
3    	// StMessageCounter                                                     //
4    	//                                                                      //
5    	// This class manages message limiting in STAR. It is a singleton.      //
6    	// Limits can be placed on message types (i.e. "I" for info messages)   //
7    	// or on strings in messages (i.e. "dst_track empty")                   //
8    	//                                                                      //
9    	//////////////////////////////////////////////////////////////////////////
10   	
11   	#include "StMessageCounter.h"
12   	#include "StMessageStream.h"
13   	#include <cstring>
14   	using namespace std;
15   	StMessageCounter* StMessageCounter::mInstance = 0;
16   	
17   	//_____________________________________________________________________________
18   	StMessageCounter::StMessageCounter() : ostrstream(),
19   	limitMessage(" - COUNT LIMIT REACHED!\n") {
20   	  messTypeList = StMessTypeList::Instance();
21   	  yesLimits = 0;
22   	  noLimits = 0;
23   	  // Initialize buffer with 256 bytes
24   	  *this << ch64 << ch64 << ch64 << ch64;
25   	}
26   	//_____________________________________________________________________________
27   	StMessageCounter::~StMessageCounter() {
28   	}
29   	//_____________________________________________________________________________
30   	StMessageCounter* StMessageCounter::Instance() {
31   	  if (!mInstance) {
32   	    mInstance = new StMessageCounter;
33   	  }
34   	  return mInstance;
35   	}
36   	//_____________________________________________________________________________
37   	void StMessageCounter::SetLimit(const char* str, int n) {
38   	  if (noLimits) return;
39   	  if (!yesLimits && (n >= 0)) yesLimits = 1;
40   	  const size_t len = strlen(str);
41   	  char* temp;
42   	  if (len==1) {                         // Limits by type
43   	    int typeN = messTypeList->FindTypeNum(str);
44   	    if (typeN) {
45   	      if (limitTList[typeN] != -5)      // -5 means fixed with no limit
46   	        limitTList[typeN] = n;
47   	    } else {                            // Waiting list for type limits
48   	      if (limitWList.size()) {
49   	        size_t index = 0;
50   	        for (curString=limitWList.begin(); curString!=limitWList.end();
51   		                                   curString++) {
52   	          if (*str == *(*curString)) {  // Already in the waiting list
53   	            if (limitWNList[index] != -5)  // -5 means fixed with no limit
54   	              limitWNList[index] = n;
55   	            return;
56   	          }
57   	          index++;
58   	        }
59   	      }
60   	      temp = new char[len+1];
61   	      temp[len] = 0;
62   	      limitWList.push_back(strncpy(temp,str,len));
63   	      limitWNList.push_back(n);
64   	    }
65   	  } else {                              // Limits by string
66   	    size_t index=0;
67   	    for (curString=limitList.begin(); curString!=limitList.end();
68   	                                      curString++) {
69   	      if (!strcmp(str,(*curString))) {
70   	        if (limitNList[index] == -5) return;  // -5 means fixed with no limit
71   	        if ((n < 0) && (n != -5)) {
72   	          limitList.erase(curString);
73   	          limitNList.erase(limitNList.begin()+index);
74   	          limitNCountList.erase(limitNCountList.begin()+index);
75   	        } else {
76   	          limitNList[index] = n;
77   	        }
78   	        return;
79   	      }
80   	      index++;
81   	    }
82   	    if ((n < 0) && (n != -5)) return;
83   	    temp = new char[len+1];
84   	    temp[len] = 0;
85   	    limitList.push_back(strncpy(temp,str,len));
86   	    limitNList.push_back(n);
87   	    limitNCountList.push_back(0);
88   	  }
89   	  return;
90   	}
91   	//_____________________________________________________________________________
92   	int StMessageCounter::GetLimit(const char* str) {
93   	  const size_t len = strlen(str);
94   	  if (len==1) {                         // Limits by type
95   	    int typeN = messTypeList->FindTypeNum(str);
96   	    if (typeN) {
97   	      return limitTList[typeN];
98   	    } else {                            // Waiting list for type limits
99   	      if (limitWList.size()) {
100  	        size_t index = 0;
101  	        for (curString=limitWList.begin(); curString!=limitWList.end();
102  		                                   curString++) {
103  	          if (*str == *(*curString)) return limitWNList[index];
104  	          index++;
105  	        }
106  	      }
107  	    }
108  	  } else {                              // Limits by string
109  	    size_t index=0;
110  	    for (curString=limitList.begin(); curString!=limitList.end();
111  	                                      curString++) {
112  	      if (!strcmp(str,(*curString))) return limitNList[index];
113  	      index++;
114  	    }
115  	  }
116  	  return -1;                            // Not found, no limit
117  	}
118  	//_____________________________________________________________________________
119  	void StMessageCounter::ListLimits() {
120  	  if (yesLimits) {
121  	    myout << "StMessage Limits: negative limit means no limit, ";
122  	    myout << "-5 means fixed with no limit\n";
123  	    myout << "  Limits :   counts : on message types" << endl;
124  	    size_t index=0;
125  	    for (index = 1; index < limitTList.size(); index++) {
126  	      myout.width(8);
127  	      myout << limitTList[index] << " : ";
128  	      myout.width(8);
129  	      myout << limitTCountList[index] << " : ";
130  	      myout << messTypeList->FindNumType(index) << " - ";
131  	      myout << messTypeList->FindNumText(index) << endl;
132  	    }
133  	    for (index = 0; index < limitWList.size(); index++) {
134  	      myout.width(8);
135  	      myout << limitWNList[index] << " : ";
136  	      myout.width(8);
137  	      myout << 0 << " : ";
138  	      myout << limitWList[index] << " - ";
139  	      myout << "???" << endl;
140  	    }
141  	    myout << "  Limits :   counts : on message strings" << endl;
142  	    index=0;
143  	    for (curString=limitList.begin(); curString!=limitList.end();
144  	                                      curString++) {
145  	      myout.width(8);
146  	      myout << limitNList[index] << " : ";
147  	      myout.width(8);
148  	      myout << limitNCountList[index++] << " : ";
149  	      myout << (*curString) << endl;
150  	    }
151  	  } else {
152  	    myout << "No limits have been set on messages." << endl;
153  	  }
154  	  return;
155  	}
156  	//_____________________________________________________________________________
157  	int StMessageCounter::CheckLimit(char* mess, const char* type) {
158  	  static const char* leader="St";
159  	  static const char* colon =": ";
160  	  static const char* stmess="StMessage: ";
161  	  int printIt = 1;
162  	  int typeN = messTypeList->FindTypeNum(type);
163  	  int typeNewSize = limitTCountList[typeN] + 1;
164  	  limitTCountList[typeN] = typeNewSize;
165  	
166  	  if (yesLimits && (! noLimits)) {
167  	    seekp(0);
168  	    int limit = limitTList[typeN];
169  	    if (typeNewSize == limit) {
170  	      *this << leader;
171  	      *this << (messTypeList->FindType(type)->Text());
172  	      *this << colon << limitMessage;
173  	    } else if ((limit >= 0) && (typeNewSize > limit)) {
174  	      printIt = 0;
175  	    }
176  	
177  	    size_t index=0;
178  	    for (curString=limitList.begin(); curString!=limitList.end();
179  	                                      curString++) {
180  	      if (strstr(mess,(*curString))) {
181  	        int counts = limitNCountList[index] + 1;
182  	        limitNCountList[index] = counts;
183  	        limit = limitNList[index];
184  	        if (counts==limit) {
185  	          *this << stmess << (*curString) << limitMessage;
186  	        } else if ((limit >= 0) && (counts > limit)) {
187  	          printIt = 0;
188  	        }
189  	      }
190  	      index++;
191  	    }
192  	    *this << ends;
193  	  }
194  	  return printIt;
195  	}
196  	//_____________________________________________________________________________
197  	void StMessageCounter::AddType(const char* type) {
198  	  limitTList.push_back(-1);
199  	  limitTCountList.push_back(0);
200  	  if (limitWList.size()) {
201  	    size_t index=0;                                // Now check the waiting list
202  	    for (curString=limitWList.begin(); curString!=limitWList.end();
203  	                                       curString++) {
204  	      if (*type == *(*curString)) {
205  	        SetLimit((*curString),limitWNList[index]);
206  	        limitWList.erase(curString);
207  	        limitWNList.erase(limitWNList.begin()+index);
208  	        return;
209  	      }
210  	      index++;
211  	    }
212  	  }
213  	}
214  	
215  	//_____________________________________________________________________________
216  	// $Id: StMessageCounter.cxx,v 1.22 2016/06/14 06:26:34 genevb Exp $
217  	// $Log: StMessageCounter.cxx,v $
218  	// Revision 1.22  2016/06/14 06:26:34  genevb
219  	// better initializations (Coverity)
220  	//
221  	// Revision 1.21  2012/06/11 15:05:34  fisyak
222  	// std namespace
223  	//
224  	// Revision 1.20  2009/08/26 19:39:04  fine
225  	// fix the compilation issues under SL5_64_bits  gcc 4.3.2
226  	//
227  	// Revision 1.19  2003/10/01 20:06:50  genevb
228  	// Initialize and test ostrstream buffer sizes (support for gcc before 3.2)
229  	//
230  	// Revision 1.18  2003/09/25 21:19:22  genevb
231  	// Some new cout-like functions and friend functions, some doxygen-ization
232  	//
233  	// Revision 1.17  2003/09/02 17:59:20  perev
234  	// gcc 3.2 updates + WarnOff
235  	//
236  	// Revision 1.16  2000/06/07 00:05:36  genevb
237  	// Added FixOn(), enforcing no limits on a specific message type/string
238  	//
239  	// Revision 1.15  2000/03/30 16:12:55  genevb
240  	// Add NoLimits() capability to turn off message limiting.
241  	//
242  	// Revision 1.14  2000/03/24 14:48:39  genevb
243  	// Insurance on end-of-strings
244  	//
245  	// Revision 1.13  2000/01/05 19:53:46  genevb
246  	// Fixed CC5 warnings, and several other small improvements under the hood
247  	//
248  	// Revision 1.12  1999/07/17 00:38:03  genevb
249  	// Small typo
250  	//
251  	// Revision 1.11  1999/07/17 00:23:23  genevb
252  	// Fixed bug when option fields are empty in FORTRAN, and let type limits be set before types are even added
253  	//
254  	// Revision 1.10  1999/07/15 05:15:06  genevb
255  	// Fixed an odd bug with seekp(0) on an empty stream buffer
256  	//
257  	// Revision 1.9  1999/07/01 01:24:46  genevb
258  	// Fixed FORTRAN character string bug on linux, removed a memory leak from Summary()
259  	//
260  	// Revision 1.7  1999/06/30 04:18:45  genevb
261  	// Fixes: summary wrap-around, unsigned ints, last character of message, <> for time; no KNOWN remaining bugs
262  	//
263  	// Revision 1.6  1999/06/29 17:37:31  genevb
264  	// Lots of fixes...
265  	//
266  	// Revision 1.5  1999/06/28 02:40:55  genevb
267  	// Additional backward compatibilit with MSG (msg_enable, msg_enabled, msg_disable
268  	//
269  	// Revision 1.4  1999/06/26 00:24:52  genevb
270  	// Fixed const type mismatches
271  	//
272  	// Revision 1.3  1999/06/25 22:57:56  genevb
273  	// Fixed a small bug in MSG compatibiliti
274  	//
275  	// Revision 1.2  1999/06/24 16:30:42  genevb
276  	// Fixed some memory leaks
277  	//
278  	// Revision 1.1  1999/06/23 15:17:49  genevb
279  	// Introduction of StMessageManager
280  	//
281