2323
2424#include < fstream>
2525#include < iomanip>
26+ #include < queue>
2627#include < set>
2728#include < sstream>
2829
@@ -209,10 +210,17 @@ bool DuplicateFilter::matchDef(const Defect &def)
209210// implementation of RateLimitter
210211
211212struct RateLimitter ::Private {
213+ // counter of checker/key-event pairs
212214 using TKey = std::pair<std::string, std::string>;
213215 using TCnt = int ;
214216 using TMap = std::map<TKey, TCnt>;
215217 TMap counter;
218+
219+ // list of defects where the limit was exceeded
220+ using TErrorList = std::queue<Defect>;
221+ TErrorList errors;
222+
223+ // rate limit set during initialization
216224 TCnt rateLimit;
217225};
218226
@@ -226,50 +234,59 @@ RateLimitter::RateLimitter(AbstractWriter *agent, int rateLimit):
226234bool RateLimitter::matchDef (const Defect &def)
227235{
228236 // resolve the checker/event pair for the key event
229- const DefEvent & evt = def.events [def.keyEventIdx ];
237+ DefEvent evt = def.events [def.keyEventIdx ];
230238 const Private::TKey key (def.checker , evt.event );
231239
232240 // increment the counter and get the current value
233241 const Private::TCnt cnt = ++d->counter [key];
234242
235243 // check whether the specified limit is exceeded
236- return (cnt < d->rateLimit );
244+ if (cnt < d->rateLimit )
245+ return true ;
246+
247+ if (cnt == d->rateLimit ) {
248+ // record defect prototype containing the key event only (without msg)
249+ evt.msg .clear ();
250+
251+ Defect defProto = def;
252+ defProto.events .clear ();
253+ defProto.events .push_back (std::move (evt));
254+ d->errors .push (std::move (defProto));
255+ }
256+
257+ // limit exceeded
258+ return false ;
237259}
238260
239261void RateLimitter::flush ()
240262{
241- for (const auto &item : d->counter ) {
242- const Private::TCnt cnt = item.second ;
243- if (cnt < d->rateLimit )
244- // limit not exceeded for this checker/event pair
245- continue ;
263+ for (; !d->errors .empty (); d->errors .pop ()) {
264+ Defect &def = d->errors .front ();
246265
247- // resolve the checker/event pair
248- const Private::TKey &key = item. first ;
249- const std::string & checker = key. first ;
250- const std::string &keyEvtName = key. second ;
266+ // resolve the count of occurrences for this checker/event pair
267+ const DefEvent &keyEvt = def. events [def. keyEventIdx ] ;
268+ const Private::TKey key (def. checker , keyEvt. event ) ;
269+ const Private::TCnt cnt = d-> counter [ key] ;
251270
252271 // construct an error event
253272 std::ostringstream err, note;
254- err << cnt << " occurrences of " << keyEvtName
273+ err << cnt << " occurrences of " << keyEvt. event
255274 << " exceeded the specified limit "
256275 << d->rateLimit ;
257276
258- DefEvent evtErr (" error[too-many]" );
277+ DefEvent &evtErr = def.events .back ();
278+ evtErr.event = " error[too-many]" ;
259279 evtErr.msg = err.str ();
260280
261281 // construct a note event
262282 note << (cnt - d->rateLimit ) << " occurrences of "
263- << keyEvtName << " were discarded because of this" ;
283+ << keyEvt. event << " were discarded because of this" ;
264284
265- DefEvent evtNote (" note" );
285+ DefEvent evtNote = evtErr;
286+ evtNote.event = " note" ;
266287 evtNote.msg = note.str ();
267288 evtNote.verbosityLevel = /* info */ 1 ;
268-
269- // construct a defect containing the above events
270- Defect def (checker);
271- def.events .push_back (evtErr);
272- def.events .push_back (evtNote);
289+ def.events .push_back (std::move (evtNote));
273290
274291 // process the newly constructed defect by the chain of writers
275292 GenericAbstractFilter::handleDef (def);
0 commit comments