BDE 4.14.0 Production release
Loading...
Searching...
No Matches
ball_ruleset.h
Go to the documentation of this file.
1/// @file ball_ruleset.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// ball_ruleset.h -*-C++-*-
8#ifndef INCLUDED_BALL_RULESET
9#define INCLUDED_BALL_RULESET
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup ball_ruleset ball_ruleset
15/// @brief Provide a set of unique rules.
16/// @addtogroup bal
17/// @{
18/// @addtogroup ball
19/// @{
20/// @addtogroup ball_ruleset
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#ball_ruleset-purpose"> Purpose</a>
25/// * <a href="#ball_ruleset-classes"> Classes </a>
26/// * <a href="#ball_ruleset-description"> Description </a>
27/// * <a href="#ball_ruleset-thread-safety"> Thread Safety </a>
28/// * <a href="#ball_ruleset-usage"> Usage </a>
29///
30/// # Purpose {#ball_ruleset-purpose}
31/// Provide a set of unique rules.
32///
33/// # Classes {#ball_ruleset-classes}
34///
35/// - ball::RuleSet: container for unique rules
36///
37/// @see ball_rule
38///
39/// # Description {#ball_ruleset-description}
40/// This component provides a value-semantic container,
41/// `ball::RuleSet`, for storage and efficient retrieval of `ball::Rule`
42/// objects.
43///
44/// This component participates in the implementation of "Rule-Based Logging".
45/// For more information on how to use that feature, please see the package
46/// level documentation and usage examples for "Rule-Based Logging".
47///
48/// ## Thread Safety {#ball_ruleset-thread-safety}
49///
50///
51/// `ball::RuleSet` is *not* thread-safe in that multiple threads attempting to
52/// concurrently modify the same `ball::RuleSet` object will leave the object in
53/// an undefined state. To ensure thread-safety, concurrent accesses to a
54/// `ball::RuleSet` must be serialized by a mutex.
55///
56/// ## Usage {#ball_ruleset-usage}
57///
58///
59/// The following code fragments illustrate how to use a rule set.
60///
61/// We first create a rule whose pattern is `WEEKEND*` and whose threshold
62/// levels are all `ball::Severity::e_OFF` except the `pass-through` level. A
63/// `pass-through` level of `ball::Severity::e_INFO` indicates that whenever the
64/// rule is active and the severity equals or exceeds `ball::Severity::e_INFO`,
65/// log records will be passed to the observer:
66/// @code
67/// ball::Rule rule1("WEEKEND*", // pattern
68/// ball::Severity::e_OFF, // record level
69/// ball::Severity::e_INFO, // pass-through level
70/// ball::Severity::e_OFF, // trigger level
71/// ball::Severity::e_OFF); // triggerAll level
72/// @endcode
73/// Next, we create another rule having a different pattern, but the same
74/// threshold levels:
75/// @code
76/// ball::Rule rule2("WEEKDAY*", // pattern
77/// ball::Severity::e_OFF, // record level
78/// ball::Severity::e_INFO, // pass-through level
79/// ball::Severity::e_OFF, // trigger level
80/// ball::Severity::e_OFF); // triggerAll level
81/// @endcode
82/// We then create a `ball::RuleSet` object, add the two rules, and verify that
83/// rules were added correctly:
84/// @code
85/// ball::RuleSet ruleSet;
86/// assert(0 <= ruleSet.addRule(rule1));
87/// assert(0 <= ruleSet.addRule(rule2));
88/// assert(2 == ruleSet.numRules());
89/// @endcode
90/// Duplicate rules cannot be added:
91/// @code
92/// assert(-1 == ruleSet.addRule(rule1));
93/// assert(-1 == ruleSet.addRule(rule2));
94/// assert( 2 == ruleSet.numRules());
95/// @endcode
96/// Rules in a rule set can be looked up by the `ruleId` method:
97/// @code
98/// int i1 = ruleSet.ruleId(rule1);
99/// int i2 = ruleSet.ruleId(rule2);
100/// assert(0 <= i1); assert(i1 < ruleSet.maxNumRules());
101/// assert(0 <= i2); assert(i2 < ruleSet.maxNumRules());
102/// assert(i1 != i2);
103/// @endcode
104/// The `removeRule` method can be used to remove rules from a rule set.
105/// @code
106/// assert(ruleSet.removeRule(rule1));
107/// assert(1 == ruleSet.numRules());
108/// assert(ruleSet.ruleId(rule1) < 0);
109/// assert(ruleSet.ruleId(rule2) == i2);
110/// @endcode
111/// @}
112/** @} */
113/** @} */
114
115/** @addtogroup bal
116 * @{
117 */
118/** @addtogroup ball
119 * @{
120 */
121/** @addtogroup ball_ruleset
122 * @{
123 */
124
125#include <balscm_version.h>
126
127#include <ball_rule.h>
128
129#include <bslma_allocator.h>
131
133
134#include <bsl_unordered_set.h>
135#include <bsl_vector.h>
136
137
138namespace ball {
139
140 // =============
141 // class RuleSet
142 // =============
143
144/// This class manages a set of unique rule values. Rules may be added to
145/// or removed from the set; however, rules having duplicate values will
146/// not be added. For the definition of two rules having the same value,
147/// please refer to the function-level documentation associated with the
148/// `Rule::operator==` function.
149///
150/// See @ref ball_ruleset
151class RuleSet {
152
153 public:
154 // PUBLIC TYPES
155
156 /// `MaskType` is an alias for the fundamental integral type used to
157 /// indicate rule subsets compactly.
158 typedef unsigned int MaskType;
159
160 enum {
161 e_MAX_NUM_RULES = 8 * sizeof(MaskType)
162 // The maximum number of rules managed by this object.
163
164#ifndef BDE_OMIT_INTERNAL_DEPRECATED
167#endif // BDE_OMIT_INTERNAL_DEPRECATED
168 };
169
170 private:
171 // PRIVATE TYPES
172
173 /// Hash functor for `Rule`.
174 struct RuleHash {
175
176 private:
177 // CLASS DATA
178 static int s_hashtableSize; // the default hashtable size
179
180 public:
181 // ACCESSORS
182
183 /// Return the hash value of the specified `rule`.
184 int operator()(const Rule& rule) const
185 {
186 return Rule::hash(rule, s_hashtableSize);
187 }
188 };
189
190 typedef bsl::unordered_set<Rule, RuleHash> HashtableType;
191
192 // DATA
193 HashtableType d_ruleHashtable; // the hash table that
194 // manages all the rules
195 // maintained by this rule set
196
197 bsl::vector<const Rule *> d_ruleAddresses; // secondary map between ids
198 // and the addresses of rules
199
200 bsl::vector<int> d_freeRuleIds; // rule Ids that are not being
201 // used
202
203 int d_numPredicates; // total number of predicates
204
205 // FRIENDS
206 friend bool operator==(const RuleSet&, const RuleSet&);
207 friend bool operator!=(const RuleSet&, const RuleSet&);
208 friend bsl::ostream& operator<<(bsl::ostream&, const RuleSet&);
209
210 public:
211 // CLASS METHODS
212
213 /// Return the maximum number of rules that can be simultaneously
214 /// maintained by this object.
215 static int maxNumRules();
216
217 /// Format the specified `mask` to the specified output `stream` at the
218 /// optionally specified indentation `level` and return a reference to
219 /// the modifiable `stream`. If `level` is specified, optionally
220 /// specify `spacesPerLevel`, the number of spaces per indentation level
221 /// for this and all of its nested objects. Each line is indented by
222 /// the absolute value of `level * spacesPerLevel`. If `level` is
223 /// negative, suppress indentation of the first line. If
224 /// `spacesPerLevel` is negative, suppress line breaks and format the
225 /// entire output on one line. If `stream` is initially invalid, this
226 /// operation has no effect.
227 static void printMask(bsl::ostream& stream,
228 MaskType mask,
229 int level = 0,
230 int spacesPerLevel = 0);
231
232 // TRAITS
234
235 // CREATORS
236
237 /// Create an empty rule set. Optionally specify a `basicAllocator`
238 /// used to supply memory. If `basicAllocator` is 0, the currently
239 /// installed default allocator will be used.
240 explicit RuleSet(bslma::Allocator *basicAllocator = 0);
241
242 /// Create a `RuleSet` object having the same value as that of the
243 /// specified `original` object. Optionally specify a `basicAllocator`
244 /// used to supply memory. If `basicAllocator` is 0, the currently
245 /// installed default allocator will be used.
246 RuleSet(const RuleSet& original, bslma::Allocator *basicAllocator = 0);
247
248 /// Destroy this object.
249 ~RuleSet() = default;
250
251 // MANIPULATOR
252
253 /// Create a new `Rule` object having the specified `value`. Return the
254 /// non-negative id of this non-modifiable object on success, and a
255 /// negative value otherwise. A return value of -1 indicates that
256 /// another rule having this value already exists. A return value of -2
257 /// indicates that the maximum number of rules for this rule set has
258 /// been reached.
259 int addRule(const Rule& value);
260
261 /// Add each rule in the specified `rules` to this rule set. Return
262 /// the number of rules added. Note that a rule in `rules` will be
263 /// ignored if there is an existing rule having the same value or if
264 /// the number of rules in the set has reached the upper limit. Also
265 /// note that if not all valid rules will fit, the (possibly empty)
266 /// subset of unique values that will be added is implementation
267 /// dependent.
268 int addRules(const RuleSet& rules);
269
270 /// Remove from this rule set the rule having the specified `id`.
271 /// Return the number of rules removed (i.e., 1 on success and 0 if
272 /// there is no rule whose id is `id`). The behavior is undefined
273 /// unless `0 <= id < e_MAX_NUM_RULES`.
274 int removeRuleById(int id);
275
276 /// Remove the rule having the specified `value` from this rule set.
277 /// Return the number of rules removed (i.e., 1 on success and 0 if
278 /// there is no such a rule).
279 int removeRule(const Rule& value);
280
281 /// Remove each rule in the specified `rules` from this rule set.
282 /// Return the number of rules removed.
283 int removeRules(const RuleSet& rules);
284
285 /// Remove every rule in the rule set maintained by this object.
287
288 /// Assign to this object the value of the specified `rhs` object.
290
291 // ACCESSORS
292
293 /// Return the id of the rule having the specified `value` if such a
294 /// rule exists, and a negative value otherwise. Note that if there are
295 /// multiple rules having `value`, the id of the first one found will be
296 /// returned and the order in which rules are searched is implementation
297 /// dependent.
298 int ruleId(const Rule& value) const;
299
300 /// Return the address of the rule having the specified `id` if such a
301 /// rule exists, and 0 otherwise. The behavior is undefined unless
302 /// `0 <= id < maxNumRules()`. Note that rules may be assigned
303 /// non-sequential identifiers, and that there may be a valid rule whose
304 /// identifier is greater than `numRules()` (i.e., valid rules may
305 /// appear anywhere in the range `0 <= id < maxNumRules()`).
306 const Rule *getRuleById(int id) const;
307
308 /// Return the number of unique rules maintained in this `RuleSet`
309 /// object. Note that this value is *not* the maximum identifier for
310 /// the rules currently in this container.
311 int numRules() const;
312
313 /// Return the total number of predicates in all rules maintained by
314 /// this object.
315 int numPredicates() const;
316
317 /// Format this object to the specified output `stream` at the
318 /// (absolute value of) the optionally specified indentation `level`
319 /// and return a reference to `stream`. If `level` is specified,
320 /// optionally specify `spacesPerLevel`, the number of spaces per
321 /// indentation level for this and all of its nested objects. If
322 /// `level` is negative, suppress indentation of the first line. If
323 /// `spacesPerLevel` is negative, format the entire output on one line,
324 /// suppressing all but the initial indentation (as governed by
325 /// `level`). If `stream` is not valid on entry, this operation has no
326 /// effect.
327 bsl::ostream& print(bsl::ostream& stream,
328 int level = 0,
329 int spacesPerLevel = 4) const;
330};
331
332// FREE OPERATORS
333
334/// Return `true` if the specified `lhs` and `rhs` rule sets have the same
335/// value, and `false` otherwise. Two rule sets have the same value if
336/// every rule that exists in one rule set also exists in the other.
337bool operator==(const RuleSet& lhs, const RuleSet& rhs);
338
339/// Return `true` if the specified `lhs` and `rhs` rule sets do not have the
340/// same value, and `false` otherwise. Two rule sets do not have the same
341/// value if there is at least one rule that exists in one rule but does not
342/// exist in the other.
343bool operator!=(const RuleSet& lhs, const RuleSet& rhs);
344
345/// Write the value of the specified `rules` to the specified `output`
346/// stream. Return the specified `output` stream
347bsl::ostream& operator<<(bsl::ostream& output, const RuleSet& rules);
348
349// ============================================================================
350// INLINE DEFINITIONS
351// ============================================================================
352
353 // -------------
354 // class RuleSet
355 // -------------
356
357// CLASS METHODS
358inline
360{
361 return e_MAX_NUM_RULES;
362}
363
364// ACCESSORS
365inline
366const Rule *RuleSet::getRuleById(int id) const
367{
368 return d_ruleAddresses[id];
369}
370
371inline
373{
374 return static_cast<int>(d_ruleHashtable.size());
375}
376
377inline
379{
380 return d_numPredicates;
381}
382
383} // close package namespace
384
385inline
386bsl::ostream& ball::operator<<(bsl::ostream& output, const RuleSet& rules)
387{
388 return rules.print(output, 0, -1);
389}
390
391
392
393#endif
394
395// ----------------------------------------------------------------------------
396// Copyright 2015 Bloomberg Finance L.P.
397//
398// Licensed under the Apache License, Version 2.0 (the "License");
399// you may not use this file except in compliance with the License.
400// You may obtain a copy of the License at
401//
402// http://www.apache.org/licenses/LICENSE-2.0
403//
404// Unless required by applicable law or agreed to in writing, software
405// distributed under the License is distributed on an "AS IS" BASIS,
406// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
407// See the License for the specific language governing permissions and
408// limitations under the License.
409// ----------------------------- END-OF-FILE ----------------------------------
410
411/** @} */
412/** @} */
413/** @} */
Definition ball_ruleset.h:151
static int maxNumRules()
Definition ball_ruleset.h:359
friend bool operator!=(const RuleSet &, const RuleSet &)
int removeRuleById(int id)
static void printMask(bsl::ostream &stream, MaskType mask, int level=0, int spacesPerLevel=0)
RuleSet(const RuleSet &original, bslma::Allocator *basicAllocator=0)
const Rule * getRuleById(int id) const
Definition ball_ruleset.h:366
int addRule(const Rule &value)
int ruleId(const Rule &value) const
int numPredicates() const
Definition ball_ruleset.h:378
friend bool operator==(const RuleSet &, const RuleSet &)
int addRules(const RuleSet &rules)
friend bsl::ostream & operator<<(bsl::ostream &, const RuleSet &)
RuleSet(bslma::Allocator *basicAllocator=0)
bsl::ostream & print(bsl::ostream &stream, int level=0, int spacesPerLevel=4) const
BSLMF_NESTED_TRAIT_DECLARATION(RuleSet, bslma::UsesBslmaAllocator)
@ BAEL_MAX_NUM_RULES
Definition ball_ruleset.h:165
@ e_MAX_NUM_RULES
Definition ball_ruleset.h:161
@ MAX_NUM_RULES
Definition ball_ruleset.h:166
RuleSet & operator=(const RuleSet &rhs)
Assign to this object the value of the specified rhs object.
int removeRules(const RuleSet &rules)
void removeAllRules()
Remove every rule in the rule set maintained by this object.
int removeRule(const Rule &value)
unsigned int MaskType
Definition ball_ruleset.h:158
int numRules() const
Definition ball_ruleset.h:372
~RuleSet()=default
Destroy this object.
Definition ball_rule.h:177
static int hash(const Rule &rule, int size)
Definition bslstl_unorderedset.h:704
size_type size() const BSLS_KEYWORD_NOEXCEPT
Return the number of elements in this set.
Definition bslstl_unorderedset.h:2469
Definition bslstl_vector.h:1025
Definition bslma_allocator.h:457
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition ball_administration.h:214
bsl::ostream & operator<<(bsl::ostream &output, const Attribute &attribute)
Definition bslma_usesbslmaallocator.h:343