My Project
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 <opm/common/OpmLog/LogUtil.hpp>
24 #include <cassert>
25 #include <map>
26 #include <string>
27 #include <unordered_map>
28 #include <vector>
29 
30 
31 namespace Opm
32 {
33 
34 
37  {
38  public:
40  enum { NoLimit = -1 };
41 
44  : MessageLimiter(NoLimit)
45  {
46  }
47 
54  explicit MessageLimiter(const int tag_limit)
55  : tag_limit_(tag_limit < 0 ? NoLimit : tag_limit),
56  category_limits_({{Log::MessageType::Debug, NoLimit},
57  {Log::MessageType::Note, NoLimit},
58  {Log::MessageType::Info, NoLimit},
59  {Log::MessageType::Warning, NoLimit},
60  {Log::MessageType::Error, NoLimit},
61  {Log::MessageType::Problem, NoLimit},
62  {Log::MessageType::Bug, NoLimit}})
63  {
64  }
65 
66  MessageLimiter(const int tag_limit, const std::map<int64_t, int>& category_limits)
67  : tag_limit_(tag_limit < 0 ? NoLimit : tag_limit),
68  category_limits_(category_limits)
69  {
70  // Must ensure NoLimit for categories that are not
71  // explicitly specified in the input.
72  for (auto category : { Log::MessageType::Debug,
73  Log::MessageType::Note,
74  Log::MessageType::Info,
75  Log::MessageType::Warning,
76  Log::MessageType::Error,
77  Log::MessageType::Problem,
78  Log::MessageType::Bug }) {
79  if (category_limits_.find(category) == category_limits_.end()) {
80  category_limits_[category] = NoLimit;
81  }
82  }
83  }
84 
86  int tagMessageLimit() const
87  {
88  return tag_limit_;
89  }
90 
92  const std::map<int64_t, int>& categoryMessageLimits() const
93  {
94  return category_limits_;
95  }
96 
98  const std::map<int64_t, int>& categoryMessageCounts() const
99  {
100  return category_counts_;
101  }
102 
105  enum class Response
106  {
107  PrintMessage, JustOverTagLimit, JustOverCategoryLimit, OverTagLimit, OverCategoryLimit
108  };
109 
117  Response handleMessageLimits(const std::string& tag, const int64_t messageMask)
118  {
119  Response res = Response::PrintMessage;
120 
121  // Deal with tag limits.
122  if (!tag.empty() && tag_limit_ != NoLimit) {
123  // See if tag already encountered.
124  auto it = tag_counts_.find(tag);
125  if (it != tag_counts_.end()) {
126  // Already encountered this tag. Increment its count.
127  const int count = ++it->second;
128  res = countBasedResponseTag(count);
129  } else {
130  // First encounter of this tag. Insert 1.
131  tag_counts_.insert({tag, 1});
132  res = countBasedResponseTag(1);
133  }
134  }
135 
136  // If tag count reached the limit, the message is not counted
137  // towards the category limits.
138  if (res == Response::PrintMessage) {
139  // We are *not* above the tag limit, consider category limit.
140  const int count = ++category_counts_[messageMask];
141  if (category_limits_[messageMask] != NoLimit) {
142  res = countBasedResponseCategory(count, messageMask);
143  }
144  }
145 
146  return res;
147  }
148 
149  private:
150  Response countBasedResponseTag(const int count) const
151  {
152  if (count <= tag_limit_) {
153  return Response::PrintMessage;
154  } else if (count == tag_limit_ + 1) {
155  return Response::JustOverTagLimit;
156  } else {
157  return Response::OverTagLimit;
158  }
159  }
160 
161 
162  Response countBasedResponseCategory(const int count, const int64_t messageMask) const
163  {
164  const int limit = category_limits_.at(messageMask);
165  if (count <= limit) {
166  return Response::PrintMessage;
167  } else if (count == limit + 1) {
168  return Response::JustOverCategoryLimit;
169  } else {
170  return Response::OverCategoryLimit;
171  }
172  }
173 
174  int tag_limit_;
175  std::unordered_map<std::string, int> tag_counts_;
176  std::map<int64_t, int> category_limits_;
177  std::map<int64_t, int> category_counts_ = {{Log::MessageType::Note, 0},
178  {Log::MessageType::Info, 0},
179  {Log::MessageType::Warning, 0},
180  {Log::MessageType::Error, 0},
181  {Log::MessageType::Problem, 0},
182  {Log::MessageType::Bug, 0}};
183  };
184 
185 
186 
187 } // namespace Opm
188 
189 #endif // OPM_MESSAGELIMITER_HEADER_INCLUDED
Handles limiting the number of messages with the same tag.
Definition: MessageLimiter.hpp:37
Response handleMessageLimits(const std::string &tag, const int64_t messageMask)
If (tag count == tag limit + 1) for the passed tag, respond JustOverTagLimit.
Definition: MessageLimiter.hpp:117
const std::map< int64_t, int > & categoryMessageCounts() const
The category message counts.
Definition: MessageLimiter.hpp:98
Response
Used for handleMessageLimits() return type (see that function).
Definition: MessageLimiter.hpp:106
MessageLimiter(const int tag_limit)
Construct with given limit to number of messages with the same tag.
Definition: MessageLimiter.hpp:54
int tagMessageLimit() const
The tag message limit (same for all tags).
Definition: MessageLimiter.hpp:86
const std::map< int64_t, int > & categoryMessageLimits() const
The category message limits.
Definition: MessageLimiter.hpp:92
MessageLimiter()
Default constructor, no limit to the number of messages.
Definition: MessageLimiter.hpp:43
This class implements a small container which holds the transmissibility mulitpliers for all the face...
Definition: Exceptions.hpp:29