ALib C++ Framework
by
Library Version: 2511 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
loxpimpl.cpp
Go to the documentation of this file.
1//##################################################################################################
2// ALib C++ Framework
3//
4// Copyright 2013-2025 A-Worx GmbH, Germany
5// Published under 'Boost Software License' (a free software license, see LICENSE.txt)
6//##################################################################################################
7/// \file
8#include "alib_precompile.hpp"
9#if !defined(ALIB_C20_MODULES) || ((ALIB_C20_MODULES != 0) && (ALIB_C20_MODULES != 1))
10# error "Configuration MACRO ALIB_C20_MODULES has to be given to the compiler as either 0 or 1"
11#endif
12#if ALIB_C20_MODULES
13 module;
14#endif
15//========================================= Global Fragment ========================================
20//============================================== Module ============================================
21#if ALIB_C20_MODULES
22 module ALib.ALox.Impl;
23 import ALib.ALox;
24 import ALib.Lang;
25 import ALib.EnumOps;
26 import ALib.Strings;
27 import ALib.Strings.Tokenizer;
28 import ALib.Boxing;
29 import ALib.EnumRecords;
30 import ALib.EnumRecords.Bootstrap;
31 import ALib.Variables;
32 import ALib.Camp;
33 import ALib.Camp.Base;
34 import ALib.Bootstrap;
35#else
36# include "ALib.Bootstrap.H"
37# include "ALib.Lang.H"
38# include "ALib.Strings.H"
40# include "ALib.Boxing.H"
42# include "ALib.Variables.H"
43# include "ALib.Camp.H"
44# include "ALib.Camp.Base.H"
45# include "ALib.ALox.H"
46# include "ALib.ALox.Impl.H"
47#endif
48//========================================== Implementation ========================================
49#if !DOXYGEN
50#if !ALIB_SINGLE_THREADED
51# define UNDEFINED_THREAD threads::UNDEFINED
52#else
53# define UNDEFINED_THREAD 0
54#endif
55
57 ALIB_COMMA alib::variables::Priority>, vt_lox_pair_verby_prio )
58
60#endif
61
63
64namespace alib { namespace lox { namespace detail {
65
66/// Domain substitution rules.
68 /// Rule types.
69 public:
70 enum class Type {
71 Exact, ///< Exact match.
72 StartsWith, ///< Starts with match.
73 EndsWith, ///< Ends with match.
74 Substring ///< Any substring.
75 };
76
77 Type type; ///< Denotes the type of the rule, depending of what
78 ///< was set in originally as search path
79 NString32 Search; ///< The path to search.
80 NString32 Replacement; ///< The replacement.
81
82 /// Constructor.
83 /// @param s The path to search.
84 /// @param r The replacement.
85 DomainSubstitutionRule( const NString& s, const NString& r ) {
86 Search .DbgDisableBufferReplacementWarning();
87 Replacement.DbgDisableBufferReplacementWarning();
88
89 // get type and adjust given search parameter
90 integer startPos= 0;
91 integer length= s.Length();
92 if ( s.CharAtStart() == '*' ) {
93 ++startPos;
94 --length;
95 if ( s.CharAtEnd() == '*' ) {
97 --length;
98 }
99 else
101 } else {
102 if ( s.CharAtEnd() == '*' ) {
104 --length;
105 }
106 else
108 }
109 Search._( s, startPos, length );
110
111 // minimum rule check
112 if ( ( ( type == Type::Exact
113 || type == Type::StartsWith )
114 && Search.CharAtStart() != '/'
115 )
116 || ( type == Type::EndsWith
117 && Search.CharAtEnd() == '/'
118 )
119 )
120 Search.Reset(); // illegal rule
121
122
123 Replacement= r;
124 }
125}; // struct DomainSubstitutionRule
126
127
128//==================================================================================================
129/// Implementation struct for class #"Lox" following the
130/// \https{Pimpl Idiom,en.cppreference.com/w/cpp/language/pimpl}.
131//==================================================================================================
132struct LoxImpl {
133 /// The self-contained monotonic allocator, that also contains this struct itself.
135
136 /// A pool allocator that uses #"monoAllocator" as its source.
138
139 /// Snapshot taken before embedding the lox in the #"monoAllocator".
141
142 #if !ALIB_SINGLE_THREADED
143 /// A mutex to control parallel access.
145 #endif
146
147 /// Counts the number of nested (recursive) acquirements.
149
150 /// A counter for the quantity of calls. The count includes logs suppressed by
151 /// disabled <em>Log Domain</em> and those suppressed by the optional log condition parameter.
153
154 /// A list of a list of logables used for (recursive) logging.
156
157 /// A list of a list of logables used for (recursive) internal logging.
159
160 /// The recursion counter for internal logging.
162
163 /// Information about the source code, method, thread, etc. invoking a log call
165
166 /// The root domain \"/\". All registered domains become a sub domain of this root.
167 /// If a <em>Sub-Log Domain's Verbosity</em> is not explicitly set, such sub domain inherits
168 /// the verbosity of its parent.
170
171 /// The root domain for internal <em>Log Domains</em>.
173
174 /// Scope Domains
176
177 /// Prefix logables store
179
180 /// Log once counters
182
183 /// Log data store
185
186 /// Used for tabular output of logger lists
188
189 /// Used for tabular output of logger lists
191
192 /// A key value used in stores if no key is given (global object).
194
195
196 /// The list of domain substitution rules.
198
199 /// Flag if a warning on circular rule detection was logged.
201
202 /// Flag used with configuration variable LOXNAME_DUMP_STATE_ON_EXIT.
204
205 /// Constructor.
206 /// @param ma The externally created, self-contained monotonic allocator, that also contains
207 /// this instance.
208 /// @param name The lox's name.
225
226 /// Destructor.
228 // unregister each logger in std domains and remove it in internals
229 for ( int i= domains->CountLoggers() - 1 ; i >= 0 ; --i ) {
230 Logger* logger= domains->GetLogger( i );
231 int ii= internalDomains->GetLoggerNo( logger );
232 if ( ii >= 0 )
233 internalDomains->RemoveLogger( ii );
235 }
236
237 // unregister remaining loggers in internal domains
238 for ( int i= internalDomains->CountLoggers() - 1 ; i >= 0 ; --i ) {
239 Logger* logger= internalDomains->GetLogger( i );
241 } }
242
243 /// Returns the number of (recursive) acquirements of this \b Lox.
244 /// If greater than \c 1, this is either recursive logging or a user has explicitly
245 /// acquired this lox repeatedly (which is not recommended to do).
246 ///
247 /// @return The number of acquirements.
248 int CountAcquirements() const noexcept { return AcquirementsCount; }
249
250 /// Shortcut to allocate arbitrary objects in #"poolAllocator".
251 /// @tparam T The type to allocate.
252 /// @tparam TArgs Types of variadic parameters given with parameter \p{args}.
253 /// Deduced by the compiler.
254 /// @param args Variadic parameters to be forwarded to the constructor of type \p{T}.
255 /// @return The allocated object.
256 template<typename T, typename... TArgs>
257 T* newPO(TArgs&&... args) { return poolAllocator().New<T>(std::forward<TArgs>(args)...); }
258
259 /// Shortcut to delete arbitrary objects in #poolAllocator.
260 /// @tparam T The type to allocate. Deduced by the compiler.
261 /// @param o The allocated object.
262 template<typename T>
263 void deletePO(T* o) { poolAllocator().Delete<T>(o); }
264
265}; // struct LoxImpl
266
267#if !DOXYGEN
268#define ASSERT_ACQUIRED ALIB_ASSERT_ERROR( impl->CountAcquirements() >0,"ALOX","Lox not acquired" )
269#endif
270
271//##################################################################################################
272// Constructors/destructor
273//##################################################################################################
276 MonoAllocator* selfContainedMA= MonoAllocator::Create( ALIB_DBG(nullptr,) ha, 8* 1024 );
277 ALIB_DBG( selfContainedMA->DbgName= NCString(*selfContainedMA, NString128("Lox") << name).Buffer(); )
278 auto snapShot= selfContainedMA->TakeSnapshot();
279 LoxImpl* result= (*selfContainedMA)().New<LoxImpl>( selfContainedMA, name );
280 result->beforeLox= snapShot;
281 return result;
282}
283
284void LI::Destruct( LoxImpl* impl ) {
285 auto& ma= impl->monoAllocator;
286 impl->~LoxImpl();
287 lang::Destruct(ma); // just destruct, as this is self-contained
288}
289
290const NString& LI::GetName(LoxImpl* impl) { return impl->scopeInfo.loxName; }
291
293
294#if !ALIB_SINGLE_THREADED
296{
298 return impl->Lock;
299}
300#endif
301
302void LI::Acquire(LoxImpl* impl, const lang::CallerInfo& ci ) {
303 #if !ALIB_SINGLE_THREADED
305 , impl->Lock.AcquireRecursive(ci); )
306 #else
308 #endif
309 ++impl->AcquirementsCount;
310 impl->scopeInfo.Set( ci );
311}
312
313void LI::Release(LoxImpl* impl) {
315 --impl->AcquirementsCount;
316 #if !ALIB_SINGLE_THREADED
318 #endif
319}
320
321void LI::init(LoxImpl* impl) {
322 impl->logableContainers.reserve(5); // 5 equals the recursive logging warning threshold
323
324 // create domain trees
325 impl->domains = impl->monoAllocator().New<Domain>(impl->monoAllocator, impl->poolAllocator, "" );
326 impl->internalDomains= impl->monoAllocator().New<Domain>(impl->monoAllocator, impl->poolAllocator, "$" );
327
328 // create internal Subdomains
329 const NString internalDomainList[]= {"LGR","DMN", "PFX", "THR", "LGD", "VAR" };
330 for ( auto& it : internalDomainList )
331 impl->internalDomains->Find( it, 1, nullptr );
332 impl->maxDomainPathLength= Lox::InternalDomains.Length() + 3;
333
334 // read domain substitution rules from configuration
336 {
337 ALIB_LOCK_WITH(ALOX.GetConfig())
340 GetName(impl)
341 #else
342 String128( GetName( impl ) )
343 #endif
344 );
345 }
346 if ( var.IsDefined() ) {
347 for( int ruleNo= 0 ; ruleNo < var.Size() ; ++ruleNo ) {
348 Substring rule= var.GetString(ruleNo);
349 if( rule.Trim().IsEmpty() )
350 continue;
351
352 integer idx= rule.IndexOf( A_CHAR("->") );
353 if ( idx > 0 ) {
354 NString256 domainPath ( rule.Substring<NC>( 0, idx ) ); domainPath .Trim();
355 NString256 replacement( rule.Substring<NC>( idx + 2, rule.Length() - idx - 2 ) ); replacement.Trim();
356 SetDomainSubstitutionRule( impl, domainPath, replacement );
357 } else {
358 // using alib warning here as we can't do internal logging in the constructor
359 ALIB_WARNING( "ALOX", "Syntax error in variable \"{}\".", var )
360 } } }
361
362}
363
364void LI::Reset(LoxImpl* impl) {
365 #if ALOX_DBG_LOG
366 if( impl == Log::Get()->impl && Log::DEBUG_LOGGER != nullptr ) {
370 }
371 #endif
372
374 999999, // code for clearing
376
377 // clear the monotonic allocator and rebuild the impl
378 MonoAllocator* loxMA = &impl->monoAllocator;
379 auto snapshot = impl->beforeLox;
380 NString128 name( impl->scopeInfo.loxName);
381 (*loxMA)().Delete(impl);
382 loxMA->Reset(snapshot);
383 ALIB_DBG( auto* dbgNewAddress= )
384 (*loxMA)().New<LoxImpl>(loxMA, name ); // creates the impl at the same position, therefore, it does not need
385 // to be stored (and passed back)
386 ALIB_ASSERT_ERROR( impl == dbgNewAddress, "ALOX", "Internal error. This must never happen." )
387 impl->beforeLox= snapshot;
388}
389
390void LI::SetFileNameCacheCapacity( LoxImpl* impl, integer numberOfLists, integer entriesPerList )
391{ impl->scopeInfo.SetFileNameCacheCapacity( numberOfLists, entriesPerList ); }
392
393#if ALIB_DEBUG_MEMORY
395#endif
396
398 const NCString& path,
399 lang::Inclusion includeString ,
400 int trimOffset ,
401 lang::Case sensitivity ,
402 const NString& trimReplacement,
403 lang::Reach reach ,
404 Priority priority )
405{
406 impl->scopeInfo.SetSourcePathTrimRule( path, includeString, trimOffset, sensitivity,
407 trimReplacement, reach, priority );
408}
409
410void LI::SetDomain( LoxImpl* impl , const NString& scopeDomain,
411 Scope scope, threads::Thread* thread ) {
412 if ( !isThreadRelatedScope( impl, scope ) )
413 return;
414 setDomain( impl, scopeDomain, scope, false, thread );
415}
416
417//##################################################################################################
418// Methods
419//##################################################################################################
420Logger* LI::GetLogger(LoxImpl* impl, const NString& loggerName ) {
421 ASSERT_ACQUIRED
422
423 // search logger
424 Logger* logger;
425 if ( (logger= impl->domains ->GetLogger( loggerName ) ) != nullptr ) return logger;
426 if ( (logger= impl->internalDomains->GetLogger( loggerName ) ) != nullptr ) return logger;
427
428 // not found
429 BoxesMA& logables= acquireInternalLogables(impl);
430 logables.Add( "No logger named {!Q} found.", loggerName );
431 logInternal( impl, Verbosity::Warning, "LGR", logables );
432 return nullptr;
433}
434
435//! @cond NO_DOX
436namespace {
437void writeVerbVarRecursive( Domain& domain, int loggerNo, CVVerbosities& verbosities,
438 Verbosity parentVerbosity ) {
439 auto verbosity= domain.GetVerbosity( loggerNo );
440 if( parentVerbosity != verbosity || verbosities.ExportAll )
441 verbosities.Add(String256(domain.FullPath) << '=' << verbosity );
442
443 // loop over all subdomains (recursion)
444 for ( Domain& subDomain : domain.SubDomains )
445 writeVerbVarRecursive( subDomain, loggerNo, verbosities, verbosity );
446}
447} // anonymous namespace
448//! @endcond
449
451DOX_MARKER([DOX_VARIABLES_REPLACEMENTS2])
453{ALIB_LOCK_WITH(ALOX.GetConfig())
454 // a local array of boxes of size two, to fill variable placeholders
455 Box replacements[2]=
456 {
457 GetName( impl ), // name of this Lox
458 logger->GetName() // name of the Logger
459 };
460
461 // declare the individually named variable
462 var.Declare( Variables::VERBOSITY, replacements );
463}
464DOX_MARKER( [DOX_VARIABLES_REPLACEMENTS2])
465 // we do not care about the writing rights.
466 (void) var.Define();
467 auto& cvVerb= var.Get<CVVerbosities>();
468 cvVerb.Clear();
469
470 // collect verbosities
471 {
472 int loggerNoMainDom= impl->domains ->GetLoggerNo( logger );
473 int loggerNoIntDom= impl->internalDomains->GetLoggerNo( logger );
474
475 if ( loggerNoMainDom >= 0 ) writeVerbVarRecursive( *impl->domains , loggerNoMainDom, cvVerb, Verbosity(-1) );
476 if ( loggerNoIntDom >= 0 ) writeVerbVarRecursive( *impl->internalDomains, loggerNoIntDom , cvVerb, Verbosity(-1) );
477 }
478
479 // internal logging
480 {
481 // get variable name. Needs shared acquisition
482 String256 varName;
483 { ALIB_LOCK_SHARED_WITH(ALOX.GetConfig())
484 varName << var; // this is needed because we are logging the name of a variable!
485 }
486 BoxesMA& logables= acquireInternalLogables(impl);
487 logables.Add( "Verbosities for logger {!Q} written to variable {!Q}",
488 logger->GetName(), varName );
489 logInternal( impl, Verbosity::Info, "VAR", logables );
490 }
491
492 // verbose logging of the value written
493 {
494 BoxesMA& logables= acquireInternalLogables(impl);
495 logables.Add(" Value:");
496 for( auto& it : cvVerb )
497 logables.Add( "\n ", it );
498 logInternal( impl, Verbosity::Verbose, "VAR", logables );
499} }
500
503 return;
505
508 GetName( impl )
509 #else
510 String128( GetName( impl ) )
511 #endif
512 );
513 if( !variable.IsDefined() )
514 return;
515 NString64 domain;
516 Verbosity verbosity= Verbosity::Info;
517 Substring tok;
518 bool error= false;
520 Tokenizer tknzr;
521 tknzr.Set(variable, ',', true);
522 while( tknzr.HasNext() ) {
523 tok= tknzr.Next();
524
525 // read log domain and verbosity
526 if( tok.IndexOf( '=' ) > 0 ) {
527 if( tok.ConsumePartOf<lang::Case::Ignore, lang::Whitespaces::Trim>( A_CHAR("verbosity"), 1) ) {
529 enumrecords::Parse<Verbosity>( tok, verbosity );
530 continue;
531 }
534 domain= tok.Trim();
535 continue;
536 }
537 error= true;
538 break;
539 }
540
541 // read and add state
542 StateInfo stateInfo;
543 if( !enumrecords::Parse<StateInfo>( tok, stateInfo ) ) {
544 error= true;
545 break;
546 }
547
548 // None clears all, others are added
549 if( stateInfo == StateInfo::NONE )
550 flags= StateInfo::NONE;
551 else
552 flags|= stateInfo;
553 }
554 if( error ) {
555 BoxesMA& logables= acquireInternalLogables(impl);
556 logables.Add( "Unknown argument {!Q} in variable {} = {!Q}.",
557 tok, variable, variable.GetString() );
558 logInternal( impl, Verbosity::Error, "VAR", logables);
559 }
560
561 if ( flags != StateInfo::NONE ) {
562 State( impl, domain, verbosity, A_CHAR("Auto dump state on exit requested: "), flags );
563} }
564
565
566bool LI::RemoveLogger( LoxImpl* impl, Logger* logger ) {
567 ASSERT_ACQUIRED
568
569 int noMainDom= impl->domains ->GetLoggerNo( logger );
570 int noIntDom= impl->internalDomains->GetLoggerNo( logger );
571
572 if( noMainDom >= 0 || noIntDom >= 0 ) {
574 writeVerbositiesOnLoggerRemoval( impl, logger );
575
576 if( noMainDom >= 0 )
577 impl->domains->RemoveLogger( noMainDom );
578
579 if( noIntDom >= 0 )
580 impl->internalDomains->RemoveLogger( noIntDom );
581
583
584 return true;
585 }
586
587 // not found
588 BoxesMA& logables= acquireInternalLogables(impl);
589 logables.Add( "Logger {!Q} not found. Nothing removed.", logger );
590 logInternal( impl, Verbosity::Warning, "LGR", logables );
591 return false;
592}
593
594Logger* LI::RemoveLogger(LoxImpl* impl, const NString& loggerName ) {
595 ASSERT_ACQUIRED
596
597 int noMainDom= impl->domains ->GetLoggerNo( loggerName );
598 int noIntDom= impl->internalDomains->GetLoggerNo( loggerName );
599
600 if( noMainDom >= 0 || noIntDom >= 0 ) {
601 Logger* logger= impl->domains->GetLogger( noMainDom );
602 if( logger == nullptr ) logger= impl->internalDomains->GetLogger( noIntDom );
603
605 writeVerbositiesOnLoggerRemoval( impl, logger );
606
607 if( noMainDom >= 0 )
608 impl->domains->RemoveLogger( noMainDom );
609
610 if( noIntDom >= 0 )
611 impl->internalDomains->RemoveLogger( noIntDom );
612
614
615 BoxesMA& logables= acquireInternalLogables(impl);
616 logables.Add( "Logger {!Q} removed.", logger );
617 logInternal( impl, Verbosity::Info, "LGR", logables );
618 return logger;
619 }
620
621 // not found
622 BoxesMA& logables= acquireInternalLogables(impl);
623 logables.Add( "Logger {!Q} not found. Nothing removed.", loggerName );
624 logInternal( impl, Verbosity::Warning, "LGR", logables );
625
626 return nullptr;
627}
628
629void LI::SetVerbosity(LoxImpl* impl, Logger* logger, Verbosity verbosity, const NString& domain, Priority priority )
630{ ASSERT_ACQUIRED
631
632 // check
633 if ( logger == nullptr ) {
634 BoxesMA& logables= acquireInternalLogables(impl);
635 logables.Add( "Given Logger is \"null\". Verbosity not set." );
636 logInternal( impl, Verbosity::Error, "LGR", logables );
637 return;
638 }
639
640 // this might create the (path of) domain(s) and set the \e Logger's verbosities like their
641 // first parent's or as given in configuration
642 Domain* dom= evaluateResultDomain( impl, domain );
643
644 // search logger, insert if not found
645 bool isNewLogger= false;
646 int no= dom->GetLoggerNo( logger );
647 if( no < 0 ) {
648 no= dom->AddLogger( logger );
649
650 // error, logger with same name already exists
651 if( no < 0 ) {
652 logInternal( impl, Verbosity::Error, "LGR", acquireInternalLogables(impl)
653 .Add( "Unable to add logger {!Q}. Logger with same name exists.", logger ) );
654
655
656 logInternal( impl, Verbosity::Verbose, "LGR",
657 acquireInternalLogables(impl).Add(
658 " Request was: SetVerbosity({!Q}, {!Q}, Verbosity::{}, {}). ",
659 logger, dom->FullPath, verbosity, priority ) );
660
661 Logger* existingLogger= dom->GetLogger( logger->GetName() );
662 logInternal( impl, Verbosity::Verbose, "LGR", acquireInternalLogables(impl)
663 .Add( " Existing Logger: {!Q}.", existingLogger ) );
664
665 return;
666 }
667
668 // We have to tell the logger that it got inserted, but only if we have not done this yet,
669 // via the 'other' root domain tree.
670 if ( ( dom->GetRoot() == impl->domains ? impl->internalDomains->GetLoggerNo( logger )
671 : impl->domains->GetLoggerNo( logger )
672 ) < 0 )
673 {
675 }
676
677 // store size of name to support tabular internal log output
678 if ( impl->maxLoggerNameLength < logger->GetName().Length() )
679 impl->maxLoggerNameLength= logger->GetName().Length();
680
681 // for internal log
682 isNewLogger= true;
683
684 // remember that a logger was set after the last removal
685 // (for variable LOXNAME_DUMP_STATE_ON_EXIT)
687 }
688
689 // get verbosities from configuration
690 if( isNewLogger ) {
691 BoxesMA& logables= acquireInternalLogables(impl);
692 logables.Add( "Logger {!Q}.", logger );
693 if( domain.StartsWith(Lox::InternalDomains) )
694 logables.Add(" added for internal log messages.");
695 else
696 logables.Add(" added.");
697 logInternal( impl, Verbosity::Info, "LGR", logables );
698
699 // we have to get all verbosities of already existing domains
700 Box replacements[2]= { GetName( impl ), logger->GetName() };
701 Variable varVerbosities= variables::CampVariable(ALOX, Variables::VERBOSITY, replacements );
702 if( varVerbosities.IsDefined() ) {
703 getAllVerbosities( impl, varVerbosities, logger, *impl->domains );
704 getAllVerbosities( impl, varVerbosities, logger, *impl->internalDomains );
705 } }
706
707 // do
708 dom->SetVerbosity( no, verbosity, priority );
709
710 BoxesMA& logables= acquireInternalLogables(impl);
711
712 logables.Add( "Logger {!Q}: {!Fill}{!Q'}{!Fill}= Verbosity::{}.",
713 logger->GetName(),
714 impl->maxLoggerNameLength - logger->GetName().Length(),
715 dom->FullPath,
716 impl->maxDomainPathLength - dom->FullPath.Length() + 1,
717 boxing::MakePair(verbosity, priority) );
718
719 Verbosity actVerbosity= dom->GetVerbosity( no );
720 if( actVerbosity != verbosity )
721 logables.Add( " Lower priority ({} < {}). Remains {}.",
722 priority, dom->GetPriority(no), actVerbosity );
723
724 logInternal( impl, Verbosity::Info, "LGR", logables );
725}
726
727void LI::SetVerbosity(LoxImpl* impl , const NString& loggerName,
728 Verbosity verbosity, const NString& domain , Priority priority ) {
729 // get logger
730 Logger* logger;
731 {
732 ASSERT_ACQUIRED
733
734 Domain* dom= evaluateResultDomain( impl, domain );
735
736 int no= dom->GetLoggerNo( loggerName );
737 if( no >= 0 )
738 logger= dom->GetLogger( no );
739 else {
740 // we have to check if the logger was added in the 'other' tree
741 Domain* otherTree= dom->GetRoot() == impl->domains ? impl->internalDomains
742 : impl->domains;
743 no= otherTree->GetLoggerNo( loggerName );
744 if ( no < 0 ) {
745 // error
746 BoxesMA& logables= acquireInternalLogables(impl);
747 logables.Add( "Logger not found. Request was: SetVerbosity({!Q}, {!Q}, Verbosity::{}, {}).",
748 loggerName, dom->FullPath, verbosity, priority );
749 logInternal( impl, Verbosity::Warning, "LGR", logables );
750 return;
751 }
752
753 logger= otherTree->GetLogger( no );
754 } }
755 // use the overloaded method
756 SetVerbosity( impl, logger, verbosity, domain, priority );
757}
758
760 const NString& scopeDomain, Scope scope,
761 bool removeNTRSD, threads::Thread* thread ) {
762 //note: the public class interface ensures that \p{removeNTRSD} (named thread related scope domain)
763 // only evaluates true for thread related scopes
764
765 ASSERT_ACQUIRED
766
767 // check
768 int pathLevel= checkScopeInformation( impl, scope, "DMN" );
769 if( pathLevel < 0 )
770 return;
771
772 #if !ALIB_SINGLE_THREADED
773 ThreadID threadID= thread != nullptr ? thread->GetID() : UNDEFINED_THREAD;
774 #else
775 threads::ThreadID threadID= UNDEFINED_THREAD;
776 (void) thread;
777 #endif
778
779 NString previousScopeDomain;
780
781 impl->scopeDomains.InitAccess( scope, pathLevel, threadID );
782 if ( removeNTRSD ) {
783 previousScopeDomain= impl->scopeDomains.Remove( scopeDomain );
784 } else {
785 if ( scopeDomain.IsNotEmpty() ) {
786 NString128 trimmable( scopeDomain );
787 previousScopeDomain= impl->scopeDomains.Store( NString(impl->poolAllocator, trimmable.Trim() ) );
788 }
789 else
790 previousScopeDomain= impl->scopeDomains.Remove( nullptr );
791 }
792
793 // log info on this
794 BoxesMA& logables= acquireInternalLogables(impl);
795 if ( !removeNTRSD && scopeDomain.IsNotEmpty() ) {
796 logables.Add("{!Q'} set as default for {}.", scopeDomain, (scope + pathLevel) );
797
798 if ( previousScopeDomain.IsNull() )
799 logInternal( impl, Verbosity::Info, "DMN", logables );
800 else {
801 if ( previousScopeDomain.Equals<NC>( scopeDomain ) ) {
802 logables.Add( "(Wasalreadyset.)");
803 logInternal( impl,Verbosity::Verbose,"DMN",logables);
804 } else {
805 logables.Add( " Replacing previous default {!Q'}.", previousScopeDomain );
806 logInternal( impl, Verbosity::Warning, "DMN", logables );
807 } }
808
809 } else {
810 if ( previousScopeDomain.IsNotNull() ) {
811 logables.Add("{!Q'} removed from {}.", previousScopeDomain, (scope + pathLevel) );
812 logInternal( impl, Verbosity::Info, "DMN", logables );
813 } else {
814 if ( removeNTRSD )
815 logables.Add("{!Q'} not found. Nothing removed for {}.", scopeDomain );
816 else
817 logables.Add("Empty Scope Domain given, nothing registered for {}.", scopeDomain);
818
819 logables.Add( scope + pathLevel);
820 logInternal( impl, Verbosity::Warning, "DMN", logables );
821 } }
822
823 // it is on us to delete the previous one
824 if ( previousScopeDomain.IsNotNull() )
825 previousScopeDomain.Free(impl->poolAllocator);
826}
827
828void LI::RemoveThreadDomain( LoxImpl* impl, const NString& scopeDomain,
829 Scope scope, threads::Thread* thread ) {
830 if ( !isThreadRelatedScope( impl, scope ) )
831 return;
832
833 // check
834 if ( scopeDomain.IsEmpty() ) {
835 BoxesMA& logables= acquireInternalLogables(impl);
836 logables.Add( "Illegal parameter. No scope domain path given. Nothing removed for {}.",
837 scope );
838 logInternal( impl, Verbosity::Warning, "DMN", logables );
839
840 // do nothing
841 return;
842 }
843
844 // invoke internal master
845 setDomain( impl, scopeDomain, scope, true, thread);
846}
847
848void LI::SetDomainSubstitutionRule(LoxImpl* impl, const NString& domainPath,
849 const NString& replacement ) {
850 // check null param: clears all rules
851 if ( domainPath.IsEmpty() ) {
852 impl->oneTimeWarningCircularDS= false;
853 impl->domainSubstitutions.Clear();
854 logInternal( impl, Verbosity::Info, "DMN", "Domain substitution rules removed.");
855 return;
856 }
857
858
859 // create rule
860 DomainSubstitutionRule newRule( domainPath, replacement );
861 if ( newRule.Search.IsEmpty() ) {
862 logInternal( impl, Verbosity::Warning, "DMN", "Illegal domain substitution rule. Nothing stored." );
863 return;
864 }
865
866 // search existing rule
868 for( it= impl->domainSubstitutions.begin(); it != impl->domainSubstitutions.end() ; ++it ) {
869 if ( (*it).type == newRule.type
870 && (*it).Search.Equals<NC>( newRule.Search ) )
871 break;
872 }
873
874 // no replacement given?
875 if ( replacement.IsEmpty() ) {
876 BoxesMA& logables= acquireInternalLogables(impl);
877 if ( it == impl->domainSubstitutions.end() ) {
878 logables.Add("Domain substitution rule {!Q} not found. Nothing to remove.", domainPath );
879 logInternal( impl, Verbosity::Warning, "DMN", logables );
880 return;
881 }
882
883 logables.Add("Domain substitution rule {!Q} -> {!Q} removed.", domainPath, (*it).Replacement );
884 logInternal( impl, Verbosity::Info, "DMN", logables );
885 (void) impl->domainSubstitutions.erase( it );
886 return;
887 }
888
889 BoxesMA& logables= acquireInternalLogables(impl);
890 logables.Add("Domain substitution rule {!Q} -> {!Q} set.", domainPath, newRule.Replacement );
891
892 // change of rule
893 NString256 msg;
894 if ( it != impl->domainSubstitutions.end() ) {
895 msg << " Replacing previous -> \"" << (*it).Replacement << "\".";
896 logables.Add( msg );
897 (*it).Replacement.Reset( newRule.Replacement );
898 }
899 else
900 impl->domainSubstitutions.emplace_back( newRule );
901
902 if( ALOX.IsBootstrapped() ) // this function might be called very early.
903 logInternal( impl, Verbosity::Info, "DMN", logables );
904}
905
906void LI::setPrefix(LoxImpl* impl, const Box& prefix, Scope scope, threads::Thread* thread ) {
907 ASSERT_ACQUIRED
908
909 // check
910 int pathLevel= checkScopeInformation( impl, scope, "PFX" );
911 if( pathLevel < 0 )
912 return;
913
914 #if !ALIB_SINGLE_THREADED
915 ThreadID threadID= thread != nullptr ? thread->GetID() : UNDEFINED_THREAD;
916 #else
917 threads::ThreadID threadID= UNDEFINED_THREAD;
918 (void) thread;
919 #endif
920
921 impl->scopePrefixes.InitAccess( scope, pathLevel, threadID );
922 bool isVoidOrEmpty= prefix.IsType<void>()
923 || prefix.IsNull()
924 || ( prefix.IsArray() && !prefix.UnboxLength() );
925
926 Box* previousLogable= !isVoidOrEmpty ? impl->scopePrefixes.Store( impl->newPO<PrefixLogable>( impl->poolAllocator, prefix ) )
927 : impl->scopePrefixes.Remove( nullptr );
928
929
930 BoxesMA& logables= acquireInternalLogables(impl);
931 logables.Add( "Object ");
932 Verbosity intMsgVerbosity= Verbosity::Info;
933 if ( !isVoidOrEmpty ) {
934 logables.Add( prefix, " added as prefix logable for {}.", (scope + pathLevel) );
935
936 if ( previousLogable != nullptr ) {
937 if ( previousLogable->Call<FEquals>( prefix ) ) {
938 logables.Add(" (Same as before.)");
939 intMsgVerbosity= Verbosity::Verbose;
940 }
941 else
942 logables.Add(" Replacing previous {}.", *previousLogable );
943 }
944 } else {
945 if ( previousLogable != nullptr )
946 logables.Add( "{!Q} removed from list of prefix logables for {}.", *previousLogable);
947 else {
948 logables.Add( "<nullptr> given but no prefix logable to remove for {}.");
949 intMsgVerbosity= Verbosity::Warning;
950 }
951 logables.Add( scope + pathLevel );
952 }
953
954 logInternal( impl, intMsgVerbosity, "PFX", logables );
955
956 // it is on us to delete the previous one
957 if ( previousLogable != nullptr )
958 impl->deletePO(static_cast<PrefixLogable*>( previousLogable ));
959}
960
961
962void LI::SetPrefix( LoxImpl* impl , const Box& prefix,
963 const NString& domain, lang::Inclusion otherPLs ) {
964
965 ASSERT_ACQUIRED
966
967 Domain* dom= evaluateResultDomain( impl, domain );
968
969 bool isVoidOrEmpty= prefix.IsType<void>()
970 || prefix.IsNull()
971 || ( prefix.IsArray() && !prefix.UnboxLength() );
972
973 BoxesMA& logables= acquireInternalLogables(impl);
974 Verbosity intLogVerbosity= Verbosity::Info;
975 PrefixLogable* removedLogable= nullptr;
976
977 if ( !isVoidOrEmpty ) {
978 // create logable: if String* type, then copy the string. We are responsible, then.
979 logables.Add( "Object {} added as prefix logable for ", prefix );
980
981 dom->PrefixLogables.emplace_back( impl->newPO<PrefixLogable>( impl->poolAllocator, prefix ), otherPLs );
982 } else {
983 auto cntPLs= dom->PrefixLogables.size();
984 if ( cntPLs > 0 ) {
985 removedLogable= dom->PrefixLogables.back().first;
986 dom->PrefixLogables.pop_back();
987 logables.Add( "Object {} removed from list of prefix logables for",
988 *static_cast<Box*>(removedLogable) );
989 } else {
990 logables.Add( "No prefix logables to remove for" );
991 intLogVerbosity= Verbosity::Warning;
992 } }
993
994 logables.Add(" domain {!Q'}.", dom->FullPath);
995 logInternal( impl, intLogVerbosity, "PFX", logables );
996
997 if( removedLogable )
998 impl->deletePO(removedLogable);
999}
1000
1001
1002#if defined (__GLIBCXX__) || defined(_LIBCPP_VERSION) || defined(__APPLE__) || defined(__ANDROID_NDK__)
1003void LI::SetStartTime(LoxImpl* impl, time_t startTime, const NString& loggerName )
1004{
1005 TickConverter converter;
1006 SetStartTime( impl, converter.ToTicks( DateTime::FromEpochSeconds( startTime ) ), loggerName );
1007}
1008
1009#elif defined( _WIN32 )
1010 void LI::SetStartTime(LoxImpl* impl, const FILETIME& startTime, const NString& loggerName )
1011 {
1012 TickConverter converter;
1013 SetStartTime( impl, converter.ToTicks( DateTime::FromFileTime( startTime ) ), loggerName );
1014 }
1015#else
1016 #pragma message "Unknown Platform in file: " __FILE__ )
1017#endif
1018
1019void LI::SetStartTime(LoxImpl* impl, Ticks startTime, const NString& loggerName ) {
1020 ASSERT_ACQUIRED
1021
1022 bool foundOne= false;
1023 for( int loggerNo= 0; loggerNo < impl->domains->CountLoggers(); ++loggerNo ) {
1024 // request logger only from main domain tree
1025 Logger* logger= impl->domains->GetLogger( loggerNo );
1026 if( loggerName.IsNotEmpty() && !loggerName.Equals<NC, lang::Case::Ignore>( logger->GetName()) )
1027 continue;
1028 foundOne= true;
1029
1030 // log info on this
1031 BoxesMA& logables= acquireInternalLogables(impl);
1032 logables.Add( "Logger {!Q}: Start time set to ", logger->GetName() );
1033 if ( !startTime.IsSet() ) {
1034 startTime= Ticks::Now();
1035 logables.Add( "'now'" );
1036 } else {
1037 DateTime asDateTime;
1038 TextLogger* asTextLogger= dynamic_cast<TextLogger*>(logger);
1039 if( asTextLogger != nullptr )
1040 asDateTime= asTextLogger->DateConverter.ToDateTime( startTime );
1041 else
1042 asDateTime= TickConverter().ToDateTime( startTime );
1043 logables.Add( "{:yyyy-MM-dd HH:mm:ss}", asDateTime );
1044 }
1045 // do
1046 logger->TimeOfCreation.SetAs( startTime );
1047 logger->TimeOfLastLog .SetAs( startTime );
1048
1049 logInternal( impl, Verbosity::Info, "LGR", logables );
1050 }
1051
1052 if ( loggerName.IsNotEmpty() && !foundOne ) {
1053 BoxesMA& logables= acquireInternalLogables(impl);
1054 logables.Add( "Logger {!Q}: not found. Start time not set.", loggerName );
1055 logInternal( impl, Verbosity::Error, "LGR", logables );
1056 return;
1057} }
1058
1059
1060void LI::MapThreadName(LoxImpl* impl, const String& threadName, threads::ThreadID id ) {
1061 #if !ALIB_SINGLE_THREADED
1062
1063 ASSERT_ACQUIRED
1064
1065 // get current thread id
1066 String origThreadName;
1067 if ( id == 0 ) {
1069 id= t->GetID();
1070 origThreadName= t->GetName();
1071 }
1072 else
1073 origThreadName= nullptr;
1074
1075 // add entry
1076 impl->scopeInfo.threadDictionary.EmplaceOrAssign(id, threadName);
1077
1078 // log info on this
1079 BoxesMA& logables= acquireInternalLogables(impl);
1080 logables.Add( "Mapped thread ID {} to {!Q}.", id, threadName);
1081 if ( origThreadName.IsNotEmpty() )
1082 logables.Add(" Original thread name: {!Q}.", origThreadName );
1083 logInternal( impl, Verbosity::Info, "THR", logables );
1084 #else
1085 (void) impl;
1086 (void) threadName;
1087 (void) id;
1088 #endif
1089}
1090
1091void LI::once( LoxImpl* impl,
1092 const NString& domain, Verbosity verbosity,
1093 const Box& logable,
1094 const String& pGroup,
1095 Scope scope,
1096 int quantity ) {
1097 int pathLevel= checkScopeInformation( impl, scope, "DMN" );
1098 if( pathLevel < 0 )
1099 return;
1100
1101 // We need a group. If none is given, there are two options:
1102 NString512 group(pGroup);
1103 bool groupWasEmtpy= group.IsEmpty();
1104 if ( groupWasEmtpy ) {
1105 // GLOBAL scope: exact code line match
1106 if ( scope == Scope::Global ) {
1107 scope= Scope::Filename;
1108 group._('#')._( impl->scopeInfo.GetLineNumber() );
1109 }
1110
1111 // not GLOBAL scope: Unique group per Scope
1112 else
1113 group._( impl->noKeyHashKey );
1114 }
1115
1116 // get the store
1117 impl->scopeLogOnce.InitAccess( scope, pathLevel, UNDEFINED_THREAD );
1118
1119 SSMap<int>* map= impl->scopeLogOnce.Get();
1120 if( map == nullptr ) {
1121 map= impl->newPO<SSMap<int>>(impl->poolAllocator);
1122 impl->scopeLogOnce.Store( map );
1123 }
1124
1125 // create map entry (if not created yet)
1126 auto it= map->Find( group );
1127 if (it == map->end() )
1128 it= map->InsertUnique( std::make_pair( NString(impl->poolAllocator, group), 0) );
1129
1130 // log Once
1131 if ( quantity >= 0 ) {
1132 if ( it->second < quantity ) {
1133 ++it->second;
1134
1135 // do the log
1136 GetLogableContainer(impl) .Add( std::forward<const Box&>( logable ) );
1137 Entry( impl, domain, verbosity );
1138
1139 // log info if this was the last time
1140 if( it->second == quantity ) {
1141 BoxesMA& logables= acquireInternalLogables(impl);
1142 logables.Add( "Once() reached limit of {} logs. No further logs for ", quantity );
1143
1144 if ( groupWasEmtpy )
1145 logables.Add( scope == Scope::Global ? Box( "this line" )
1146 : Box(scope + pathLevel) );
1147 else {
1148 logables.Add( "group {!Q}", group );
1149 if ( scope != Scope::Global )
1150 logables.Add(" in ", (scope + pathLevel) );
1151 }
1152 logables.Add('.');
1153
1154 logInternal( impl, Verbosity::Info, "", logables );
1155 } } }
1156
1157 // log Nth
1158 else {
1159 if ( it->second++ % -quantity == 0 ) {
1160 GetLogableContainer(impl) .Add( std::forward<const Box&>( logable ) );
1161 Entry( impl, domain, verbosity );
1162} } }
1163
1164void LI::store( LoxImpl* impl, const Box& data, const NString& pKey, Scope scope ) {
1165 // We need a key. If none is given, we use a constant one indicating that storage is
1166 // associated exclusively with scope
1167 NString256 key(pKey);
1168 bool keyWasEmtpy= key.IsEmpty();
1169 if ( keyWasEmtpy )
1170 key= impl->noKeyHashKey;
1171
1172 // get path level
1173 int pathLevel= 0;
1174 if ( scope > Scope::Path ) {
1175 pathLevel= int( scope - Scope::Path );
1176 scope= Scope::Path;
1177 }
1178
1179 // get the store
1180 impl->scopeLogData.InitAccess( scope, pathLevel, UNDEFINED_THREAD );
1181 SSMap<Box>* map= impl->scopeLogData.Get();
1182 if( map == nullptr ) {
1183 map= impl->newPO<SSMap<Box>>(impl->poolAllocator);
1184 impl->scopeLogData.Store( map );
1185 }
1186
1187 BoxesMA& logables= acquireInternalLogables(impl);
1188
1189 // create map entry (if not created yet)
1190 auto it= map->Find( key );
1191 if ( !data.IsType<void>() ) {
1192 bool replacedPrevious= false;
1193 if ( it == map->end() )
1194 map->InsertUnique( std::make_pair( NString(impl->poolAllocator, key), data ) );
1195 else {
1196 replacedPrevious= true;
1197 it->second= data;
1198 }
1199
1200 // log info if this was the last time
1201 logables.Add( "Stored data " );
1202
1203 if ( !keyWasEmtpy )
1204 logables.Add( " with key {!Q} ", key );
1205 logables.Add( "in {}.", (scope + pathLevel) );
1206 if ( replacedPrevious )
1207 logables.Add( " (Replaced and deleted previous.)" );
1208 }
1209
1210 // delete
1211 else {
1212 if ( it != map->end() ) {
1213 auto keyString= it->first;
1214 map->erase( it );
1215 if ( map->Size() == 0 ) {
1216 impl->deletePO(map);
1217 impl->scopeLogData.Remove( nullptr );
1218 }
1219 keyString.Free(impl->poolAllocator);
1220 logables.Add( "Deleted map data " );
1221 }
1222 else
1223 logables.Add( "No map data found to delete " );
1224
1225 if ( !keyWasEmtpy )
1226 logables.Add( " with key {!Q} ", key );
1227 logables.Add( "in {}.", (scope + pathLevel) );
1228 }
1229
1230 LI::logInternal( impl, Verbosity::Info, "LGD", logables );
1231}
1232
1233
1234Box LI::retrieve( LoxImpl* impl, const NString& pKey, Scope scope ) {
1235 // We need a key. If none is given, we use a constant one indicating that storage is
1236 // associated exclusively with scope
1237 NString256 key= pKey;
1238 bool keyWasEmtpy= key.IsEmpty();
1239 if ( keyWasEmtpy )
1240 key= impl->noKeyHashKey;
1241
1242 int pathLevel= 0;
1243 if ( scope > Scope::Path ) {
1244 pathLevel= int( scope - Scope::Path );
1245 scope= Scope::Path;
1246 }
1247
1248 // get the data (create if not found)
1249 impl->scopeLogData.InitAccess( scope, pathLevel, UNDEFINED_THREAD );
1250 Box returnValue;
1251 SSMap<Box>* map= impl->scopeLogData.Get();
1252 if( map != nullptr ) {
1253 auto it= map->Find( key );
1254 if ( it != map->end() )
1255 returnValue= it->second;
1256 }
1257
1258 if ( returnValue.IsType<void>() )
1259 store( impl, Box(), pKey, scope + pathLevel );
1260
1261 // log info if this was the last time
1262 BoxesMA& logables= acquireInternalLogables(impl);
1263 logables.Add( "Data " );
1264
1265 if ( !keyWasEmtpy )
1266 logables.Add( " with key {!Q} ", key );
1267 logables.Add( "in ", (scope + pathLevel), ( !returnValue.IsType<void>() ? " received."
1268 : " not found." ) );
1269
1270 logInternal( impl, Verbosity::Info, "LGD", logables );
1271 return returnValue;
1272}
1273
1274
1275void LI::State( LoxImpl* impl,
1276 const NString& domain,
1277 Verbosity verbosity,
1278 const String& headLine,
1279 StateInfo flags ) {
1280 ASSERT_ACQUIRED
1281
1282 NAString buf;
1283 buf.SetBuffer( 2048 );
1284 if ( headLine.IsNotEmpty() )
1285 buf._<NC>( headLine ).NewLine();
1286
1287 GetState( impl, buf, flags );
1288
1289 GetLogableContainer(impl) .Add( buf );
1290 Entry( impl, domain, verbosity );
1291}
1292
1294 auto cntAcquirements= impl->CountAcquirements();
1295 ALIB_ASSERT_ERROR( cntAcquirements >= 1, "ALOX", "Lox not acquired." )
1296 ALIB_ASSERT_WARNING( cntAcquirements < 5, "ALOX", "Logging recursion depth >= 5" )
1297 while( int(impl->logableContainers.size()) < cntAcquirements )
1298 impl->logableContainers.emplace_back( impl->monoAllocator().New<BoxesMA>(impl->monoAllocator) );
1299 BoxesMA& logables= *impl->logableContainers[size_t(cntAcquirements - 1)];
1300 logables.clear();
1301 return logables;
1302}
1303
1304void LI::Entry(LoxImpl* impl, const NString& domain, Verbosity verbosity ) {
1305 ASSERT_ACQUIRED
1306
1307 // auto-initialization of debug loggers
1308 #if ALOX_DBG_LOG
1309 if( impl == Log::Get()->impl
1310 && impl->domains->CountLoggers() == 0
1311 && Log::DEBUG_LOGGER == nullptr )
1312 Log::AddDebugLogger( Log::Get() );
1313 #endif
1314
1315 ALIB_ASSERT_ERROR(ALOX.IsBootstrapped(), "ALOX", "ALox (ALib) was not properly bootstrapped." )
1316
1317 ++impl->CntLogCalls;
1318
1319 if ( impl->domains->CountLoggers() == 0 )
1320 return;
1321
1322 log( impl,
1323 evaluateResultDomain( impl, domain ),
1324 verbosity,
1325 *impl->logableContainers[size_t(impl->CountAcquirements() - 1)],
1326 lang::Inclusion::Include );
1327}
1328
1329int LI::IsActive(LoxImpl* impl, Verbosity verbosity, const NString& domain, NAString* resultDomain){
1330 ASSERT_ACQUIRED
1331
1332 // auto-initialization of debug loggers
1333 #if ALOX_DBG_LOG
1334 if( impl == Log::Get()->impl
1335 && impl->domains->CountLoggers() == 0
1336 && Log::DEBUG_LOGGER == nullptr )
1337 Log::AddDebugLogger( Log::Get() );
1338 #endif
1339
1340 ALIB_ASSERT_ERROR(ALOX.IsBootstrapped(), "ALOX", "ALox (ALib) was not properly bootstrapped." )
1341
1342 Domain* dom= evaluateResultDomain( impl, domain );
1343 if ( resultDomain != nullptr )
1344 resultDomain->_( dom->FullPath );
1345
1346 if ( impl->domains->CountLoggers() == 0 )
1347 return 0;
1348
1349 int result= 0;
1350 for ( int i= 0; i < dom->CountLoggers() ; ++i )
1351 if( dom->IsActive( i, verbosity ) )
1352 ++result;
1353 return result;
1354}
1355
1356Verbosity LI::GetVerbosity(LoxImpl* impl, const NString& domain, NAString* resultDomain){
1357 ASSERT_ACQUIRED
1358
1359 // auto-initialization of debug loggers
1360 #if ALOX_DBG_LOG
1361 if( impl == Log::Get()->impl
1362 && impl->domains->CountLoggers() == 0
1363 && Log::DEBUG_LOGGER == nullptr )
1364 Log::AddDebugLogger( Log::Get() );
1365 #endif
1366
1367 ALIB_ASSERT_ERROR(ALOX.IsBootstrapped(), "ALOX", "ALox (ALib) was not properly bootstrapped." )
1368
1369 Domain* dom= evaluateResultDomain( impl, domain );
1370 if ( resultDomain != nullptr )
1371 resultDomain->_( dom->FullPath );
1372
1373 if ( impl->domains->CountLoggers() == 0 )
1374 return Verbosity::Off;
1375
1376 std::array verbosities={ Verbosity::Verbose, Verbosity::Info,
1377 Verbosity::Warning, Verbosity::Error, Verbosity::Off };
1378
1379 for ( auto verbosity : verbosities ) {
1380 for ( int i= 0; i < dom->CountLoggers() ; ++i )
1381 if( dom->IsActive( i, verbosity ) )
1382 return verbosity;
1383 }
1384 return Verbosity::Off;
1385}
1386
1387void LI::IncreaseLogCounter( LoxImpl* impl) { ++impl->CntLogCalls; }
1388
1389void LI::entryDetectDomainImpl(LoxImpl* impl, Verbosity verbosity ) {
1390 BoxesMA& logables= *impl->logableContainers[size_t(impl->CountAcquirements() - 1)];
1391 if ( logables.Size() > 1 && logables[0].IsArrayOf<nchar>() ) {
1392 NString firstArg= logables[0].Unbox<NString>();
1393
1394 // accept internal domain at the start
1395 integer idx= 0;
1396 if( firstArg.StartsWith( Lox::InternalDomains ) )
1397 idx+= Lox::InternalDomains.Length();
1398
1399 // loop over domain and check for illegal characters
1400 bool illegalCharacterFound= false;
1401 for( ; idx< firstArg.Length() ; ++idx ) {
1402 char c= firstArg[idx];
1403 if (! ( isdigit( c )
1404 || ( c >= 'A' && c <= 'Z' )
1405 || c == '-'
1406 || c == '_'
1407 || c == '/'
1408 || c == '.'
1409 ) )
1410 {
1411 illegalCharacterFound= true;
1412 break;
1413 } }
1414
1415 if ( illegalCharacterFound ) {
1416 Entry( impl, nullptr, verbosity );
1417 return;
1418 }
1419
1420 logables.erase( logables.begin() );
1421 Entry( impl, firstArg, verbosity );
1422 return;
1423 }
1424
1425 Entry( impl, nullptr, verbosity );
1426}
1427
1428
1429//##################################################################################################
1430// internals
1431//##################################################################################################
1432Domain* LI::evaluateResultDomain(LoxImpl* impl, const NString& domainPath ) {
1433 NString128 resDomain;
1434
1435 // 0. internal domain tree?
1436 if ( domainPath.StartsWith( Lox::InternalDomains ) ) {
1437 // cut "$/" from the path
1438 resDomain._( domainPath, Lox::InternalDomains.Length() );
1439 return findDomain( impl, *impl->internalDomains, resDomain );
1440 }
1441
1442 // loop over scopes
1443 NString64 localPath; localPath.DbgDisableBufferReplacementWarning();
1444 impl->scopeDomains.InitWalk( Scope::ThreadInner,
1445 // we have to provide NULL_STRING if parameter is empty
1446 domainPath.IsNotEmpty() ? localPath._(domainPath)
1447 : NULL_NSTRING
1448 );
1449 NString nextDefault;
1450 while( (nextDefault= impl->scopeDomains.Walk() ).IsNotNull() ) {
1451 ALIB_ASSERT( nextDefault.IsNotEmpty(), "ALOX" )
1452
1453 if ( resDomain.IsNotEmpty() )
1454 resDomain.InsertAt( "/", 0);
1455 resDomain.InsertAt( nextDefault, 0 );
1456
1457 // absolute path? That's it
1458 if ( resDomain.CharAtStart() == Domain::Separator() )
1459 break;
1460 }
1461 return findDomain( impl, *impl->domains, resDomain );
1462}
1463
1464void LI::getVerbosityFromConfig(LoxImpl* impl, Variable& v, Logger* logger, Domain& dom ) {
1465 // get logger number. It may happen that the logger is not existent in this domain tree.
1466 int loggerNo= dom.GetLoggerNo( logger ) ;
1467 if ( loggerNo < 0 )
1468 return;
1469
1470 auto& cvVerb = v.Get<alib::lox::CVVerbosities>();
1471
1472 for (auto it : cvVerb) {
1473 Tokenizer verbosityTknzr( it, '=' );
1474
1475 NString256 domainStrBuf;
1476 Substring domainStrParser= verbosityTknzr.Next();
1477 if ( domainStrParser.ConsumeString<lang::Case::Ignore>( A_CHAR("INTERNAL_DOMAINS")) ) {
1478 while ( domainStrParser.ConsumeChar('/') )
1479 ;
1480 domainStrBuf << Lox::InternalDomains << domainStrParser;
1481 }
1482 else
1483 domainStrBuf._( domainStrParser );
1484
1485 NSubstring domainStr= domainStrBuf ;
1486
1487 Substring verbosityStr= verbosityTknzr.Next();
1488 if ( verbosityStr.IsEmpty() )
1489 continue;
1490
1491 int searchMode= 0;
1492 if ( domainStr.ConsumeChar ( '*' ) ) searchMode+= 2;
1493 if ( domainStr.ConsumeCharFromEnd( '*' ) ) searchMode+= 1;
1494 if( ( searchMode == 0 && dom.FullPath.Equals <NC ,lang::Case::Ignore>( domainStr ) )
1495 || ( searchMode == 1 && dom.FullPath.StartsWith<CHK,lang::Case::Ignore>( domainStr ) )
1496 || ( searchMode == 2 && dom.FullPath.EndsWith <CHK,lang::Case::Ignore>( domainStr ) )
1497 || ( searchMode == 3 && dom.FullPath.IndexOf <CHK,lang::Case::Ignore>( domainStr ) >=0 )
1498 )
1499 {
1500 Verbosity verbosity(Verbosity::Info);
1501 enumrecords::Parse<Verbosity>(verbosityStr, verbosity );
1502 dom.SetVerbosity( loggerNo, verbosity, v.GetPriority() );
1503
1504 // log info on this
1505 NString512 msg;
1506 msg._<NC>( "Logger \"" )._<NC>( logger->GetName() ) ._<NC>( "\":" )._(NTab(11 + impl->maxLoggerNameLength))
1507 ._<NC>( '\'' )._<NC>( dom.FullPath )
1508 ._( '\'' ).InsertChars(' ', impl->maxDomainPathLength - dom.FullPath.Length() + 1 )
1509 ._( "= Verbosity::" )
1510 ._( boxing::MakePair(verbosity, dom.GetPriority( loggerNo )) ).TrimEnd()
1511 ._<NC>( '.' );
1512
1513 logInternal( impl, Verbosity::Info, "LGR", msg );
1514} } }
1515
1518 {ALIB_LOCK_WITH(ALOX.GetConfig())
1520 decl= ALOX.GetConfig()->StoreDeclaration( decl,
1522 GetName( impl )
1523 #else
1524 String128( GetName( impl ) )
1525 #endif
1526 );
1527 if( !variable.Try(decl) )
1528 return;
1529 }
1530
1531 Tokenizer prefixTokOuter;
1532 prefixTokOuter.Set(variable, ';', true);
1533 while(prefixTokOuter.HasNext()) {
1534 Tokenizer prefixTok( prefixTokOuter.Next(), '=' );
1535
1536 NString128 domainStrBuf;
1537 Substring domainStrParser= prefixTok.Next();
1538 if ( domainStrParser.ConsumeString<lang::Case::Ignore>( A_CHAR("INTERNAL_DOMAINS")) ) {
1539 while ( domainStrParser.ConsumeChar('/') )
1540 ;
1541 domainStrBuf << Lox::InternalDomains << domainStrParser;
1542 }
1543 else
1544 domainStrBuf._( domainStrParser );
1545
1546 NSubstring domainStr= domainStrBuf ;
1547
1548 Tokenizer prefixTokInner( prefixTok.Next(), ',' );
1549 Substring prefixStr= prefixTokInner.Next();
1550 if ( prefixStr.IsEmpty() )
1551 continue;
1552 if ( prefixStr.ConsumeChar( '\"' ) )
1553 prefixStr.ConsumeCharFromEnd( '\"' );
1554
1556 prefixTokInner.Next();
1557 if ( prefixTokInner.Actual.IsNotEmpty() )
1559
1560 int searchMode= 0;
1561 if ( domainStr.ConsumeChar ( '*' ) ) searchMode+= 2;
1562 if ( domainStr.ConsumeCharFromEnd( '*' ) ) searchMode+= 1;
1563 if( ( searchMode == 0 && dom.FullPath.Equals <NC ,lang::Case::Ignore>( domainStr ) )
1564 || ( searchMode == 1 && dom.FullPath.StartsWith<CHK,lang::Case::Ignore>( domainStr ) )
1565 || ( searchMode == 2 && dom.FullPath.EndsWith <CHK,lang::Case::Ignore>( domainStr ) )
1566 || ( searchMode == 3 && dom.FullPath.IndexOf <CHK,lang::Case::Ignore>( domainStr ) >=0 )
1567 )
1568 {
1569 dom.PrefixLogables.emplace_back( impl->newPO<PrefixLogable>( impl->poolAllocator, prefixStr ), otherPLs );
1570
1571 // log info on this
1572 NString128 msg; msg._<NC>( "String \"" )._<NC>( prefixStr )._<NC>( "\" added as prefix logable for domain \'" )
1573 ._<NC>( dom.FullPath )
1574 ._<NC>( "\'. (Retrieved from configuration variable \'" )._<NC>(variable)._( "\'.)" );
1575
1576 logInternal( impl, Verbosity::Info, "PFX", msg );
1577} } }
1578
1579void LI::getAllVerbosities(LoxImpl* impl, Variable& varVerbosities, Logger* logger, Domain& dom) {
1580 // get verbosity for us
1581 getVerbosityFromConfig( impl, varVerbosities, logger, dom );
1582
1583 // loop over all subdomains (recursion)
1584 for ( Domain& subDomain : dom.SubDomains )
1585 getAllVerbosities( impl, varVerbosities, logger, subDomain );
1586}
1587
1588
1589Domain* LI::findDomain(LoxImpl* impl, Domain& rootDomain, NString domainPath ) {
1590 int maxSubstitutions= 10;
1591 NString128 substPath;
1592 for(;;) {
1593 // loop for creating domains, one by one
1594 Domain* dom= nullptr;
1595 for(;;) {
1596 bool wasCreated;
1597 dom= rootDomain.Find( domainPath, 1, &wasCreated );
1598 if ( wasCreated ) {
1599 // get maximum domain path length (for nicer State output only...)
1600 if ( impl->maxDomainPathLength < dom->FullPath.Length() )
1601 impl->maxDomainPathLength= dom->FullPath.Length();
1602
1603 // log info on new domain
1604 BoxesMA& logables= acquireInternalLogables(impl);
1605 logables.Add( "{!Q} registered.", dom->FullPath );
1606 logInternal( impl, Verbosity::Info, "DMN", logables );
1607 }
1608
1609 // read domain from config
1610 if ( !dom->ConfigurationAlreadyRead )
1611 { dom->ConfigurationAlreadyRead= true;
1612
1613 Box replacements[2];
1614 for ( int i= 0; i < dom->CountLoggers(); ++i ) {
1615 Logger* logger= dom->GetLogger(i);
1616 replacements[0]= GetName( impl );
1617 replacements[1]= logger->GetName();
1618 Variable varVerbosities= variables::CampVariable(ALOX, Variables::VERBOSITY, replacements );
1619 if ( varVerbosities.IsDefined() )
1620 getVerbosityFromConfig( impl, varVerbosities, logger, *dom );
1621 }
1622
1623 getDomainPrefixFromConfig( impl, *dom );
1624 }
1625
1626 if ( wasCreated ) {
1627 if ( dom->CountLoggers() == 0 )
1628 logInternal( impl, Verbosity::Verbose, "DMN", " No loggers set, yet." );
1629 else
1630 for ( int i= 0; i < dom->CountLoggers(); ++i ) {
1631 NString256 msg; msg._(" \"")._( dom->GetLogger(i)->GetName() )._("\": ");
1632 msg.InsertChars( ' ', impl->maxLoggerNameLength + 6 - msg.Length() );
1633 msg._( dom->FullPath )._(" = " )
1634 ._(boxing::MakePair(dom->GetVerbosity(i), dom->GetPriority(i)));
1635 logInternal( impl, Verbosity::Verbose, "DMN", msg );
1636 } }
1637 else
1638 break;
1639 }
1640
1641 // apply domain substitutions
1642 if( !impl->domainSubstitutions.empty() ) {
1643 substPath.Reset();
1644 NSubstring domFullPath= dom->FullPath;
1645 if ( domFullPath.CharAtStart<NC>() == '$' )
1646 domFullPath.ConsumeChar();
1647
1648 while( maxSubstitutions-- > 0 ) {
1649 // loop over rules
1650 bool substituted= false;
1651 for( auto& rule : impl->domainSubstitutions ) {
1652 switch( rule.type ) {
1654 if( substPath.IsEmpty() ) {
1655 if ( domFullPath.StartsWith( rule.Search ) ) {
1656 substPath._( rule.Replacement )._( domFullPath, rule.Search.Length() );
1657 substituted= true;
1658 continue;
1659 }
1660 } else {
1661 if ( substPath.StartsWith( rule.Search ) ) {
1662 substPath.ReplaceSubstring<NC>( rule.Replacement, 0, rule.Search.Length() );
1663 substituted= true;
1664 continue;
1665 } }
1666 break;
1667
1669 if( substPath.IsEmpty() ) {
1670 if ( domFullPath.EndsWith( rule.Search ) ) {
1671 substPath._( domFullPath, 0, domFullPath.Length() - rule.Search.Length() )._( rule.Replacement );
1672 substituted= true;
1673 continue;
1674 }
1675 } else {
1676 if ( substPath.EndsWith( rule.Search ) ) {
1677 substPath.DeleteEnd( rule.Search.Length() )._( rule.Replacement );
1678 substituted= true;
1679 continue;
1680 } }
1681 break;
1682
1683
1685 {
1686 if( substPath.IsEmpty() ) {
1687 integer idx= domFullPath.IndexOf( rule.Search );
1688 if ( idx >= 0 ) {
1689 substPath._( domFullPath, 0, idx )._( rule.Replacement)._( domFullPath, idx + rule.Search.Length() );
1690 substituted= true;
1691 continue; //next rule
1692 }
1693 } else {
1694 integer idx= substPath.IndexOf( rule.Search, 0 );
1695 if ( idx >= 0 ) {
1696 substPath.ReplaceSubstring<NC>( rule.Replacement, idx, rule.Search.Length() );
1697 substituted= true;
1698 continue; //next rule
1699 } } }
1700 break;
1701
1702
1704 {
1705 if( substPath.IsEmpty() ) {
1706 if ( domFullPath.Equals<NC>( rule.Search ) ) {
1707 substPath._( rule.Replacement);
1708 substituted= true;
1709 continue; //next rule
1710 }
1711 if ( domFullPath.CharAtStart<NC>() == '$' ) {
1712 substPath._( rule.Replacement);
1713 substituted= true;
1714 continue; //next rule
1715 }
1716 } else {
1717 if ( substPath.Equals<NC>( rule.Search) ) {
1718 substPath.Reset( rule.Replacement );
1719 substituted= true;
1720 continue; //next rule
1721 } } }
1722 break;
1723
1724 default: ALIB_ERROR("ALOX", "Illegal switch state." ) break;
1725 } // switch rule type
1726
1727 }//rules loop
1728
1729 // stop if non was found
1730 if( !substituted )
1731 break;
1732 }
1733
1734 // too many substitutions?
1735 if ( maxSubstitutions <= 0 && !impl->oneTimeWarningCircularDS ) {
1736 impl->oneTimeWarningCircularDS= true;
1737 logInternal( impl, Verbosity::Error, "DMN",
1738 "The Limit of 10 domain substitutions was reached. Circular substitution assumed!"
1739 " (This error is only reported once!)" );
1740 }
1741
1742 // anything substituted?
1743 if( substPath.Length() > 0 ) {
1744 domainPath= substPath;
1745 continue;
1746 } }
1747
1748 return dom;
1749} }
1750
1751int LI::checkScopeInformation(LoxImpl* impl, Scope& scope, const NString& internalDomain ) {
1752 int pathLevel= 0;
1753 if ( scope > Scope::Path ) {
1754 pathLevel= int( scope - Scope::Path );
1755 scope= Scope::Path;
1756 }
1757
1758 if ( ( scope == Scope::Path && impl->scopeInfo.GetFullPath().IsEmpty() )
1759 || ( scope == Scope::Filename && impl->scopeInfo.GetFileName().IsEmpty() )
1760 || ( scope == Scope::Method && impl->scopeInfo.GetMethod() .IsEmpty() ) )
1761 {
1762 BoxesMA& logables= acquireInternalLogables(impl);
1763 logables.Add( "Missing scope information. Cant use {}.", (scope + pathLevel) );
1764 logInternal( impl, Verbosity::Error, internalDomain, logables );
1765 return -1;
1766 }
1767 return pathLevel;
1768}
1769
1771 // check
1772 if ( scope == Scope::ThreadOuter
1773 || scope == Scope::ThreadInner )
1774 return true;
1775
1776 BoxesMA& logables= acquireInternalLogables(impl);
1777 logables.Add( "Illegal parameter, only Scope::ThreadOuter and Scope::ThreadInner allowed."
1778 " Given: {}.", scope );
1779 logInternal( impl, Verbosity::Error, "DMN", logables );
1780
1781 #if ALIB_DEBUG
1783 impl->scopeInfo.GetLineNumber(),
1784 impl->scopeInfo.GetMethod(),
1785 #if !ALIB_SINGLE_THREADED
1787 #elif ALIB_EXT_LIB_THREADS_AVAILABLE
1788 std::thread::id(),
1789 #endif
1790 impl->scopeInfo.GetTypeInfo()
1791 },
1792 0, "Illegal scope type \"{}\" given. Only Scope::ThreadOuter and "
1793 "Scope::ThreadInner allowed.", scope );
1794 #endif
1795
1796 return false;
1797}
1798
1799void LI::log( LoxImpl* impl , Domain* dom,
1800 Verbosity verbosity, BoxesMA& logables, lang::Inclusion includePrefixes ) {
1801 ++dom->CntLogCalls;
1802 bool logablesCollected= false;
1803 PrefixLogable marker(impl->poolAllocator, nullptr);
1804 for ( int i= 0; i < dom->CountLoggers() ; ++i )
1805 if( dom->IsActive( i, verbosity ) ) {
1806 // lazily collect objects once an active logger is found
1807 if ( !logablesCollected ) {
1808 logablesCollected= true;
1809 impl->scopePrefixes.InitWalk( Scope::ThreadInner, &marker );
1810 const Box* next;
1811 int userLogablesSize= int( logables.Size() );
1812 int threadInnersSize= -1;
1813
1814 while( (next= impl->scopePrefixes.Walk() ) != nullptr ) {
1815 if( next != &marker ) {
1816 // this is false for internal domains (only domain specific logables are added there)
1817 if ( includePrefixes == lang::Inclusion::Include ) {
1818 // after marker is read, logables need to be prepended. This is checked below
1819 // using "qtyThreadInners < 0"
1820 if ( next->IsType<BoxesMA*>() ) {
1821 auto* boxes= next->Unbox<BoxesMA*>();
1822 for (auto pfxI= boxes->Size() - 1 ; pfxI >= 0 ; --pfxI )
1823 logables.emplace( logables.begin() + ( threadInnersSize < 0 ? userLogablesSize : 0 ),
1824 (*boxes)[size_t(pfxI)] );
1825 }
1826 else if ( next->IsType<Boxes*>() ) {
1827 auto* boxes= next->Unbox<Boxes*>();
1828 for (auto pfxI= boxes->Size() - 1 ; pfxI >= 0 ; --pfxI )
1829 logables.emplace( logables.begin() + ( threadInnersSize < 0 ? userLogablesSize : 0 ),
1830 (*boxes)[size_t(pfxI)] );
1831 }
1832 else if ( next->IsType<BoxesPA*>() ) {
1833 auto* boxes= next->Unbox<BoxesPA*>();
1834 for (auto pfxI= boxes->Size() - 1 ; pfxI >= 0 ; --pfxI )
1835 logables.emplace( logables.begin() + ( threadInnersSize < 0 ? userLogablesSize : 0 ),
1836 (*boxes)[size_t(pfxI)] );
1837 }
1838 else
1839 logables.emplace( logables.begin() + ( threadInnersSize < 0 ? userLogablesSize : 0 ), *next );
1840 } }
1841
1842 // was this the actual? then insert domain-associated logables now
1843 else {
1844 bool excludeOthers= false;
1845 threadInnersSize= int( logables.Size() ) - userLogablesSize;
1846 Domain* pflDom= dom;
1847 while ( pflDom != nullptr ) {
1848 for( auto it= pflDom->PrefixLogables.rbegin() ; it != pflDom->PrefixLogables.rend() ; ++it ) {
1849 // a list of logables? Copy them
1850 PrefixLogable& prefix= *it->first;
1851 if ( prefix.IsType<Boxes*>() ) {
1852 auto* boxes= prefix.Unbox<Boxes*>();
1853 for (auto pfxI= boxes->Size() - 1 ; pfxI >= 0 ; --pfxI )
1854 logables.emplace( logables.begin(),
1855 (*boxes)[size_t(pfxI)] );
1856 }
1857 else if ( prefix.IsType<BoxesMA*>() ) {
1858 auto* boxes= prefix.Unbox<BoxesMA*>();
1859 for (auto pfxI= boxes->Size() - 1 ; pfxI >= 0 ; --pfxI )
1860 logables.emplace( logables.begin(),
1861 (*boxes)[size_t(pfxI)] );
1862 }
1863 else if ( prefix.IsType<BoxesPA*>() ) {
1864 auto* boxes= prefix.Unbox<BoxesPA*>();
1865 for (auto pfxI= boxes->Size() - 1 ; pfxI >= 0 ; --pfxI )
1866 logables.emplace( logables.begin(),
1867 (*boxes)[size_t(pfxI)] );
1868 }
1869 else
1870 logables.emplace( logables.begin(), prefix );
1871
1872
1873 if ( it->second == lang::Inclusion::Exclude ) {
1874 excludeOthers= true;
1875 break;
1876 } }
1877
1878 pflDom= excludeOthers ? nullptr : pflDom->Parent;
1879 }
1880
1881 // found a stoppable one? remove those from thread inner and break
1882 if (excludeOthers) {
1883 for ( int ii= 0; ii < threadInnersSize ; ++ii )
1884 logables.pop_back();
1885 break;
1886 } } }
1887 } // end of collection
1888
1889 Logger* logger= dom->GetLogger(i);
1890 { ALIB_LOCK_RECURSIVE_WITH(*logger)
1891 ++logger->CntLogs;
1892 logger->Log( *dom, verbosity, logables, impl->scopeInfo );
1893 logger->TimeOfLastLog= Ticks::Now();
1894} } }
1895
1897 if( integer(impl->internalLogables.size()) == impl->internalLogRecursionCounter ) {
1898 BoxesMA* newLogables= impl->monoAllocator().New<BoxesMA>(impl->monoAllocator);
1899 impl->internalLogables.emplace_back( newLogables );
1900 }
1901
1902 return *impl->internalLogables[size_t(impl->internalLogRecursionCounter++)];
1903}
1904
1905void LI::logInternal(LoxImpl* impl, Verbosity verbosity, const NString& subDomain, BoxesMA& msg ) {
1906 ALIB_ASSERT_ERROR(ALOX.IsBootstrapped(), "ALOX", "ALox (ALib) was not properly bootstrapped." )
1907 log( impl, findDomain( impl, *impl->internalDomains, subDomain ), verbosity, msg, lang::Inclusion::Exclude );
1908
1909 impl->internalLogables[size_t(--impl->internalLogRecursionCounter)]->clear();
1910}
1911
1912void LI::logInternal( LoxImpl* impl , Verbosity verbosity,
1913 const NString& subDomain, const NString& msg ) {
1914 BoxesMA& logables= acquireInternalLogables(impl);
1915 logables.Add( msg );
1916 logInternal( impl, verbosity, subDomain, logables );
1917}
1918
1919#if !DOXYGEN
1920
1921namespace {
1922void getStateDomainRecursive( Domain& domain, integer maxDomainPathLength, NAString& buf );
1923void getStateDomainRecursive( Domain& domain, integer maxDomainPathLength, NAString& buf ) {
1924 integer reference= buf.Length();
1925 buf._(" "); domain.ToString( buf );
1926 integer idx= buf.IndexOf( '[', reference );
1927 buf.InsertChars( ' ', maxDomainPathLength + 5 - idx + reference, idx);
1928 buf.NewLine();
1929
1930 // loop over all subdomains (recursion)
1931 for ( Domain& subDomain : domain.SubDomains )
1932 getStateDomainRecursive( subDomain, maxDomainPathLength, buf );
1933}
1934
1935void getStateDomainsWithDiffVerb( Domain& dom, int loggerNo, std::vector<Domain*>& results );
1936void getStateDomainsWithDiffVerb( Domain& dom, int loggerNo, std::vector<Domain*>& results ) {
1937 if ( dom.Parent == nullptr
1938 || dom.Parent->GetVerbosity(loggerNo) != dom.GetVerbosity(loggerNo) )
1939 results.emplace_back( &dom );
1940
1941 for( auto& it : dom.SubDomains )
1942 getStateDomainsWithDiffVerb( it, loggerNo, results );
1943}
1944
1945void getStateCollectPrefixes( Domain& dom, integer indentSpaces, NAString& target );
1946void getStateCollectPrefixes( Domain& dom, integer indentSpaces, NAString& target ) {
1947 AString buffer;
1948 for ( auto& pfl : dom.PrefixLogables ) {
1949 buffer.InsertChars( ' ', indentSpaces );
1950 buffer << '"';
1951 integer actLen= buffer.Length();
1952 buffer._( *static_cast<Box*>(pfl.first) );
1953 ESC::ReplaceToReadable( buffer, actLen );
1954 buffer << Escape( lang::Switch::On, actLen );
1955 buffer << '"';
1956 if ( pfl.second == lang::Inclusion::Exclude )
1957 buffer._<NC>( " (Excl.)" );
1958 buffer._<NC>( Tab( 25, -1 ) );
1959 buffer._<NC>( "<domain> [" )._<NC>( dom.FullPath )._<NC>(']').NewLine();
1960 }
1961 target << buffer;
1962
1963 for( auto& subDom : dom.SubDomains )
1964 getStateCollectPrefixes( subDom, indentSpaces, target );
1965}
1966
1967} // anonymous namespace
1968
1969#endif // !DOXYGEN
1970
1971
1972void LI::GetState( LoxImpl* impl, NAString& buf, StateInfo flags ) {
1973 ASSERT_ACQUIRED
1974
1976 impl->noKeyHashKey, buf );
1977
1978 if ( HasBits( flags, StateInfo::CompilationFlags ) ) {
1979 buf._<NC>( "ALib Version: " )._<NC>( alib::VERSION)
1980 ._<NC>(" (Rev. ") ._ ( alib::REVISION)._(')').NewLine();
1981 buf._<NC>( "ALib Configuration Macros:" ).NewLine();
1982 {
1983 for( auto& p : alib::COMPILATION_FLAG_MEANINGS ) {
1984 buf << " " << NField( p.Name, 41, lang::Alignment::Left ) << ':'
1985 << (alib::COMPILATION_FLAGS.bits[p.Flag/8] & (1 << p.Flag % 8) ? " On" : " Off")
1986 << NEW_LINE;
1987 }
1988
1989 }
1990
1991 buf.NewLine();
1992 }
1993
1994 // basic lox info
1995 if( alib::HasBits( flags, StateInfo::Basic ) )
1996 buf._<NC>( "Name: \"" )._( impl->scopeInfo.GetLoxName() )._('\"').NewLine();
1997
1998 if( HasBits( flags, StateInfo::Version ) ) {
1999 buf._<NC>( "Version: " )._<NC>( alib::VERSION)
2000 ._<NC>(" (Rev. " )._( alib::REVISION)._(')').NewLine();
2001 }
2002
2003 if( HasBits( flags, StateInfo::Basic ) )
2004 buf._<NC>( "#Log Calls: " )._<NC>( impl->CntLogCalls ).NewLine();
2005
2006 if( HasBits( flags, StateInfo::Basic )
2007 || HasBits( flags, StateInfo::Version ) )
2008 buf.NewLine();
2009
2010 // source path trim info
2011 if( HasBits( flags, StateInfo::SPTR ) ) {
2012 buf._<NC>( "Source Path Trimming Rules: " ).NewLine();
2013
2014 int cnt= 0;
2015 // do 2 times, 0== global list, 1 == local list
2016 for( int trimInfoNo= 0; trimInfoNo < 2 ; ++trimInfoNo ) {
2017 // choose local or global list
2018 std::vector<ScopeInfo::SourcePathTrimRule>* trimInfoList=
2019 trimInfoNo == 0 ? &ScopeInfo::GlobalSPTRs
2020 : &impl->scopeInfo.LocalSPTRs;
2021
2022
2023 // loop over trimInfo
2024 for ( auto& ti : *trimInfoList ) {
2025 ++cnt;
2026 buf._<NC>( trimInfoNo == 0 ? " Global: "
2027 : " Local: " );
2028 buf._<NC>( ti.IsPrefix ? "\"" : "\"*");
2029 buf._<NC>( ti.Path )._<NC>( "\", " );
2030 buf._<NC>( ti.IncludeString );
2031 if ( ti.TrimOffset != 0 )
2032 buf._<NC>( ti.Path )._<NC>( "\", Offset: " )._<NC>( ti.TrimOffset );
2033 buf._<NC>( ", Priority: " )._( ti.Priority );
2034 buf.NewLine();
2035 } }
2036
2037
2038 if ( cnt == 0 )
2039 buf._<NC>(" <no rules set>" ).NewLine();
2040 buf.NewLine();
2041 }
2042
2043 // domain substitutions
2044 if( HasBits( flags, StateInfo::DSR ) ) {
2045 buf._<NC>( "Domain Substitution Rules: " ).NewLine();
2046 if( !impl->domainSubstitutions.empty() ) {
2047 // get size
2048 integer maxWidth= 0;
2049 for ( auto& it : impl->domainSubstitutions )
2050 if ( maxWidth < it.Search.Length() )
2051 maxWidth = it.Search.Length();
2052 maxWidth+= 2;
2053
2054 // write
2055 for ( auto& it : impl->domainSubstitutions ) {
2056 buf._<NC>( " " );
2059 buf._<NC>( '*' );
2060
2061 buf._<NC>( it.Search );
2064 buf._<NC>( '*' );
2065
2066 buf._<NC>( NTab( maxWidth, -1, 0 ) )
2067 ._<NC>( " -> " )
2068 ._<NC>( it.Replacement );
2069 buf.NewLine();
2070 } }
2071 else
2072 buf._<NC>(" <no rules set>" ).NewLine();
2073 buf.NewLine();
2074 }
2075
2076 // Log Once Counters
2077 if( HasBits( flags, StateInfo::Once ) ) {
2078 buf._<NC>( "Once() Counters: " ).NewLine();
2079 if ( scopeDump.writeStoreMap( &impl->scopeLogOnce ) == 0 )
2080 buf._<NC>(" <no Once() counters set>" ).NewLine();
2081 buf.NewLine();
2082 }
2083
2084 // Log Data
2085 if( HasBits( flags, StateInfo::LogData ) ) {
2086 buf._<NC>( "Log Data: " ).NewLine();
2087 if ( scopeDump.writeStoreMap( &impl->scopeLogData ) == 0 )
2088 buf._<NC>(" <no data objects stored>" ).NewLine();
2089 buf.NewLine();
2090 }
2091
2092 // Prefix Logables
2093 if( HasBits( flags, StateInfo::PrefixLogables ) ) {
2094 buf._<NC>( "Prefix Logables: " ).NewLine();
2095 integer oldLength= buf.Length();
2096 scopeDump.writeStore( &impl->scopePrefixes, 2 );
2097 getStateCollectPrefixes( *impl->domains, 2, buf );
2098 if ( oldLength == buf.Length() )
2099 buf._<NC>(" <no prefix logables set>" ).NewLine();
2100 buf.NewLine();
2101 }
2102
2103 // thread mappings
2104 if( HasBits( flags, StateInfo::ThreadMappings ) ) {
2105 #if !ALIB_SINGLE_THREADED
2106 buf._<NC>( "Named Threads: " ).NewLine();
2107 if ( impl->scopeInfo.threadDictionary.Size() == 0 )
2108 buf._<NC>(" <no thread name mappings set>" ).NewLine();
2109 else
2110 for ( auto& pair : impl->scopeInfo.threadDictionary ) {
2111 buf._<NC>( " " ) << NField( String32() << '(' << pair.first << "):", 7, lang::Alignment::Left )
2112 << '\"' << pair.second << '\"';
2113 buf.NewLine();
2114 }
2115 buf.NewLine();
2116 #endif
2117 }
2118
2119 // Scope Domains
2120 if( HasBits( flags, StateInfo::ScopeDomains ) ) {
2121 buf._<NC>( "Scope Domains: " ).NewLine();
2122 if ( scopeDump.writeStore( &impl->scopeDomains, 2 ) == 0 )
2123 buf._<NC>(" <no scope domains set>" ).NewLine();
2124 buf.NewLine();
2125 }
2126
2127 // Loggers
2128 if( HasBits( flags, StateInfo::Loggers ) ) {
2129 TickConverter dateTimeConverter;
2130 std::vector<Domain*> domainsWithDiffVerb;
2131 for (int treeNo= 0; treeNo < 2; ++treeNo ) {
2132 int cnt= 0;
2133 Domain* domTree;
2134 if( treeNo==0 ) {
2135 domTree= impl->domains;
2136 buf._<NC>( "Loggers:" ).NewLine();
2137 } else {
2138 domTree= impl->internalDomains;
2139 buf._<NC>( "Loggers on Internal Domains:" ).NewLine();
2140 }
2141
2142 for ( int loggerNo= 0; loggerNo< domTree->CountLoggers(); ++loggerNo ) {
2143 ++cnt;
2144 String64 as64;
2146
2147 Logger* logger= domTree->GetLogger(loggerNo);
2148 buf._<NC>( " " )._<NC>( *logger ).NewLine();
2149 buf._<NC>( " Lines logged: " )._<NC>( logger->CntLogs ).NewLine();
2150
2151 ct.Set( dateTimeConverter.ToDateTime(logger->TimeOfCreation) );
2152 buf._<NC>( " Creation time: " )._<NC>( ct.Format( A_CHAR("yyyy-MM-dd HH:mm:ss"), as64.Reset()) ).NewLine();
2153
2154 ct.Set( dateTimeConverter.ToDateTime(logger->TimeOfLastLog) );
2155 buf._<NC>( " Last log time: " )._<NC>( ct.Format( A_CHAR("yyyy-MM-dd HH:mm:ss"), as64.Reset()) ).NewLine();
2156
2157 domainsWithDiffVerb.clear();
2158 getStateDomainsWithDiffVerb( *domTree, loggerNo, domainsWithDiffVerb);
2159 for ( Domain* dom : domainsWithDiffVerb ) {
2160 buf._<NC>(" ")
2161 ._( dom == *domainsWithDiffVerb.begin() ? "Verbosities: "
2162 : " " );
2163
2164 integer tabRef= buf.Length();
2165 buf << dom->FullPath << NTab( impl->maxDomainPathLength +1, tabRef);
2166
2167 buf << "= " << boxing::MakePair(dom->GetVerbosity( loggerNo ), dom->GetPriority(loggerNo) )
2168 << NEW_LINE;
2169 } }
2170 if ( cnt == 0 )
2171 buf._<NC>(" <no loggers attached>" ).NewLine();
2172 buf.NewLine();
2173 } }
2174
2175 // Internal Domains
2176 if( HasBits( flags, StateInfo::InternalDomains ) ) {
2177 buf._<NC>( "Internal Domains:" ).NewLine();
2178 getStateDomainRecursive( *impl->internalDomains, impl->maxDomainPathLength, buf );
2179 buf.NewLine();
2180 }
2181
2182 // Domains
2183 if( HasBits( flags, StateInfo::Domains ) ) {
2184 buf._<NC>( "Domains:" ).NewLine();
2185 getStateDomainRecursive( *impl->domains , impl->maxDomainPathLength, buf );
2186 buf.NewLine();
2187} }
2188
2189} // namespace alib::lox[::detail]
2190
2191
2192
2193}} // namespace [alib::lox]
2194# include "ALib.Lang.CIMethods.H"
2195
2196#undef UNDEFINED_THREAD
2197#undef ASSERT_ACQUIRED
#define ALIB_LOCK_SHARED_WITH(lock)
Definition alib.inl:1415
#define IF_ALIB_THREADS(...)
Definition alib.inl:466
#define A_CHAR(STR)
Definition alib.inl:1325
#define ALIB_CHARACTERS_WIDE
Definition alib.inl:966
#define ALIB_WARNING(domain,...)
Definition alib.inl:1141
#define ALIB_ASSERT_WARNING(cond, domain,...)
Definition alib.inl:1145
#define ALIB_ERROR(domain,...)
Definition alib.inl:1140
#define ALIB_LOCK_RECURSIVE_WITH(lock)
Definition alib.inl:1414
#define ALIB_DBG(...)
Definition alib.inl:931
#define ALIB_ASSERT_ERROR(cond, domain,...)
Definition alib.inl:1144
#define ALIB_CALLER_PRUNED
Definition alib.inl:1102
#define ALIB_COMMA
Definition alib.inl:1041
#define ALIB_LOCK_WITH(lock)
Definition alib.inl:1413
#define ALIB_REL_DBG(releaseCode,...)
Definition alib.inl:933
#define LOG_RELEASE
#define LOG_ACQUIRE
#define ALIB_BOXING_VTABLE_DEFINE(TMapped, Identifier)
decltype(std::declval< typename TFDecl::Signature >()(std::declval< Box & >(), std::declval< TArgs >()...)) Call(TArgs &&... args) const
Definition box.inl:971
bool IsType() const
bool IsArray() const
Definition box.inl:554
integer UnboxLength() const
Definition box.inl:828
bool IsNull() const
Definition box.inl:1114
TBoxes & Add()
Definition boxes.inl:55
integer Size() const
Definition boxes.inl:126
std::pair< Iterator, bool > EmplaceOrAssign(const KeyType &key, TArgs &&... args)
Iterator Find(const KeyType &key)
integer erase(const KeyType &key)
Iterator InsertUnique(const StoredType &value)
integer Size() const noexcept
static void ReplaceToReadable(AString &target, integer startIdx)
Definition aloxinit.cpp:48
static void RemoveDebugLogger(Lox *lox)
Definition alox.cpp:256
static textlogger::TextLogger * DEBUG_LOGGER
The debug logger created by AddDebugLogger.
Definition log.inl:40
static Lox * Get()
Definition log.inl:47
static constexpr NString InternalDomains
Definition lox.inl:46
Domain * Find(NSubstring domainPath, int maxCreate, bool *wasCreated)
Definition domain.cpp:93
void ToString(NAString &target)
Definition domain.cpp:228
bool ConfigurationAlreadyRead
Flag which is set when verbosity configuration data was read.
Definition domain.inl:103
void RemoveLogger(int loggerNo)
Definition domain.inl:157
Domain * Parent
The parent domain. For root domains, this is nullptr.
Definition domain.inl:81
bool IsActive(int loggerNo, Verbosity verbosity)
Definition domain.inl:247
Verbosity GetVerbosity(int loggerNo)
Definition domain.inl:228
ListMA< Domain, Recycling::None > SubDomains
A list of subdomains, sorted by name.
Definition domain.inl:84
Verbosity SetVerbosity(int loggerNo, Verbosity verbosity, Priority priority)
Definition domain.cpp:204
NString FullPath
The full path of the domain (set in the constructor once) .
Definition domain.inl:78
Priority GetPriority(int loggerNo)
Definition domain.inl:233
ListPA< std::pair< PrefixLogable *, lang::Inclusion >, Recycling::None > PrefixLogables
Prefix Logables associated with this domain.
Definition domain.inl:93
int GetLoggerNo(const NString &loggerName)
Definition domain.inl:197
int AddLogger(detail::Logger *logger)
Definition domain.inl:140
detail::Logger * GetLogger(const NString &loggerName)
Definition domain.inl:177
const NString & GetName() const
Definition logger.inl:143
virtual void Log(Domain &dom, Verbosity verbosity, BoxesMA &logables, ScopeInfo &scope)=0
time::Ticks TimeOfLastLog
Timestamp of the last log operation.
Definition logger.inl:69
virtual void AcknowledgeLox(LoxImpl *lox, lang::ContainerOp op)
Definition logger.inl:134
time::Ticks TimeOfCreation
The creation time of the Logger.
Definition logger.inl:66
static std::vector< SourcePathTrimRule > GlobalSPTRs
List of trim definitions for portions of source paths to be ignored.
Definition scopeinfo.inl:60
const NCString & GetOrigFile()
std::thread::id GetThreadNativeID()
void SetSourcePathTrimRule(const NCString &path, lang::Inclusion includeString, int trimOffset, lang::Case sensitivity, const NString &trimReplacement, lang::Reach reach, Priority priority)
NString loxName
The name of the Lox we are attached to.
void SetFileNameCacheCapacity(integer numberOfLists, integer entriesPerList)
ThreadDictionary threadDictionary
Definition scopeinfo.inl:88
void PopNestedScope()
Releases latest scope information.
void Set(const lang::CallerInfo &ci)
std::vector< SourcePathTrimRule > LocalSPTRs
List of trim definitions for portions of source paths to be ignored.
Definition scopeinfo.inl:63
const std::type_info * GetTypeInfo()
static TMonoAllocator * Create(const char *dbgName, lang::HeapAllocator &pAllocator, size_t initialBufferSizeInKB, unsigned bufferGrowthInPercent=200)
void Reset(Snapshot snapshot=Snapshot())
TAString & ReplaceSubstring(const TString< TChar > &src, integer regionStart, integer regionLength)
TAString & DeleteEnd(integer regionLength)
TAString & InsertChars(TChar c, integer qty)
TAString & _(const TAppendable &src)
TAString & Trim(const TCString< TChar > &trimChars=CStringConstantsTraits< TChar >::DefaultWhitespaces())
constexpr integer Length() const
Definition string.inl:304
constexpr bool IsEmpty() const
Definition string.inl:353
bool EndsWith(const TString &needle) const
Definition string.inl:768
TChar CharAtStart() const
Definition string.inl:421
integer IndexOf(TChar needle, integer startIdx=0) const
Definition string.inl:803
constexpr bool IsNotNull() const
Definition string.inl:343
constexpr bool IsNotEmpty() const
Definition string.inl:357
TChar CharAtEnd() const
Definition string.inl:440
TString< TChar > Substring(integer regionStart, integer regionLength=MAX_LEN) const
Definition string.inl:372
bool Equals(const TString< TChar > &rhs) const
Definition string.inl:519
constexpr bool IsNull() const
Definition string.inl:338
bool StartsWith(const TString &needle) const
Definition string.inl:739
void Free(TAllocator &allocator)
Definition string.inl:1761
bool ConsumeString(const TString< TChar > &consumable)
integer ConsumePartOf(const TString< TChar > &consumable, int minChars=1)
bool ConsumeCharFromEnd(TChar consumable)
TSubstring & Trim(const TCString< TChar > &whiteSpaces=CStringConstantsTraits< TChar >::DefaultWhitespaces())
void Set(const DateTime &timeStamp, lang::Timezone timezone=lang::Timezone::Local)
Definition calendar.cpp:74
AString & Format(Substring format, AString &target, lang::CurrentData targetData=lang::CurrentData::Keep) const
Definition calendar.cpp:293
void Set(const TString< TChar > &src, TChar delimiter, bool skipEmptyTokens=false)
TSubstring< TChar > Actual
Definition tokenizer.inl:67
TSubstring< TChar > & Next(lang::Whitespaces trimming=lang::Whitespaces::Trim, TChar newDelim='\0')
Definition tokenizer.cpp:26
void AcquireRecursive(ALIB_DBG_TAKE_CI)
Definition locks.cpp:182
void ReleaseRecursive(ALIB_DBG_TAKE_CI)
Definition locks.cpp:215
static Thread * GetCurrent()
Definition thread.inl:298
ThreadID GetID() const
Definition thread.inl:227
virtual const character * GetName() const
Definition thread.inl:241
static DateTime FromFileTime(const FILETIME &fileTime)
static DateTime FromEpochSeconds(time_t epochSeconds)
Definition datetime.inl:63
DateTime ToDateTime(Ticks ticks)
Ticks ToTicks(DateTime dateTime)
void SetAs(const TDerived &other)
static const Declaration * Get(TEnum element)
bool Define(Priority requestedPriority=Priority::Standard)
Definition variable.cpp:260
bool Try(const String &name)
Variable & Declare(const String &name, const String &typeName, const String &defaultValue=NULL_STRING)
Definition variable.cpp:186
void Raise(const lang::CallerInfo &ci, int type, std::string_view domain, TArgs &&... args)
Definition assert.inl:181
void SingleThreaded()
Definition assert.cpp:140
constexpr Pair< T1, T2 > MakePair(const T1 &t1, const T2 &t2)
bool ParseEnumOrTypeBool(strings::TSubstring< TChar > &input, TEnum &result, TEnum falseValue, TEnum trueValue)
bool Parse(strings::TSubstring< TChar > &input, TEnum &result)
Reach
Denotes the reach of something.
@ Global
Denotes global reach.
@ Left
Chooses left alignment.
@ Remove
Denotes removals.
@ Insert
Denotes insertions.
@ On
Switch it on, switched on, etc.
Case
Denotes upper and lower case character treatment.
void Destruct(T &object)
Definition tmp.inl:82
@ Trim
Trim whitespaces away.
Inclusion
Denotes how members of a set something should be taken into account.
@ Exclude
Chooses exclusion.
@ Include
Chooses inclusion.
HashMap< PoolAllocator, NString, T, std::hash< NString >, std::equal_to< NString >, lang::Caching::Enabled, Recycling::None > SSMap
Shortcut to the ScopeStore's hashmap.
@ ScopeDomains
Scope domains.
@ CompilationFlags
ALib/ALox compilation flags
@ DSR
Domain substitution rules.
@ InternalDomains
Internal domains.
@ Version
Library Version and thread safeness.
@ PrefixLogables
Prefix logables.
@ Domains
Log domains currently registered.
@ LogData
Log data objects.
@ Basic
Name and number of log calls.
@ SPTR
Source path trim rules.
@ Once
Log once counters.
@ ThreadMappings
Named threads.
@ VERBOSITY
Denotes configuration variable #"alxcvALOX_LOGGERNAME_VERBOSITY_WITH_LOXNAME".
Definition aloxcamp.inl:28
@ DOMAIN_SUBSTITUTION
Denotes configuration variable #"alxcvALOX_LOXNAME_DOMAIN_SUBSTITUTION" used by class #"Lox".
Definition aloxcamp.inl:37
@ DUMP_STATE_ON_EXIT
Denotes configuration variable #"alxcvALOX_LOXNAME_DUMP_STATE_ON_EXIT" used by class #"Lox".
Definition aloxcamp.inl:43
@ PREFIXES
Denotes configuration variable #"alxcvALOX_LOXNAME_PREFIXES" used by class #"Lox".
Definition aloxcamp.inl:40
integer ThreadID
The ALib thread identifier type.
Definition thread.inl:23
variables::Variable CampVariable(camp::Camp &camp)
Definition camp.inl:285
monomem::TMonoAllocator< lang::HeapAllocator > MonoAllocator
threads::ThreadID ThreadID
Type to store thread identifiers.
Definition thread.inl:390
strings::TString< nchar > NString
Type alias in namespace alib.
Definition string.inl:2181
lox::textlogger::TextLogger TextLogger
Type alias in namespace alib.
strings::TField< nchar > NField
Type alias in namespace alib.
NLocalString< 32 > NString32
Type alias name for #"TLocalString;TLocalString<nchar,32>".
constexpr NString NULL_NSTRING
A nulled string of the narrow character type.
Definition string.inl:2263
threads::Thread Thread
Type alias in namespace alib.
Definition thread.inl:387
strings::TCString< nchar > NCString
Type alias in namespace alib.
Definition cstring.inl:408
alib::variables::Priority Priority
Type alias in namespace alib.
variables::Variable Variable
Type alias in namespace alib.
strings::TTab< nchar > NTab
Type alias in namespace alib.
Definition format.inl:515
CompilationFlagMeaningsEntry COMPILATION_FLAG_MEANINGS[40]
strings::util::TTokenizer< character > Tokenizer
Type alias in namespace alib.
containers::List< T, MonoAllocator, TRecycling > ListMA
Type alias in namespace alib.
Definition list.inl:697
strings::TEscape< character > Escape
Type alias in namespace alib.
Definition format.inl:532
LocalString< 64 > String64
Type alias name for #"TLocalString;TLocalString<character,64>".
constexpr CString NEW_LINE
A zero-terminated string containing the new-line character sequence.
Definition cstring.inl:540
lox::ALoxCamp ALOX
The singleton instance of ALib Camp class #"ALoxCamp".
Definition aloxcamp.cpp:54
strings::TAString< nchar, lang::HeapAllocator > NAString
Type alias in namespace alib.
boxing::TBoxes< lang::HeapAllocator > Boxes
Type alias in namespace alib.
Definition boxes.inl:189
lang::integer integer
Type alias in namespace alib.
Definition integers.inl:149
monomem::TPoolAllocator< MonoAllocator > PoolAllocator
boxing::Box Box
Type alias in namespace alib.
Definition box.inl:1135
TCompilationFlags COMPILATION_FLAGS
boxing::TBoxes< PoolAllocator > BoxesPA
Type alias in namespace alib.
Definition boxes.inl:196
int VERSION
strings::TString< character > String
Type alias in namespace alib.
Definition string.inl:2172
strings::TSubstring< character > Substring
Type alias in namespace alib.
strings::TSubstring< nchar > NSubstring
Type alias in namespace alib.
strings::util::CalendarDateTime CalendarDateTime
Type alias in namespace alib.
Definition calendar.inl:512
LocalString< 128 > String128
Type alias name for #"TLocalString;TLocalString<character,128>".
boxing::TBoxes< MonoAllocator > BoxesMA
Type alias in namespace alib.
Definition boxes.inl:193
NLocalString< 256 > NString256
Type alias name for #"TLocalString;TLocalString<nchar,256>".
LocalString< 256 > String256
Type alias name for #"TLocalString;TLocalString<character,256>".
time::Ticks Ticks
Type alias in namespace alib.
Definition ticks.inl:79
boxing::FEquals FEquals
Type alias in namespace alib.
NLocalString< 128 > NString128
Type alias name for #"TLocalString;TLocalString<nchar,128>".
NLocalString< 512 > NString512
Type alias name for #"TLocalString;TLocalString<nchar,512>".
strings::TAString< character, lang::HeapAllocator > AString
Type alias in namespace alib.
variables::Declaration Declaration
Type alias in namespace alib.
time::TickConverter TickConverter
Type alias in namespace alib.
std::vector< T, StdMA< T > > StdVectorMA
Type alias in namespace alib.
NLocalString< 64 > NString64
Type alias name for #"TLocalString;TLocalString<nchar,64>".
LocalString< 32 > String32
Type alias name for #"TLocalString;TLocalString<character,32>".
threads::RecursiveLock RecursiveLock
Type alias in namespace alib.
time::DateTime DateTime
Type alias in namespace alib.
Definition datetime.inl:185
unsigned char REVISION
strings::TTab< character > Tab
Type alias in namespace alib.
Definition format.inl:512
See sibling type #"NC".
Definition chk_nc.inl:33
void Clear()
Frees all allocated strings and clears vector.
Definition aloxcamp.inl:112
integer Add(const strings::TString< character > &src)
NString32 Search
The path to search.
Definition loxpimpl.cpp:79
DomainSubstitutionRule(const NString &s, const NString &r)
Definition loxpimpl.cpp:85
NString32 Replacement
The replacement.
Definition loxpimpl.cpp:80
static BoxesMA & GetLogableContainer(LoxImpl *impl)
static const NString & GetName(LoxImpl *impl)
Definition loxpimpl.cpp:290
static void getVerbosityFromConfig(LoxImpl *impl, variables::Variable &variable, detail::Logger *logger, detail::Domain &dom)
static BoxesMA & acquireInternalLogables(LoxImpl *impl)
static void SetFileNameCacheCapacity(LoxImpl *impl, integer numberOfLists, integer entriesPerList)
Definition loxpimpl.cpp:390
static detail::Domain * evaluateResultDomain(LoxImpl *impl, const NString &domainPath)
static void logInternal(LoxImpl *impl, Verbosity verbosity, const NString &subDomain, BoxesMA &msg)
static void SetStartTime(LoxImpl *impl, Ticks startTime, const NString &loggerName)
static integer & GetLogCounter(LoxImpl *impl)
Definition loxpimpl.cpp:292
static int checkScopeInformation(LoxImpl *impl, Scope &scope, const NString &internalDomain)
static void init(LoxImpl *impl)
Definition loxpimpl.cpp:321
static void Destruct(LoxImpl *lox)
Definition loxpimpl.cpp:284
static void store(LoxImpl *impl, const Box &data, const NString &pKey, Scope scope)
static void RemoveThreadDomain(LoxImpl *impl, const NString &scopeDomain, Scope scope, threads::Thread *thread)
Definition loxpimpl.cpp:828
static bool RemoveLogger(LoxImpl *impl, detail::Logger *logger)
Definition loxpimpl.cpp:566
static void SetVerbosity(LoxImpl *impl, detail::Logger *logger, Verbosity verbosity, const NString &domain, Priority priority)
Definition loxpimpl.cpp:629
static void SetDomain(LoxImpl *impl, const NString &scopeDomain, Scope scope, threads::Thread *thread)
Definition loxpimpl.cpp:410
static detail::Domain * findDomain(LoxImpl *impl, detail::Domain &domainSystem, NString domainPath)
static void SetDomainSubstitutionRule(LoxImpl *impl, const NString &domainPath, const NString &replacement)
Definition loxpimpl.cpp:848
static void SetPrefix(LoxImpl *impl, const Box &prefix, const NString &domain, lang::Inclusion otherPLs)
Definition loxpimpl.cpp:962
static void Release(LoxImpl *impl)
Definition loxpimpl.cpp:313
static void writeVerbositiesOnLoggerRemoval(LoxImpl *impl, Logger *logger)
Definition loxpimpl.cpp:450
static void setPrefix(LoxImpl *impl, const Box &prefix, Scope scope, threads::Thread *thread)
Definition loxpimpl.cpp:906
static void log(LoxImpl *impl, detail::Domain *dom, Verbosity verbosity, BoxesMA &logables, lang::Inclusion prefixes)
static void getAllVerbosities(LoxImpl *impl, variables::Variable &variable, detail::Logger *logger, detail::Domain &dom)
static void once(LoxImpl *impl, const NString &domain, Verbosity verbosity, const Box &logables, const String &pGroup, Scope scope, int quantity)
static void SetSourcePathTrimRule(LoxImpl *impl, const NCString &path, lang::Inclusion includeString, int trimOffset, lang::Case sensitivity, const NString &trimReplacement, lang::Reach reach, Priority priority)
Definition loxpimpl.cpp:397
static void Entry(LoxImpl *impl, const NString &domain, Verbosity verbosity)
static void getDomainPrefixFromConfig(LoxImpl *impl, detail::Domain &dom)
static LoxImpl * Construct(const NString &name)
Definition loxpimpl.cpp:274
static void Acquire(LoxImpl *impl, const lang::CallerInfo &ci)
Definition loxpimpl.cpp:302
static void GetState(LoxImpl *impl, NAString &buf, StateInfo flags)
static MonoAllocator & DbgGetMonoAllocator(LoxImpl *impl)
Definition loxpimpl.cpp:394
static Box retrieve(LoxImpl *impl, const NString &pKey, Scope scope)
static void setDomain(LoxImpl *impl, const NString &scopeDomain, Scope scope, bool removeNTRSD, threads::Thread *thread)
Definition loxpimpl.cpp:759
static void dumpStateOnLoggerRemoval(LoxImpl *impl)
Definition loxpimpl.cpp:501
static detail::Logger * GetLogger(LoxImpl *impl, const NString &loggerName)
Definition loxpimpl.cpp:420
static threads::RecursiveLock & getLock(LoxImpl *impl)
Definition loxpimpl.cpp:295
static bool isThreadRelatedScope(LoxImpl *impl, Scope scope)
static void State(LoxImpl *impl, const NString &domain, Verbosity verbosity, const String &headLine, StateInfo flags)
static void MapThreadName(LoxImpl *impl, const String &threadName, threads::ThreadID id)
monomem::Snapshot beforeLox
Snapshot taken before embedding the lox in the #"monoAllocator".
Definition loxpimpl.cpp:140
ScopeStore< SSMap< int > *, false > scopeLogOnce
Log once counters.
Definition loxpimpl.cpp:181
Domain * internalDomains
The root domain for internal Log Domains.
Definition loxpimpl.cpp:172
T * newPO(TArgs &&... args)
Definition loxpimpl.cpp:257
ScopeInfo scopeInfo
Information about the source code, method, thread, etc. invoking a log call.
Definition loxpimpl.cpp:164
ScopeStore< NString, true > scopeDomains
Scope Domains.
Definition loxpimpl.cpp:175
PoolAllocator poolAllocator
A pool allocator that uses #"monoAllocator" as its source.
Definition loxpimpl.cpp:137
integer maxLoggerNameLength
Used for tabular output of logger lists.
Definition loxpimpl.cpp:187
int CountAcquirements() const noexcept
Definition loxpimpl.cpp:248
const NString noKeyHashKey
A key value used in stores if no key is given (global object).
Definition loxpimpl.cpp:193
bool oneTimeWarningCircularDS
Flag if a warning on circular rule detection was logged.
Definition loxpimpl.cpp:200
StdVectorMA< BoxesMA * > internalLogables
A list of a list of logables used for (recursive) internal logging.
Definition loxpimpl.cpp:158
integer maxDomainPathLength
Used for tabular output of logger lists.
Definition loxpimpl.cpp:190
StdVectorMA< BoxesMA * > logableContainers
A list of a list of logables used for (recursive) logging.
Definition loxpimpl.cpp:155
ListMA< DomainSubstitutionRule > domainSubstitutions
The list of domain substitution rules.
Definition loxpimpl.cpp:197
MonoAllocator & monoAllocator
The self-contained monotonic allocator, that also contains this struct itself.
Definition loxpimpl.cpp:134
bool loggerAddedSinceLastDebugState
Flag used with configuration variable LOXNAME_DUMP_STATE_ON_EXIT.
Definition loxpimpl.cpp:203
int AcquirementsCount
Counts the number of nested (recursive) acquirements.
Definition loxpimpl.cpp:148
LoxImpl(MonoAllocator *ma, const NString &name)
Definition loxpimpl.cpp:209
ScopeStore< SSMap< Box > *, false > scopeLogData
Log data store.
Definition loxpimpl.cpp:184
ScopeStore< PrefixLogable *, true > scopePrefixes
Prefix logables store.
Definition loxpimpl.cpp:178
integer internalLogRecursionCounter
The recursion counter for internal logging.
Definition loxpimpl.cpp:161
threads::RecursiveLock Lock
A mutex to control parallel access.
Definition loxpimpl.cpp:144