BDE 4.39.x Production Release
Loading...
Searching...
No Matches
ball_context.h
Go to the documentation of this file.
1/// @file ball_context.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// ball_context.h -*-C++-*-
8#ifndef INCLUDED_BALL_CONTEXT
9#define INCLUDED_BALL_CONTEXT
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup ball_context ball_context
15/// @brief Provide a container for the context of a transmitted log record.
16/// @addtogroup bal
17/// @{
18/// @addtogroup ball
19/// @{
20/// @addtogroup ball_context
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#ball_context-purpose"> Purpose</a>
25/// * <a href="#ball_context-classes"> Classes </a>
26/// * <a href="#ball_context-description"> Description </a>
27/// * <a href="#ball_context-constraints"> Constraints </a>
28/// * <a href="#ball_context-usage"> Usage </a>
29/// * <a href="#ball_context-example-1-basic-usage"> Example 1: Basic Usage </a>
30///
31/// # Purpose {#ball_context-purpose}
32/// Provide a container for the context of a transmitted log record.
33///
34/// # Classes {#ball_context-classes}
35///
36/// - ball::Context: context of a transmitted log record
37///
38/// @see ball_transmission, ball_observer, ball_record
39///
40/// # Description {#ball_context-description}
41/// This component defines a container for aggregating a message's
42/// publication cause, as well as the record (or message) index and sequence
43/// length of messages delivered as part of a message sequence. Note that
44/// messages that are not part of a sequence (i.e., PASSTHROUGH) will have the
45/// index and sequence length fields set to 0 and 1, respectively.
46///
47/// The context attributes held by `ball::Context` are detailed in the following
48/// table:
49/// @code
50/// Attribute Type Description Default
51/// ----------------- ------------------------ ----------------- -----------
52/// transmissionCause ball::Transmission::Cause cause of output PASSTHROUGH
53/// recordIndex int index in sequence 0
54/// sequenceLength int # records in seq. 1
55/// @endcode
56///
57/// ## Constraints {#ball_context-constraints}
58///
59///
60/// This attribute class assumes that the following constraints on contained
61/// values hold:
62/// @code
63/// if (ball::Transmission::e_PASSTHROUGH == transmissionCause()) {
64/// assert(0 == recordIndex());
65/// assert(1 == sequenceLength());
66/// }
67/// else {
68/// assert(
69/// ball::Transmission::e_TRIGGER == transmissionCause()
70/// || ball::Transmission::e_TRIGGER_ALL == transmissionCause()
71/// || ball::Transmission::e_MANUAL_PUBLISH == transmissionCause()
72/// || ball::Transmission::e_MANUAL_PUBLISH_ALL == transmissionCause());
73/// assert(0 <= recordIndex());
74/// assert(1 <= sequenceLength());
75/// assert(recordIndex() < sequenceLength());
76/// }
77/// @endcode
78/// A static `isValid` method is provided to verify that particular
79/// `transmissionCause`, `recordIndex`, and `sequenceLength` values are valid
80/// before they are used to create or (unilaterally) modify a context object.
81///
82/// ## Usage {#ball_context-usage}
83///
84///
85/// This section illustrates intended use of this component.
86///
87/// ### Example 1: Basic Usage {#ball_context-example-1-basic-usage}
88///
89///
90/// A `ball::Context` object holds sufficient information to determine the
91/// length of a message sequence and the index of a message within that
92/// sequence. In addition, `ball::Context` indicates the cause for the
93/// transmission of a message. The following example illustrates the essentials
94/// of working with these contextual attributes.
95///
96/// This example illustrates the use of `ball::Context` by a hypothetical
97/// logging system. First we define a simple logger class named `my_Logger`:
98/// @code
99/// // my_logger.h
100///
101/// #include <string>
102/// #include <vector>
103///
104/// class my_Logger {
105///
106/// bsl::vector<bsl::string> archive; // log message archive
107///
108/// private:
109/// // NOT IMPLEMENTED
110/// my_Logger(const my_Logger&);
111/// my_Logger& operator=(const my_Logger&);
112///
113/// // PRIVATE MANIPULATORS
114/// void publish(const bsl::string& message,
115/// const ball::Context& context);
116///
117/// public:
118/// // TYPES
119/// enum Severity { ERROR = 0, WARN = 1, TRACE = 2 };
120///
121/// // CREATORS
122/// my_Logger();
123/// ~my_Logger();
124///
125/// // MANIPULATORS
126/// void logMessage(const bsl::string& message, Severity severity);
127/// };
128/// @endcode
129/// Clients of `my_Logger` log messages at one of three severity levels through
130/// the `logMessage` method. Messages logged with `TRACE` severity are simply
131/// archived by `my_Logger`. Messages logged with `WARN` severity are archived
132/// and also output to `stdout` (say, to a console terminal overseen by an
133/// operator) through the `publish` method. Messages logged with `ERROR`
134/// severity report serious conditions; these trigger a dump of the backlog of
135/// messages that `my_Logger` has archived to that point. The `ball::Context`
136/// argument passed to `publish` provides contextual information regarding the
137/// message it is being asked to publish.
138///
139/// A complete implementation of this trivial logger follows:
140/// @code
141/// // my_Logger.cpp
142///
143/// // PRIVATE MANIPULATORS
144/// void my_Logger::publish(const bsl::string& message,
145/// const ball::Context& context)
146/// {
147/// using namespace std;
148///
149/// switch (context.transmissionCause()) {
150/// case ball::Transmission::e_PASSTHROUGH: {
151/// cout << "Single Pass-through Message: ";
152/// } break;
153/// case ball::Transmission::e_TRIGGER_ALL: {
154/// cout << "Remotely "; // no 'break'; concatenated
155/// // output
156/// } break;
157/// case ball::Transmission::e_TRIGGER: {
158/// cout << "Triggered Publication Sequence: Message "
159/// << context.recordIndex() + 1 // Account for 0-based index.
160/// << " of " << context.sequenceLength() << ": ";
161/// } break;
162/// case ball::Transmission::e_MANUAL_PUBLISH: {
163/// cout << "Manually triggered Message: ";
164/// } break;
165/// default: {
166/// cout << "***ERROR*** Unsupported Message Cause: ";
167/// return;
168/// } break;
169/// }
170/// cout << message << endl;
171/// }
172///
173/// // CREATORS
174/// my_Logger::my_Logger() { }
175/// my_Logger::~my_Logger() { }
176///
177/// // MANIPULATORS
178/// void my_Logger::logMessage(const bsl::string& message, Severity severity)
179/// {
180/// archive.append(message);
181/// switch (severity) {
182/// case TRACE: {
183/// // Do nothing beyond archiving the message.
184/// } break;
185/// case WARN: {
186/// ball::Context context(ball::Transmission::e_PASSTHROUGH, 0, 1);
187/// publish(message, context);
188/// } break;
189/// case ERROR: {
190/// int index = 0;
191/// int length = archive.length();
192/// ball::Context context(ball::Transmission::e_TRIGGER,
193/// index, length);
194/// while (length--) {
195/// publish(archive[length], context);
196/// context.setRecordIndexRaw(++index);
197/// }
198/// archive.removeAll(); // flush archive
199/// } break;
200/// }
201/// }
202/// @endcode
203/// Note that `ball::Transmission::e_TRIGGER_ALL` is not used by `my_Logger`,
204/// but is included in the switch statement for completeness.
205///
206/// Finally, we declare a `my_Logger` named `logger` and simulate the logging of
207/// several messages of varying severity:
208/// @code
209/// my_Logger logger;
210/// bsl::string message;
211///
212/// message = "TRACE 1"; logger.logMessage(message, my_Logger::TRACE);
213/// message = "TRACE 2"; logger.logMessage(message, my_Logger::TRACE);
214/// message = "WARNING"; logger.logMessage(message, my_Logger::WARN);
215/// message = "TRACE 3"; logger.logMessage(message, my_Logger::TRACE);
216/// message = "TROUBLE!"; logger.logMessage(message, my_Logger::ERROR);
217/// @endcode
218/// The following output is produced on `stdout`:
219/// @code
220/// Single Pass-through Message: WARNING
221/// Triggered Publication Sequence: Message 1 of 5: TROUBLE!
222/// Triggered Publication Sequence: Message 2 of 5: TRACE 3
223/// Triggered Publication Sequence: Message 3 of 5: WARNING
224/// Triggered Publication Sequence: Message 4 of 5: TRACE 2
225/// Triggered Publication Sequence: Message 5 of 5: TRACE 1
226/// @endcode
227/// Note that the warning message (severity `WARN`) was emitted first since the
228/// trace messages (severity `TRACE`) were simply archived. When the error
229/// message (severity `ERROR`) was logged, it triggered a dump of the complete
230/// message archive (in reverse order).
231/// @}
232/** @} */
233/** @} */
234
235/** @addtogroup bal
236 * @{
237 */
238/** @addtogroup ball
239 * @{
240 */
241/** @addtogroup ball_context
242 * @{
243 */
244
245#include <balscm_version.h>
246
247#include <ball_transmission.h>
248
249#include <bslma_allocator.h>
251
253
254#include <bsls_platform.h>
255
256#include <bsl_iosfwd.h>
257
258#ifndef BDE_OMIT_INTERNAL_DEPRECATED
259#if defined(BSLS_PLATFORM_CMP_MSVC) && defined(PASSTHROUGH)
260 // Note: on Windows -> WinGDI.h:#define PASSTHROUGH 19
261#undef PASSTHROUGH
262#endif
263#endif // BDE_OMIT_INTERNAL_DEPRECATED
264
265
266namespace ball {
267
268 // =============
269 // class Context
270 // =============
271
272/// This class provides a container for aggregating the auxiliary
273/// information needed to transmit a log record. For each context attribute
274/// in this class (e.g., `recordIndex`), there is an accessor for obtaining
275/// the attribute's value (`recordIndex`) and there are manipulators for
276/// changing the contained attribute values (`setAttributes` checks
277/// attribute constraints; `setAttributesRaw` and `setRecordIndexRaw` do
278/// not). A static `isValid` method is also provided to verify that
279/// particular attribute values are consistent before they are used to create or modify a context object.
280///
281/// \note Note that it is the client's
282/// responsibility not to construct or unilaterally modify a context object
283/// to hold incompatible attribute values.
284///
285/// Additionally, this class supports a complete set of *value* *semantic*
286/// operations, including copy construction, assignment and equality
287/// comparison, and `ostream` printing. A precise operational definition of
288/// when two instances have the same value can be found in the description
289/// of `operator==` for the class. This class is *exception* *neutral* with
290/// no guarantee of rollback: if an exception is thrown during the
291/// invocation of a method on a pre-existing instance, the object is left in
292/// a valid state, but its value is undefined. In no event is memory
293/// leaked. Finally, *aliasing* (e.g., using all or part of an object as
294/// both source and destination) is supported in all cases.
295///
296/// See @ref ball_context
297class Context {
298
299 // DATA
300 Transmission::Cause d_transmissionCause; // cause of transmitted record
301 int d_recordIndex; // 0-based index within sequence
302 int d_sequenceLength; // number of records in sequence
303
304 // PRIVATE TYPES
305 enum { k_SUCCESS = 0, k_FAILURE = -1 };
306
307 // FRIENDS
308 friend bool operator==(const Context&, const Context&);
309
310 public:
311 // TRAITS
313
314 // CLASS METHODS
315
316 /// Return `true` if the specified `transmissionCause`, `recordIndex`,
317 /// and `sequenceLength` represent a valid context, and `false`
318 /// otherwise. (See the CONSTRAINTS section of the component-level
319 /// documentation above for a complete specification of the constraints
320 /// on attribute values.)
322 int recordIndex,
323 int sequenceLength);
324
325 // CREATORS
326
327 /// Create a context object with all attributes having default values.
328 /// Optionally specify a `basicAllocator` used to supply memory. If
329 /// `basicAllocator` is 0, the currently installed default allocator is used.
330 ///
331 /// \note Note that `basicAllocator` is currently ignored.
332 Context(bslma::Allocator *basicAllocator = 0);
333
334 /// Create a context object indicating the specified
335 /// `transmissionCause`, `recordIndex`, and `sequenceLength` values.
336 /// Optionally specify a `basicAllocator` used to supply memory. If
337 /// `basicAllocator` is 0, the currently installed default allocator is used.
338 ///
339 /// \pre The behavior is undefined unless the resulting attribute values are compatible.
340 ///
341 /// \note Note that `basicAllocator` is currently
342 /// ignored.
344 int recordIndex,
345 int sequenceLength,
346 bslma::Allocator *basicAllocator = 0);
347
348 /// Create a context object having the value of the specified `original`
349 /// context object. Optionally specify a `basicAllocator` used to
350 /// supply memory. If `basicAllocator` is 0, the currently installed default allocator is used.
351 ///
352 /// \note Note that `basicAllocator` is currently
353 /// ignored.
354 Context(const Context& original, bslma::Allocator *basicAllocator = 0);
355
356 /// Destroy this object.
357 ~Context() = default;
358
359 // MANIPULATORS
360
361 /// Assign to this context object the value of the specified `rhs` context
362 /// object.
363 Context& operator=(const Context& rhs);
364
365 /// Set the value of this context object to the specified
366 /// `transmissionCause`, `recordIndex`, and `sequenceLength` values if
367 /// `transmissionCause`, `recordIndex`, and `sequenceLength` represent a
368 /// valid context. Return 0 on success, and a non-zero value (with no
369 /// effect on this context object) otherwise.
371 int recordIndex,
372 int sequenceLength);
373
374 /// Set the value of this context object to the specified
375 /// `transmissionCause`, `recordIndex`, and `sequenceLength` values.
376 ///
377 /// \pre The behavior is undefined if the resulting attribute values are
378 /// incompatible.
380 int recordIndex,
381 int sequenceLength);
382
383 /// Set the record index attribute of this context object to the specified `index`.
384 ///
385 /// \pre The behavior is undefined if the resulting attribute values
386 /// are incompatible.
387 void setRecordIndexRaw(int index);
388
389 // ACCESSORS
390
391 /// Return the transmission cause attribute of this context object.
393
394 /// Return the record index attribute of this context object.
395 int recordIndex() const;
396
397 /// Return the sequence length attribute of this context object.
398 int sequenceLength() const;
399
400 /// Format this object to the specified output `stream` at the
401 /// optionally specified indentation `level` and return a reference to
402 /// the modifiable `stream`. If `level` is specified, optionally
403 /// specify `spacesPerLevel`, the number of spaces per indentation level
404 /// for this and all of its nested objects. Each line is indented by
405 /// the absolute value of `level * spacesPerLevel`. If `level` is
406 /// negative, suppress indentation of the first line. If
407 /// `spacesPerLevel` is negative, suppress line breaks and format the
408 /// entire output on one line. If `stream` is initially invalid, this
409 /// operation has no effect.
410 bsl::ostream& print(bsl::ostream& stream,
411 int level = 0,
412 int spacesPerLevel = 4) const;
413};
414
415// FREE OPERATORS
416
417/// Return `true` if the specified `lhs` and `rhs` context objects have the
418/// same value, and `false` otherwise. Two context objects have the same
419/// value if each respective pair of corresponding attributes have the same
420/// value.
421bool operator==(const Context& lhs, const Context& rhs);
422
423/// Return `true` if the specified `lhs` and `rhs` context objects do not
424/// have the same value, and `false` otherwise. Two context objects do not
425/// have the same value if one or more respective attributes differ in
426/// value.
427bool operator!=(const Context& lhs, const Context& rhs);
428
429/// Write the specified `rhs` context to the specified output `stream` and
430/// return a reference to the modifiable `stream`.
431bsl::ostream& operator<<(bsl::ostream& stream, const Context& rhs);
432
433// ============================================================================
434// INLINE DEFINITIONS
435// ============================================================================
436
437 // -------------
438 // class Context
439 // -------------
440
441// CREATORS
442inline
444: d_transmissionCause(Transmission::e_PASSTHROUGH)
445, d_recordIndex(0)
446, d_sequenceLength(1)
447{
448}
449
450inline
452 int recordIndex,
453 int sequenceLength,
455: d_transmissionCause(transmissionCause)
456, d_recordIndex(recordIndex)
457, d_sequenceLength(sequenceLength)
458{
459}
460
461inline
463: d_transmissionCause(original.d_transmissionCause)
464, d_recordIndex(original.d_recordIndex)
465, d_sequenceLength(original.d_sequenceLength)
466{
467}
468
469// MANIPULATORS
470inline
472{
473 d_transmissionCause = rhs.d_transmissionCause;
474 d_recordIndex = rhs.d_recordIndex;
475 d_sequenceLength = rhs.d_sequenceLength;
476 return *this;
477}
478
479inline
481 int recordIndex,
482 int sequenceLength)
483{
484 d_transmissionCause = transmissionCause;
485 d_recordIndex = recordIndex;
486 d_sequenceLength = sequenceLength;
487}
488
489inline
491 int recordIndex,
492 int sequenceLength)
493{
496 return k_SUCCESS; // RETURN
497 }
498 return k_FAILURE;
499}
500
501inline
503{
504 d_recordIndex = index;
505}
506
507// ACCESSORS
508inline
510{
511 return d_transmissionCause;
512}
513
514inline
516{
517 return d_recordIndex;
518}
519
520inline
522{
523 return d_sequenceLength;
524}
525
526} // close package namespace
527
528// FREE OPERATORS
529inline
530bool ball::operator==(const Context& lhs, const Context& rhs)
531{
532 return lhs.d_transmissionCause == rhs.d_transmissionCause
533 && lhs.d_recordIndex == rhs.d_recordIndex
534 && lhs.d_sequenceLength == rhs.d_sequenceLength;
535}
536
537inline
538bool ball::operator!=(const Context& lhs, const Context& rhs)
539{
540 return !(lhs == rhs);
541}
542
543inline
544bsl::ostream& ball::operator<<(bsl::ostream& stream, const Context& rhs)
545{
546 return rhs.print(stream, 0, -1);
547}
548
549
550
551#endif
552
553// ----------------------------------------------------------------------------
554// Copyright 2015 Bloomberg Finance L.P.
555//
556// Licensed under the Apache License, Version 2.0 (the "License");
557// you may not use this file except in compliance with the License.
558// You may obtain a copy of the License at
559//
560// http://www.apache.org/licenses/LICENSE-2.0
561//
562// Unless required by applicable law or agreed to in writing, software
563// distributed under the License is distributed on an "AS IS" BASIS,
564// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
565// See the License for the specific language governing permissions and
566// limitations under the License.
567// ----------------------------- END-OF-FILE ----------------------------------
568
569/** @} */
570/** @} */
571/** @} */
Definition ball_context.h:297
Context & operator=(const Context &rhs)
Definition ball_context.h:471
BSLMF_NESTED_TRAIT_DECLARATION(Context, bslma::UsesBslmaAllocator)
Transmission::Cause transmissionCause() const
Return the transmission cause attribute of this context object.
Definition ball_context.h:509
int recordIndex() const
Return the record index attribute of this context object.
Definition ball_context.h:515
bsl::ostream & print(bsl::ostream &stream, int level=0, int spacesPerLevel=4) const
int sequenceLength() const
Return the sequence length attribute of this context object.
Definition ball_context.h:521
void setAttributesRaw(Transmission::Cause transmissionCause, int recordIndex, int sequenceLength)
Definition ball_context.h:480
~Context()=default
Destroy this object.
Context(bslma::Allocator *basicAllocator=0)
Definition ball_context.h:443
friend bool operator==(const Context &, const Context &)
int setAttributes(Transmission::Cause transmissionCause, int recordIndex, int sequenceLength)
Definition ball_context.h:490
void setRecordIndexRaw(int index)
Definition ball_context.h:502
static bool isValid(Transmission::Cause transmissionCause, int recordIndex, int sequenceLength)
Definition bslma_allocator.h:545
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
Definition ball_administration.h:214
bsl::ostream & operator<<(bsl::ostream &output, const Attribute &attribute)
bool operator!=(const Attribute &lhs, const Attribute &rhs)
bool operator==(const Attribute &lhs, const Attribute &rhs)
ALLOCATOR const STRING_VIEW_LIKE_TYPE & rhs
Definition bslstl_string.h:3918
ALLOCATOR & lhs
Definition bslstl_string.h:3917
Definition ball_transmission.h:210
Cause
Definition ball_transmission.h:215
Definition bslma_usesbslmaallocator.h:344