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