opm-common
MessageLimiter.hpp
1 /*
2  Copyright 2016 SINTEF ICT, Applied Mathematics.
3 
4  This file is part of the Open Porous Media project (OPM).
5 
6  OPM is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  OPM is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with OPM. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #ifndef OPM_MESSAGELIMITER_HEADER_INCLUDED
21 #define OPM_MESSAGELIMITER_HEADER_INCLUDED
22 
23 #include <cstdint>
24 #include <map>
25 #include <string>
26 #include <unordered_map>
27 
28 namespace Opm
29 {
30 
31 
34  {
35  public:
37  enum { NoLimit = -1 };
38 
40  enum class Response
41  {
44 
47 
50 
53 
56  };
57 
59  MessageLimiter() = default;
60 
67  explicit MessageLimiter(const int tag_limit)
68  : MessageLimiter { tag_limit, {} }
69  {}
70 
71  MessageLimiter(const int tag_limit, const std::map<std::int64_t, int>& category_limits)
72  : tag_limit_ { (tag_limit < 0) ? NoLimit : tag_limit }
73  , category_limits_ { category_limits }
74  {}
75 
77  int tagMessageLimit() const
78  {
79  return tag_limit_;
80  }
81 
89  Response handleMessageLimits(const std::string& tag,
90  const std::int64_t messageMask) const
91  {
93 
94  // Deal with tag limits.
95  if (!tag.empty() && (this->tag_limit_ != NoLimit)) {
96  res = this->countBasedResponseTag(this->increaseTagCount(tag));
97  }
98 
99  if (res != Response::PrintMessage) {
100  // Tag count reached limit. Do not include message in
101  // category count.
102  return res;
103  }
104 
105  // Tag count within limits. Include message in category count.
106  const auto count = this->increaseCategoryCount(messageMask);
107 
108  if (const auto limitPos = this->category_limits_.find(messageMask);
109  (limitPos != this->category_limits_.end()) &&
110  (limitPos->second != NoLimit))
111  {
112  // There is a defined category limit for 'messageMask'.
113  // Generate response based on this limit.
114  res = this->countBasedResponseCategory(count, limitPos->second);
115  }
116 
117  // PrintMessage or category based response.
118  return res;
119  }
120 
128  int categoryMessageCount(const std::int64_t category) const
129  {
130  const auto countPos = this->category_counts_.find(category);
131 
132  return (countPos != this->category_counts_.end())
133  ? countPos->second : 0;
134  }
135 
136  private:
140  int tag_limit_ {NoLimit};
141 
147  std::map<std::int64_t, int> category_limits_{};
148 
150  mutable std::unordered_map<std::string, int> tag_counts_{};
151 
153  mutable std::map<std::int64_t, int> category_counts_{};
154 
155  int increaseTagCount(const std::string& tag) const
156  {
157  return increaseCount(tag, this->tag_counts_);
158  }
159 
160  int increaseCategoryCount(const std::int64_t messageMask) const
161  {
162  return increaseCount(messageMask, this->category_counts_);
163  }
164 
165  Response countBasedResponseTag(const int count) const
166  {
167  return response(count, this->tag_limit_,
170  }
171 
172  Response countBasedResponseCategory(const int count,
173  const int category_limit) const
174  {
175  return response(count, category_limit,
178  }
179 
180  template <typename Key, class CountMap>
181  static int increaseCount(const Key& key, CountMap& counts)
182  {
183  return ++counts.try_emplace(key, 0).first->second;
184  }
185 
186  static Response response(const int count,
187  const int limit,
188  const Response justOverLimit,
189  const Response overLimit)
190  {
191  if (count <= limit) {
192  return Response::PrintMessage;
193  } else if (count == limit + 1) {
194  return justOverLimit;
195  } else {
196  return overLimit;
197  }
198  }
199  };
200 
201 } // namespace Opm
202 
203 #endif // OPM_MESSAGELIMITER_HEADER_INCLUDED
Response handleMessageLimits(const std::string &tag, const std::int64_t messageMask) const
If (tag count == tag limit + 1) for the passed tag, respond JustOverTagLimit.
Definition: MessageLimiter.hpp:89
Message is over the current limit of this category.
This class implements a small container which holds the transmissibility mulitpliers for all the face...
Definition: Exceptions.hpp:30
Message should be printed. Not affected by any limit.
Message has reached the current limit for this tag.
Message has reached the current limit for this category.
Response
Used for handleMessageLimits() return type (see that function).
Definition: MessageLimiter.hpp:40
int categoryMessageCount(const std::int64_t category) const
Retrieve message count for specific category.
Definition: MessageLimiter.hpp:128
int tagMessageLimit() const
The tag message limit (same for all tags).
Definition: MessageLimiter.hpp:77
MessageLimiter()=default
Default constructor, no limit to the number of messages.
Handles limiting the number of messages with the same tag.
Definition: MessageLimiter.hpp:33
Message is over the current limit for this tag.
MessageLimiter(const int tag_limit)
Construct with given limit to number of messages with the same tag.
Definition: MessageLimiter.hpp:67