/** ****************************************************************************************
         *  Converts the given unsigned 64 bit integer value to a string representation.<br>
         *  Negative numbers have to be converted to positive values when invoking this method.
         *  The maximum number of digits written are 20. The given buffer has to be large
         *  enough to receive the characters. The method does not check any overflow within the
         *  given character buffer.
         *
         *  \note This method is used internally by various AString conversion methods. It is
         *        advisable to use AString methods to convert integer values.
         *
         * @param value        The integer value to convert.
         * @param buffer       The character array to write the value to. Depending on the value
         *                     given, a maximum of 20 characters need to be allocated prior to
         *                     invoking this method.
         * @param idx          The index within the character array to write the value to.
         * @param minDigits    The minimum number of digits to append.
         *                     If given value has less digits, '0' characters are prepended.
         *                     The given value is cut to the range 1..20 (max digits of an
         *                     unsigned 64 bit integer).
         * @param sizeHint     The maximum number of digits found in the value. This is a hint
         *                     for optimizing the loop. If -1 is provided, the number is detected.
         *                     If a number is provided that is lower than the actual 'log10(value)',
         *                     the method produces unpredictable results.
         *
         * @return  The index of the new new end of the buffer.
         ******************************************************************************************/
        public int IntegerToString(ulong value, char[] buffer, int idx, int minDigits, int sizeHint)
        {
            // adjust minDigits to 1..20 and maxDigits to 1..minDigits
            if (minDigits < 1)
            {
                minDigits = 1;
            }
            if (minDigits > 20)
            {
                minDigits = 20;
            }
            if (sizeHint < minDigits)
            {
                sizeHint = minDigits;
            }
            if (sizeHint > 20)
            {
                sizeHint = 20;
            }

            int  actDigit     = sizeHint;
            bool printStarted = false;

            while (--actDigit >= 0)
            {
                // rest is zeros?
                if (value == 0)
                {
                    while (actDigit >= 0)
                    {
                        if (!(printStarted |= actDigit-- < minDigits))
                        {
                            continue;
                        }
                        buffer[idx++] = '0';
                    }
                    return(idx);
                }

                // get next d
                ulong actBase    = pow10_0to19[actDigit];
                int   digitValue = (int)(value / actBase);
                ALIB.ASSERT(digitValue <= 9);

                // did we hit i for the first time
                if (!(printStarted |= (digitValue != 0) || actDigit < minDigits))
                {
                    continue;
                }

                // print the digit
                buffer[idx++] = (char)(48 + digitValue); // 48= '0'

                // next
                value = value % actBase;
            }

            // return me for concatenated operations
            return(idx);
        }
Example #2
0
        public void Log_Threads()
        {
            UT_INIT();

            Log.AddDebugLogger();

            Log.SetDomain("TEST/THREAD1", Scope.Method);
            Log.SetVerbosity(Log.DebugLogger, Verbosity.Verbose, "TEST/THREAD1");

            // if this gets commented out, the test might crash. At least the console will
            // become scrambled!
            //Log.LOX.Lock.setUnsafe( true );

            Thread thread = new Thread(new ThreadStart(testDifferentThreadMethod))
            {
                Name = "Thread2"
            };

            thread.Start();

            for (int i = 0; i < 50; i++)
            {
                Log.Info("This is the main thread ");// + i );
                ALIB.SleepMillis(4);
            }
        }
        void SampleALibReport()
        {
            Console.WriteLine("Sample: ALib Report via using ALox");

            Log.AddDebugLogger();
            Log.SetDomain("/SAMPLE", Scope.Filename);
            Log.SetVerbosity(Log.DebugLogger, Verbosity.Info, "");
            Log.Info("Method \"Log.AddDebugLogger()\" by default creates a replacement for ALibs'\n"
                     + "error/warning reporter. If this is a debug compiliation, let's have a try and\n"
                     + "create 3 Messages:");

            Report.GetDefault().PushHaltFlags(false, false);
            ALIB.ERROR("This is an error report!");
            ALIB.WARNING("And this is a warning!");
            AString illegalAccess = new AString(10);

            illegalAccess._("1234");
            illegalAccess.SetCharAt_NC(5, '5');
            Report.GetDefault().PopHaltFlags();


            Log.SetVerbosity(Log.DebugLogger, Verbosity.Verbose, ALox.InternalDomains);
            ALIB.REPORT(2, "This is an ALib Report. Types other than '0' and '1' are user defined.\n"
                        + "Verbosity of ALox.InternalDomains has to be increased to see them when using"
                        + " ALoxReportWriter.");


            Log.Info("Note the domain prefix '" + ALox.InternalDomains.ToString() + "'. This addresses "
                     + "the tree of internal domains\nof the Lox, which the report writer is just "
                     + "using for ALib reports.");

            Log.RemoveDebugLogger();
        }
Example #4
0
        public void testDifferentThreadMethod()
        {
            Log.SetDomain("TEST/THREAD2", Scope.Method);
            Log.SetVerbosity(Log.DebugLogger, Verbosity.Verbose, "TEST/THREAD2");

            for (int i = 0; i < 20; i++)
            {
                Log.Info("This is a different Thread. Cnt= " + i);
                ALIB.SleepMillis(3);
            }
        }
Example #5
0
        /** ****************************************************************************************
         * This method must (may) be called prior to using the ALox library, e.g. at the beginning of
         * the main() method of an application. It is OK, to call this method more than once, which
         * allows independent code blocks (e.g. libraries) to bootstrap ALox without interfering.
         * But only the first call is effective and may be used to set the command line arguments
         * as configuration plug-in.
         *
         * In the C# version of the AWorx library, the invocation of this method is optional.
         * However, it is good practice to invoke this method in the main() method of a process
         * and provide the command line arguments. See \ref cs::aworx::lib::ALIB::Init "ALIB.Init"
         * for more information on the configuration parameters.
         *
         *  @param useEnv  If true, a
         *                 \ref cs::aworx::lib::config::EnvironmentPlugIn "EnvironmentPlugIn"
         *                 is attached to the
         *                 \ref cs::aworx::lib::ALIB::Config "ALIB.Config" singleton. Hence,
         *                 environment variables are read and potentially overwrite
         *                 configuration variables in other configuration plug-ins.<br>
         *                 Defaults to true.
         *  @param args    Parameter which in the standard case is taken from  C/C++ main()
         *                 method providing the command line arguments.
         *                 If arguments are provided, a
         *                 \ref cs::aworx::lib::config::CommandLinePlugIn "CommandLinePlugIn"
         *                 is attached to the
         *                 \ref cs::aworx::lib::ALIB::Config "ALIB.Config" singleton. Hence,
         *                 command line options are read and those potentially overwrite
         *                 configuration variables in other configuration plug-ins.<br>
         *                 Defaults to null.
         ******************************************************************************************/
        public static void     Init(bool useEnv = true, String[] args = null)
        {
            if (isInitialized)
            {
                return;
            }
            isInitialized = true;

            // initialize ALIB
            ALIB.Init(useEnv, args);
        }
        public bool RemovePlugin(ConfigurationPlugIn plugin)
        {
            for (int i = 0; i < plugins.Count; i++)
            {
                if (plugins[i].plugIn == plugin)
                {
                    plugin.Parent = null;
                    plugins.RemoveAt(i);
                    return(true);
                }
            }

            ALIB.WARNING("No Plug-in was removed ");
            return(false);
        }
Example #7
0
        public void ThreadLock_Threaded()
        {
            UT_INIT();

            Log.SetVerbosity(new ConsoleLogger(), Verbosity.Verbose, "/");
            Log.MapThreadName("UnitTest");
            Log.SetDomain("TestTLock", Scope.Filename);
            Log.SetVerbosity("CONSOLE", Verbosity.Verbose, "ALIB");

            ThreadLock aLock = new ThreadLock();

            Test_ThreadLock_SharedInt shared = new Test_ThreadLock_SharedInt();

            Log.Info("starting thread locked");
            aLock.Acquire();
            Test_ThreadLock_TestThreadParams tParam = new Test_ThreadLock_TestThreadParams(aLock, 10, 1, true, shared);

            Thread thread = new Thread(new ParameterizedThreadStart(Test_ThreadLock_Test_run));

            thread.Name = "A Thread";
            thread.Start(tParam);

            Log.Info("We wait 1100 ms. This should give a warning! ");
            ALIB.SleepMillis(1100);
            aLock.Release();

            // wait until t ended
            while (thread.IsAlive)
            {
                ALIB.SleepMillis(1);
            }

            // now we do the same with a higher wait limit, no erro should come
            aLock.waitWarningTimeLimitInMillis = 5;
            aLock.Acquire();
            tParam = new Test_ThreadLock_TestThreadParams(aLock, 10, 1, true, shared);
            thread = new Thread(new ParameterizedThreadStart(Test_ThreadLock_Test_run));
            thread.Start(tParam);
            Log.Info("We wait 1 ms. This should NOT give a warning! ");
            ALIB.SleepMillis(1);
            aLock.Release();

            // wait until t ended
            while (thread.IsAlive)
            {
                ALIB.SleepMillis(1);
            }
        }
Example #8
0
        /** ********************************************************************************************
         *  Releases ownership of this object. If Acquire() was called multiple times before, the same
         *  number of calls to this method have to be performed to release ownership.
         **********************************************************************************************/
        public void Release()
        {
            // are we in unsafe mode?
            if (mutex == null)
            {
                // not locked
                if (lockMode == LockMode.Recursive && lockCount == 0)
                {
                    ALIB.ERROR("Release() without Acquire() (unsafe mode). This must never happen, check your code, set lock to safe mode!");
                }

                // we are still decreasing the lockCount
                lockCount = lockMode == LockMode.Recursive  ? lockCount - 1
                                                        : 0;
                // end of unsafe version of this method
                return;
            }

            // synchronize on mutex
            lock ( mutex )
            {
                // not locked
                if (lockCount == 0)
                {
                    ALIB.ERROR("Release() without Acquire(). This must never happen, check your code!");
                }

                // decreasing the lockCount
                lockCount = lockMode == LockMode.Recursive ? lockCount - 1
                                                       : 0;

                // release and notify next waiting thread
                if (lockCount == 0)
                {
                    owner = null;
                    Monitor.Pulse(mutex);

                #if DEBUG
                    acquirementLineNumber = -1;
                    acquirementSourcefile = null;
                    acquirementMethodName = null;
                #endif
                }
            } // synchronized
        }
        // #############################################################################################
        // static entrance (Main)
        // #############################################################################################
        static void Main(string[] args)
        {
            ALIB.Init(true, args);


            // create us
            AloxSamples samples = new AloxSamples();

            // do some release logging tests.
            Console.WriteLine("PRINT: Debug logging:");
            samples.DebugLogging();
            ALoxSampleReset();

            // do some release logging tests.
            Console.WriteLine("PRINT: Release logging:");
            samples.ReleaseLogging();
            ALoxSampleReset();

            // do some performance tests.
            Console.WriteLine("PRINT: Performance test (debug logging):");
            samples.PerformanceTest();
            ALoxSampleReset();

            // do some performance tests.
            Console.WriteLine("PRINT: Performance test (release logging):");
            samples.PerformanceTestRL();
            ALoxSampleReset();

            // test class TextFileLogger
            Console.WriteLine("PRINT: test class TextFileLogger:");
            samples.TextFileLogger();
            ALoxSampleReset();

            // test class terminal test (colors and styles)
            Console.WriteLine("PRINT: Colors (depending on detected terminal):");
            samples.ColorTest();
            ALoxSampleReset();

            Console.WriteLine("PRINT: Thats it!");

            // sample ALib report facility through ALox
            samples.SampleALibReport();

            ALIB.TerminationCleanUp();
        }
Example #10
0
        public void ThreadLock_HeavyLoad()
        {
            UT_INIT();
            Log.SetVerbosity(new ConsoleLogger(), Verbosity.Verbose, "/");
            Log.MapThreadName("UnitTest");
            Log.SetDomain("TestTLock", Scope.Filename);

            ThreadLock aLock = new ThreadLock();

            // uncomment this for unsafe mode
            // lock.setUnsafe( true );

            Test_ThreadLock_SharedInt shared = new Test_ThreadLock_SharedInt();
            int  holdTime = 0;
            int  repeats  = 5000;
            bool verbose  = false;

            Test_ThreadLock_TestThreadParams p1 = new Test_ThreadLock_TestThreadParams(aLock, holdTime, repeats, verbose, shared);
            Test_ThreadLock_TestThreadParams p2 = new Test_ThreadLock_TestThreadParams(aLock, holdTime, repeats, verbose, shared);
            Test_ThreadLock_TestThreadParams p3 = new Test_ThreadLock_TestThreadParams(aLock, holdTime, repeats, verbose, shared);

            Log.Info("starting three threads");

            Thread t1 = new Thread(new ParameterizedThreadStart(Test_ThreadLock_Test_run));
            Thread t2 = new Thread(new ParameterizedThreadStart(Test_ThreadLock_Test_run));
            Thread t3 = new Thread(new ParameterizedThreadStart(Test_ThreadLock_Test_run));

            t1.Start(p1);
            t2.Start(p2);
            t3.Start(p3);

            // wait until all ended
            while (t1.IsAlive || t2.IsAlive || t3.IsAlive)
            {
                ALIB.SleepMillis(1);
            }

            Log.Info("All threads ended. Shared value=" + shared.val);

            UT_TRUE(shared.val == 0);
        }
Example #11
0
        /** ********************************************************************************************
         *  If parameter is true, the whole locking system is disabled. The only objective here is to
         *  to gain execution speed, as thread synchronization causes relatively expensive system calls.
         *  Use this method only if you are 100% sure that your (otherwise) critical section are executed
         *  in a single threaded environment. And: "relative expensive" means: they are not really
         *  expensive. This is provided only for the rare case that your critical section is very,
         *  very frequently executed.
         *
         * @param safeness  Determines if this object should use a mutex (\c Safeness.Safe)
         *                  or just do nothing (\c Safeness.Unsafe).
         *************************************************************************************************/
        public void SetSafeness(Safeness safeness)
        {
            // are we in unsafe mode?
            if (mutex == null)
            {
                // already locked? ALIB Error
                if (lockCount != 0)
                {
                    ALIB.ERROR("Cannot switch safeness mode while already locked. Current mode: unsafe, requested mode: "
                               + safeness.ToString());
                    return;
                }

                //  switch on?
                if (safeness == Safeness.Safe)
                {
                    mutex = new Object();
                }

                // end of unsafe version of this method
                return;
            }

            // synchronize on mutex
            lock ( mutex )
            {
                // already locked? ALIB Error
                if (owner != null)
                {
                    ALIB.ERROR("Cannot switch safeness mode while already locked. Current mode: safe, requested mode: "
                               + safeness.ToString());
                    return;
                }

                //  switch off?
                if (safeness == Safeness.Unsafe)
                {
                    mutex = null;
                }
            }
        }
        public void InsertPlugin(ConfigurationPlugIn plugin, int priority)
        {
            int i;

            for (i = 0; i < plugins.Count; i++)
            {
                ALIB.ASSERT_ERROR(plugins[i].prio != priority,
                                  "Configuration.InsertPlugin(): Plug-in with same priority exists");

                if (plugins[i].prio < priority)
                {
                    break;
                }
            }

            PluginAndPrio pap = new PluginAndPrio();

            pap.plugIn = plugin;
            pap.prio   = priority;
            plugins.Insert(i, pap);

            plugin.Parent = this;
        }
Example #13
0
        public void Test_ThreadLock_Test_run(Object o)
        {
            Test_ThreadLock_TestThreadParams p = o as Test_ThreadLock_TestThreadParams;

            for (int i = 0; i < p.repeats; i++)
            {
                if (p.verbose)
                {
                    Log.Info("Thread: " + Thread.CurrentThread.Name + " acuiring lock...");
                }
                p.aLock.Acquire();
                if (p.verbose)
                {
                    Log.Info("Thread: " + Thread.CurrentThread.Name + " has lock.");
                }

                int sVal = ++p.shared.val;

                ALIB.SleepMillis(p.holdTime);

                p.shared.val = sVal - 1;

                if (p.verbose)
                {
                    Log.Info("Thread: " + Thread.CurrentThread.Name + " releasing lock.");
                }
                p.aLock.Release();
                if (p.verbose)
                {
                    Log.Info("Thread: " + Thread.CurrentThread.Name + " released lock.");
                }
            }

            p.result = 0;
            Log.Info("Thread: " + Thread.CurrentThread.Name + " terminates.");
        }
Example #14
0
        void     Register(Lox lox, ContainerOp operation)
        {
            try { ALIB.Lock.Acquire();

                  // check
                  if (lox == null)
                  {
                      ALIB.ERROR("null given");
                      return;
                  }

                  // remove
                  if (operation == ContainerOp.Remove)
                  {
                      if (!loxes.Remove(lox))
                      {
                          ALIB.WARNING("A lox named \"" + lox.GetName()
                                       + "\" could not be found for removal.");
                      }
                  }

                  // insert
                  else
                  {
                      foreach (Lox it in loxes)
                      {
                          if (it.GetName().Equals(lox.GetName( )))
                          {
                              ALIB.ERROR("A lox named \"" + lox.GetName()
                                         + "\" was already registered. Registration ignored");
                              return;
                          }
                      }
                      loxes.Add(lox);
                  } } finally { ALIB.Lock.Release(); }
        }
Example #15
0
        // #############################################################################################
        // Interface
        // #############################################################################################


        /** ********************************************************************************************
         *  Thread which invokes this method gets registered  as the current owner of this object, until the
         *  same thread releases the ownership invoking Release().
         *  In the case that this object is already owned by another thread, the invoking thread is suspended
         *  until ownership can be gained.
         *  Multiple (nested) calls to this method are counted and the object is only released when the same
         *  number of Release() calls have been made.
         *
         * @param cln (Optional) Caller info, compiler generated. Please omit.
         * @param csf (Optional) Caller info, compiler generated. Please omit.
         * @param cmn (Optional) Caller info, compiler generated. Please omit.
         **********************************************************************************************/
        public void Acquire(
            [CallerLineNumber] int cln = 0, [CallerFilePath] String csf = "", [CallerMemberName] String cmn = "")

        {
            // are we in unsafe mode?
            if (mutex == null)
            {
                // we are still increasing the lockCount
                lockCount = lockMode == LockMode.Recursive ? lockCount + 1
                                                       : 1;

                // reached warning limit
                if (lockCount <= 0)
                {
                    ALIB.ERROR("Unsafe mode: Counter invalid (<= 0): This should never happen. Set lock to safe mode!");
                }

                else if (lockCount % RecursionWarningThreshold == 0)
                {
                    ALIB.WARNING("Recursion depth " + lockCount + ". To prevent this, change ThreadSafe.recursionWarningThreshold or fix your code!");
                }

                // end of unsafe version of this method
                return;
            }

            // get current thread
            Thread thisThread = Thread.CurrentThread;

            // synchronize on mutex
            lock ( mutex )
            {
                // we already own the thread
                if (owner == thisThread)
                {
                    // we are still increasing the lockCount
                    lockCount = lockMode == LockMode.Recursive ? lockCount + 1
                                                           : 1;
                    // reached warning limit
                    if (lockCount % RecursionWarningThreshold == 0)
                    {
                        ALIB.WARNING("Recursion depth " + lockCount + ". To prevent this, change ThreadSafe.recursionWarningThreshold or fix your code!");
                    }

                    return;
                }

                // we do not own this thread, wait until lock is free
                bool hasWarned = false;
                while (owner != null)
                {
                    try
                    {
                        // wait unconditional
                        if (waitWarningTimeLimitInMillis <= 0 || hasWarned)
                        {
                            Monitor.Wait(mutex);
                        }

                        // wait with time limit
                        else
                        {
                            waitTime.Set();
                            Monitor.Wait(mutex, waitWarningTimeLimitInMillis);
                            long time = waitTime.Age().InMillis();
                            if (time >= waitWarningTimeLimitInMillis)
                            {
                                hasWarned = true;
                                ALIB.WARNING("Timeout (" + waitWarningTimeLimitInMillis
                                             + " ms). Change your codes critical section length if possible." + CString.NewLineChars
                                             + "This thread: " + thisThread.ManagedThreadId + "/" + thisThread.Name + CString.NewLineChars
                                             + "Owning thread: " + (owner != null ? (owner.ManagedThreadId + "/" + owner.Name) : "null")
                                    #if DEBUG
                                             + CString.NewLineChars
                                             + "Location of acquirement: " + acquirementSourcefile + ":" + acquirementLineNumber + " " + acquirementMethodName + "()"
                                    #endif
                                             );
                            }
                        }
                    }
                    catch (Exception) {} // ignore spurious wakeups
                }

                // take control
                owner = thisThread;
            #if DEBUG
                acquirementLineNumber = cln;
                acquirementSourcefile = csf;
                acquirementMethodName = cmn;
            #endif

                lockCount = 1;
            } // synchronized
        }
        // #############################################################################################
        // logText
        // #############################################################################################

        /** ********************************************************************************************
         *
         *  The implementation of the abstract method of parent class TextLogger. Logs messages to the
         *  application console and/or the VStudio output window.
         *
         * @param domain      The <em>Log Domain</em>.
         * @param verbosity   The verbosity. This has been checked to be active already on this
         *                    stage and is provided to be able to be logged out only.
         * @param msg         The log message
         * @param scope       Information about the scope of the <em>Log Statement</em>..
         * @param lineNumber  The line number of a multi-line message, starting with 0. For
         *                    single line messages this is -1.
         **********************************************************************************************/
        override protected void logText(Domain domain, Verbosity verbosity,
                                        AString msg,
                                        ScopeInfo scope, int lineNumber)
        {
            // loop over message, print the parts between the escape sequences
            Tokenizer msgParts = new Tokenizer(msg, '\x001B');
            Substring actual   = msgParts.Actual;
            Substring rest     = msgParts.Rest;
            int       column   = 0;

            for (;;)
            {
                msgParts.Next(Whitespaces.Keep);

                // check if this is an ANSI sequence already
                if (rest.CharAtStart() == '[')
                {
                    // read the 'm'
                    int idx = rest.IndexOf('m');

                    if (idx < 0) // unknown ANSI Code
                    {
                        ALIB.WARNING("Unknown ANSI ESC Code ");
                        textWriter.Write(actual.Buf, actual.Start, actual.Length());
                        continue;
                    }

                    column += actual.Length();

                    actual.End  = rest.Start + idx;
                    rest.Start += idx + 1;

                    textWriter.Write(actual.Buf, actual.Start, actual.Length());

                    continue;
                }
                else
                {
                    if (actual.IsNotEmpty())
                    {
                        textWriter.Write(actual.Buf, actual.Start, actual.Length());
                        column += actual.Length();
                    }
                }

                // end of loop?
                if (!msgParts.HasNext())
                {
                    break;
                }

                // found an ESC sequence
                char c = rest.Consume();

                // Colors
                bool isForeGround = true;
                if (c == 'C' || c == 'c')
                {
                    isForeGround = c == 'c';

                    c = rest.Consume();
                    int colNo = c - '0';
                    ALIB.ASSERT_WARNING(colNo >= 0 && colNo <= 9, "Unknown ESC-c code");

                    // add bg
                    colNo += isForeGround ? 0 : 10;

                    // add light
                    colNo += (isForeGround ? !IsBackgroundLight : IsBackgroundLight)  ? 20 : 0;

                    textWriter.Write(ansiCols[colNo]);
                }

                // Styles
                else if (c == 's')
                {
                    // bold/italics style not supported in Windows console

                    // reset all
                    if (rest.Consume() == 'a')
                    {
                        textWriter.Write(ANSI_RESET);
                    }
                }

                // auto tab / end of meta
                else if (c == 't' || c == 'A')
                {
                    bool endOfMeta = c == 'A';
                    c = rest.Consume();
                    int extraSpace = c >= '0' && c <= '9' ? (int)(c - '0')
                                                      : (int)(c - 'A') + 10;

                    int tabStop = AutoSizes.Next(column, extraSpace);

                    Util.WriteSpaces(textWriter, tabStop - column);
                    column = tabStop;

                    if (endOfMeta)
                    {
                        String msgPrefix;
                        switch (verbosity)
                        {
                        case lox.Verbosity.Verbose:   msgPrefix = MsgPrefixVerbose;     break;

                        case lox.Verbosity.Info:      msgPrefix = MsgPrefixInfo;        break;

                        case lox.Verbosity.Warning:   msgPrefix = MsgPrefixWarning;     break;

                        case lox.Verbosity.Error:     msgPrefix = MsgPrefixError;       break;

                        default:                  msgPrefix = "";                   break;
                        }
                        textWriter.Write(msgPrefix);
                    }
                }

                // Link (we just colorize links here)
                else if (c == 'l')
                {
                    textWriter.Write(rest.Consume() == 'S'
                                       ?  (IsBackgroundLight ? ANSI_LIGHT_BLUE : ANSI_LIGHT_BLUE)
                                       :  ANSI_STD_COL);
                }

                else
                {
                    ALIB.WARNING("Unknown ESC code");
                }
            } // write loop


            textWriter.WriteLine(MsgSuffix);
        }
        public void Log_Data()
        {
            UT_INIT();

            Log.AddDebugLogger();
            Log.SetVerbosity(Log.DebugLogger, Verbosity.Verbose, ALox.InternalDomains);
            Log.SetDomain("Data", Scope.Method);

            // LogData Constructors
            {
                LogData ld;
                AString asnull = new AString();
                ld = new LogData(              ); UT_EQ(asnull, ld.StringValue); UT_EQ(0, ld.IntegerValue); UT_TRUE(ld.ObjectValue == null);
                ld = new LogData(3); UT_EQ(asnull, ld.StringValue); UT_EQ(3, ld.IntegerValue); UT_TRUE(ld.ObjectValue == null);
                ld = new LogData(3, this); UT_EQ(asnull, ld.StringValue); UT_EQ(3, ld.IntegerValue); UT_TRUE(ld.ObjectValue == this);
                ld = new LogData("ABC"); UT_EQ("ABC", ld.StringValue); UT_EQ(0, ld.IntegerValue); UT_TRUE(ld.ObjectValue == null);
                ld = new LogData("ABC", 0, this); UT_EQ("ABC", ld.StringValue); UT_EQ(0, ld.IntegerValue); UT_TRUE(ld.ObjectValue == this);
                ld = new LogData("ABC", 3); UT_EQ("ABC", ld.StringValue); UT_EQ(3, ld.IntegerValue); UT_TRUE(ld.ObjectValue == null);
                ld = new LogData("ABC", 3, this); UT_EQ("ABC", ld.StringValue); UT_EQ(3, ld.IntegerValue); UT_TRUE(ld.ObjectValue == this);
            }

            // without key
            Log.Store(null, Scope.Global);
            Log.Store(new LogData("Replaced"), Scope.Global);
            Log.Store(null, Scope.Global);
            Log.Store(null, Scope.Global);
            Log.Store(new LogData("Replaced"), Scope.Global);
            Log.Store(new LogData("Global"), Scope.Global);
            Log.Store(new LogData("Replaced"), Scope.ThreadOuter);
            Log.Store(new LogData("ThreadOuter"), Scope.ThreadOuter);
            Log.Store(new LogData("Replaced"), Scope.Path, 1);
            Log.Store(new LogData("Path1"), Scope.Path, 1);
            Log.Store(new LogData("Replaced"), Scope.Path);
            Log.Store(new LogData("Path"), Scope.Path);
            Log.Store(new LogData("Replaced"), Scope.Filename);
            Log.Store(new LogData("FileName"), Scope.Filename);
            Log.Store(new LogData("Replaced"), Scope.Method);
            Log.Store(new LogData("Method"), Scope.Method);
            Log.Store(new LogData("Replaced"), Scope.ThreadInner);
            Log.Store(new LogData("ThreadInner"), Scope.ThreadInner);

            LogData data = null;

            data = Log.Retrieve(Scope.Global); UT_EQ("Global", data.StringValue);
            data = Log.Retrieve(Scope.ThreadOuter); UT_EQ("ThreadOuter", data.StringValue);
            data = Log.Retrieve(Scope.Path, 1); UT_EQ("Path1", data.StringValue);
            data = Log.Retrieve(Scope.Path); UT_EQ("Path", data.StringValue);
            data = Log.Retrieve(Scope.Filename); UT_EQ("FileName", data.StringValue);
            data = Log.Retrieve(Scope.Method); UT_EQ("Method", data.StringValue);
            data = Log.Retrieve(Scope.ThreadInner); UT_EQ("ThreadInner", data.StringValue);

            // wit key
            Log.Store(new LogData("Replaced"), "mykey", Scope.Global);
            Log.Store(new LogData("Global"), "mykey", Scope.Global);
            Log.Store(new LogData("Replaced"), "mykey", Scope.ThreadOuter);
            Log.Store(new LogData("ThreadOuter"), "mykey", Scope.ThreadOuter);
            Log.Store(new LogData("Replaced"), "mykey", Scope.Path, 1);
            Log.Store(new LogData("Path1"), "mykey", Scope.Path, 1);
            Log.Store(new LogData("Replaced"), "mykey", Scope.Path);
            Log.Store(new LogData("Path"), "mykey", Scope.Path);
            Log.Store(new LogData("Replaced"), "mykey", Scope.Filename);
            Log.Store(new LogData("FileName"), "mykey", Scope.Filename);
            Log.Store(new LogData("Replaced"), "mykey", Scope.Method);
            Log.Store(new LogData("Method"), "mykey", Scope.Method);
            Log.Store(new LogData("Replaced"), "mykey", Scope.ThreadInner);
            Log.Store(new LogData("ThreadInner"), "mykey", Scope.ThreadInner);


            data = Log.Retrieve("mykey", Scope.Global); UT_EQ("Global", data.StringValue);
            data = Log.Retrieve("mykey", Scope.ThreadOuter); UT_EQ("ThreadOuter", data.StringValue);
            data = Log.Retrieve("mykey", Scope.Path, 1); UT_EQ("Path1", data.StringValue);
            data = Log.Retrieve("mykey", Scope.Path); UT_EQ("Path", data.StringValue);
            data = Log.Retrieve("mykey", Scope.Filename); UT_EQ("FileName", data.StringValue);
            data = Log.Retrieve("mykey", Scope.Method); UT_EQ("Method", data.StringValue);
            data = Log.Retrieve("mykey", Scope.ThreadInner); UT_EQ("ThreadInner", data.StringValue);


            // threaded
            Log.Store(new LogData("Main Thread Data"), Scope.ThreadOuter);
            Log.Store(new LogData("Main Thread Data, keyed"), "mykey", Scope.ThreadOuter);


            Thread thread = new Thread(new ThreadStart(StoreDataTestThreadRun));

            thread.Start();
            while (thread.IsAlive)
            {
                ;
            }
            ALIB.SleepMicros(1);

            data = Log.Retrieve(Scope.ThreadOuter); UT_EQ("Main Thread Data", data.StringValue);
            data = Log.Retrieve("mykey", Scope.ThreadOuter); UT_EQ("Main Thread Data, keyed", data.StringValue);
        }
        public void Log_LogOnce()
        {
            UT_INIT();

            Log.AddDebugLogger();
            MemoryLogger ml = new MemoryLogger();

            Log.SetVerbosity(ml, Verbosity.Verbose);
            Log.SetVerbosity(Log.DebugLogger, Verbosity.Verbose, ALox.InternalDomains);
            Log.SetDomain("ONCE", Scope.Method);

            //-------------------- associated to scope method-----------------
            for (int i = 0; i < 5; i++)
            {
                Log.Once(Verbosity.Info, "Once(Scope method) 1x", Scope.Method);
            }
            Log.Once(Verbosity.Info, "Once(Scope method) 1x", Scope.Method);

            UT_EQ(1, ml.CntLogs); ml.CntLogs = 0;


            //-------------------- associated to scope filename -----------------
            for (int i = 0; i < 5; i++)
            {
                Log.Once("Subdom", Verbosity.Info, "Once(Scope filename) 4x", Scope.Filename, 0, 4);
                logOnceMethod();
            }
            Log.Once(Verbosity.Info, "Once(Scope filename) 4x", Scope.Filename, 0, 4);

            UT_EQ(4, ml.CntLogs); ml.CntLogs = 0;

            //-------------------- associated to scope thread -----------------
            Log.Once(Verbosity.Info, "Once(Scope.ThreadOuter) 2x - main thread", Scope.ThreadOuter, 0, 2);
            UT_EQ(1, ml.CntLogs); ml.CntLogs = 0;
            Thread thread = new Thread(new ThreadStart(LogOnceTestThreadRun));

            thread.Start();
            while (thread.IsAlive)
            {
                ;
            }
            ALIB.SleepMicros(1);
            UT_EQ(2, ml.CntLogs); ml.CntLogs = 0;
            Log.Once(Verbosity.Info, "Once(Scope.ThreadOuter) 2x - main thread", Scope.ThreadOuter, 0, 2);
            UT_EQ(1, ml.CntLogs); ml.CntLogs = 0;
            Log.Once(Verbosity.Info, "Once(Scope.ThreadOuter) 2x - main thread", Scope.ThreadOuter, 0, 2);
            UT_EQ(0, ml.CntLogs); ml.CntLogs = 0;
            Log.Once(Verbosity.Info, "Once(Scope.ThreadOuter) 2x - main thread", Scope.ThreadOuter, 0, 2);
            UT_EQ(0, ml.CntLogs); ml.CntLogs = 0;

            // different group
            Log.Once("Once(group, Scope.ThreadOuter) 2x - main thread", "group", Scope.ThreadOuter, 0, 1);
            UT_EQ(1, ml.CntLogs); ml.CntLogs = 0;
            Log.Once("Once(group, Scope.ThreadOuter) 2x - main thread", "group", Scope.ThreadOuter, 0, 1);
            UT_EQ(0, ml.CntLogs); ml.CntLogs = 0;

            //-------------------- associated to line (using group interface)  -----------------
            for (int i = 0; i < 5; i++)
            {
                Log.Once(Verbosity.Info, "Once(line) 1x");
            }
            UT_EQ(1, ml.CntLogs); ml.CntLogs = 0;

            for (int i = 0; i < 5; i++)
            {
                Log.Once(Verbosity.Info, "Once(line other) 2x", "", 2);
            }
            UT_EQ(2, ml.CntLogs); ml.CntLogs = 0;

            for (int i = 0; i < 5; i++)
            {
                Log.Once(Verbosity.Info, "Once(line other) 1x", "", 1);
            }
            UT_EQ(1, ml.CntLogs); ml.CntLogs = 0;

            for (int i = 0; i < 5; i++)
            {
                Log.Once(Verbosity.Info, "Once(line other) 0x", "", 0);
            }
            UT_EQ(0, ml.CntLogs); ml.CntLogs = 0;

            for (int i = 0; i < 5; i++)
            {
                Log.Once("Once(line) Just msg and number", 2);
            }
            UT_EQ(2, ml.CntLogs); ml.CntLogs = 0;

            for (int i = 0; i < 5; i++)
            {
                Log.Once("Once(line) Just msg ");
            }
            UT_EQ(1, ml.CntLogs); ml.CntLogs = 0;

            //-------------------- associated to group -----------------
            for (int i = 0; i < 5; i++)
            {
                Log.Once(Verbosity.Info, "Once(\"a group\") 1x", "a group");
            }
            UT_EQ(1, ml.CntLogs); ml.CntLogs = 0;
            Log.Once(Verbosity.Info, "Once(\"a group\") 1x but tricked up", "a group", 2);
            UT_EQ(1, ml.CntLogs); ml.CntLogs = 0;


            Log.Once(Verbosity.Info, "Once(\"a group\") 1x", "a group");
            UT_EQ(0, ml.CntLogs); ml.CntLogs = 0;

            Log.Once(Verbosity.Info, "Once(\"b group\") 1x", "b group");
            UT_EQ(1, ml.CntLogs); ml.CntLogs = 0;

            Log.Once(Verbosity.Info, "Once(\"b group\") 1x", "b group");
            UT_EQ(0, ml.CntLogs); ml.CntLogs = 0;

            Log.Once(Verbosity.Info, "Once(\"c group\") 2x", "c group", 2);
            UT_EQ(1, ml.CntLogs); ml.CntLogs = 0;

            Log.Once(Verbosity.Info, "Once(\"c group\") 2x", "c group", 2);
            UT_EQ(1, ml.CntLogs); ml.CntLogs = 0;

            Log.Once(Verbosity.Info, "Once(\"c group\") 2x", "c group", 2);
            UT_EQ(0, ml.CntLogs); ml.CntLogs = 0;

            Log.Once(Verbosity.Info, "Once(\"a group\") 1x", "a group");
            UT_EQ(0, ml.CntLogs); ml.CntLogs = 0;

            Log.Once(Verbosity.Info, "Once(\"b group\") 1x", "b group");
            UT_EQ(0, ml.CntLogs); ml.CntLogs = 0;

            Log.Once(Verbosity.Info, "Once(\"c group\") 2x", "c group", 2);
            UT_EQ(0, ml.CntLogs); ml.CntLogs = 0;

            // AString
            Log.Once(new AString("Once with AString"));
            UT_EQ(1, ml.CntLogs); ml.CntLogs = 0;


            //-------------------- Log every Nth -----------------
            for (int i = 0; i < 10; i++)
            {
                Log.Once(Verbosity.Info, "Every 2nd ", -2);
            }
            UT_EQ(5, ml.CntLogs); ml.CntLogs = 0;

            for (int i = 0; i < 10; i++)
            {
                Log.Once(Verbosity.Info, "Every 3rd ", -3);
            }

            UT_EQ(4, ml.CntLogs); ml.CntLogs = 0;
        }
        public void Lox_ScopeDomains()
        {
            UT_INIT();

            // we have tell alox to include more directories in the scope path
            Log.ClearSourcePathTrimRules(Inclusion.Include, false);
            Log.SetSourcePathTrimRule("*/alox/src.cs/", Inclusion.Exclude);

            Lox          lox           = new Lox("ReleaseLox");
            TextLogger   consoleLogger = Lox.CreateConsoleLogger();
            MemoryLogger ml            = new MemoryLogger();

            ml.MetaInfo.Format._()._("@%D#");
            lox.SetVerbosity(ml, Verbosity.Verbose);

            lox.SetVerbosity(consoleLogger, Verbosity.Verbose);
            lox.SetVerbosity(consoleLogger, Verbosity.Verbose, ALox.InternalDomains);

            // scope global
            lox.SetDomain("REPLACE", Scope.Global);  lox.Info("", ""); SDCHECK_RL("@/REPLACE#", ml);
            lox.SetDomain("GLOBAL", Scope.Global);  lox.Info("", ""); SDCHECK_RL("@/GLOBAL#", ml);

            lox.SetDomain(null, Scope.Global);  lox.Info("", ""); SDCHECK_RL("@/#", ml);

            // scope source
            lox.SetDomain("REPLACE", Scope.Filename);  lox.Info("", ""); CICHECK_RL("@/REPLACE#", ml);
            lox.SetDomain("FILE", Scope.Filename);  lox.Info("", ""); CICHECK_RL("@/FILE#", ml);

            // scope method
            lox.SetDomain("REPLACE", Scope.Method);  lox.Info("", ""); CICHECK_RL("@/FILE/REPLACE#", ml);
            lox.SetDomain("Method", Scope.Method);  lox.Info("", ""); CICHECK_RL("@/FILE/METHOD#", ml);
            lox.SetDomain("/ABS", Scope.Method);  lox.Info("", ""); CICHECK_RL("@/ABS#", ml);

            // unset method with null
            lox.SetDomain(null, Scope.Method);  lox.Info("", ""); CICHECK_RL("@/FILE#", ml);

            // unset method with ""
            lox.SetDomain("/METHOD", Scope.Method);  lox.Info("", ""); CICHECK_RL("@/METHOD#", ml);
            lox.SetDomain("", Scope.Method);  lox.Info("", ""); CICHECK_RL("@/FILE#", ml);
            lox.SetDomain("Method", Scope.Method);  lox.Info("", ""); CICHECK_RL("@/FILE/METHOD#", ml);

            // source path
            lox.SetDomain("REPLACE", Scope.Path);  lox.Info("", ""); CICHECK_RL("@/REPLACE/FILE/METHOD#", ml);
            lox.SetDomain("PATH", Scope.Path);  lox.Info("", ""); CICHECK_RL("@/PATH/FILE/METHOD#", ml);
            lox.SetDomain("REPLACE", Scope.Path, 1);  lox.Info("", ""); CICHECK_RL("@/REPLACE/PATH/FILE/METHOD#", ml);
            lox.SetDomain("PO1", Scope.Path, 1);  lox.Info("", ""); CICHECK_RL("@/PO1/PATH/FILE/METHOD#", ml);
            lox.SetDomain("REPLACE", Scope.Path, 2);  lox.Info("", ""); CICHECK_RL("@/REPLACE/PO1/PATH/FILE/METHOD#", ml);
            lox.SetDomain("PO2", Scope.Path, 2);  lox.Info("", ""); CICHECK_RL("@/PO2/PO1/PATH/FILE/METHOD#", ml);

            lox.SetDomain("GLOBAL", Scope.Global);  lox.Info("", ""); CICHECK_RL("@/GLOBAL/PO2/PO1/PATH/FILE/METHOD#", ml);


            // remove all previous scope domains
            lox.SetDomain("", Scope.Global);
            lox.SetDomain("", Scope.Path);
            lox.SetDomain("", Scope.Path, 1);
            lox.SetDomain("", Scope.Path, 2);
            lox.SetDomain("", Scope.Filename);
            lox.SetDomain("", Scope.Method);  lox.Info("LOC", ""); SDCHECK_RL("@/LOC#", ml);

            // Thread-related
            lox.SetDomain("T_O", Scope.ThreadOuter);  lox.Info("", ""); SDCHECK_RL("@/T_O#", ml);
            lox.SetDomain("GL", Scope.Global);  lox.Info("", ""); SDCHECK_RL("@/GL/T_O#", ml);
            lox.SetDomain("MET", Scope.Method);  lox.Info("", ""); CICHECK_RL("@/GL/T_O/MET#", ml);
            lox.Info("LOC", ""); CICHECK_RL("@/GL/T_O/MET/LOC#", ml);
            lox.SetDomain("T_I", Scope.ThreadInner);  lox.Info("", ""); CICHECK_RL("@/GL/T_O/MET/T_I#", ml);
            lox.Info("LOC", ""); CICHECK_RL("@/GL/T_O/MET/LOC/T_I#", ml);
            lox.SetDomain("T_O2", Scope.ThreadOuter);  lox.Info("", ""); CICHECK_RL("@/GL/T_O/T_O2/MET/T_I#", ml);
            lox.SetDomain("T_I2", Scope.ThreadInner);  lox.Info("", ""); CICHECK_RL("@/GL/T_O/T_O2/MET/T_I/T_I2#", ml);

            lox.SetDomain("/T_O3", Scope.ThreadOuter);  lox.Info("", ""); CICHECK_RL("@/T_O3/MET/T_I/T_I2#", ml);
            lox.SetDomain("/T_I3", Scope.ThreadInner);  lox.Info("", ""); SDCHECK_RL("@/T_I3#", ml);
            lox.SetDomain("", Scope.Method);  lox.Info("", ""); SDCHECK_RL("@/T_I3#", ml);

            lox.SetDomain("", Scope.ThreadInner);  lox.Info("", ""); SDCHECK_RL("@/T_O3/T_I/T_I2#", ml);
            lox.RemoveThreadDomain("T_IXX", Scope.ThreadInner);  lox.Info("", ""); SDCHECK_RL("@/T_O3/T_I/T_I2#", ml);
            lox.RemoveThreadDomain("T_I", Scope.ThreadInner);  lox.Info("", ""); SDCHECK_RL("@/T_O3/T_I2#", ml);
            lox.RemoveThreadDomain("", Scope.ThreadInner);  lox.Info("", ""); SDCHECK_RL("@/T_O3/T_I2#", ml);
            lox.SetDomain("", Scope.ThreadInner);  lox.Info("", ""); SDCHECK_RL("@/T_O3#", ml);
            lox.SetDomain("", Scope.ThreadOuter);  lox.Info("", ""); SDCHECK_RL("@/GL/T_O/T_O2#", ml);
            lox.SetDomain("T_O3", Scope.ThreadOuter);  lox.Info("", ""); SDCHECK_RL("@/GL/T_O/T_O2/T_O3#", ml);
            lox.RemoveThreadDomain("T_O2", Scope.ThreadOuter);  lox.Info("", ""); SDCHECK_RL("@/GL/T_O/T_O3#", ml);
            lox.RemoveThreadDomain("T_O", Scope.ThreadOuter);  lox.Info("", ""); SDCHECK_RL("@/GL/T_O3#", ml);
            lox.SetDomain("", Scope.ThreadOuter);  lox.Info("", ""); SDCHECK_RL("@/GL#", ml);
            lox.SetDomain("", Scope.Global);  lox.Info("", ""); SDCHECK_RL("@/#", ml);


            // second thread
            Thread thread = new Thread(new ParameterizedThreadStart(DomainTestThreadRun_RL));

            lox.SetDomain("THIS_THREAD", Scope.ThreadOuter);
            lox.SetDomain("OTHER_THREAD", Scope.ThreadOuter, thread);
            thread.Start(lox);
            while (thread.IsAlive)
            {
                ALIB.SleepMillis(1);
            }
            UT_EQ("@/OTHER_THREAD/DTT#", ml.MemoryLog);  ml.MemoryLog._(); ml.AutoSizes.Reset();
            lox.Info("ME", "");  UT_EQ("@/THIS_THREAD/ME#", ml.MemoryLog);  ml.MemoryLog._(); ml.AutoSizes.Reset();

            // cleanup
            lox.RemoveLogger(consoleLogger);
            lox.RemoveLogger(ml);
        }
        public void Log_ScopeDomains()
        {
            UT_INIT();

            // we have tell alox to include more directories in the scope path
            Log.ClearSourcePathTrimRules(Inclusion.Include, false);
            Log.SetSourcePathTrimRule("*/alox/src.cs/", Inclusion.Exclude);

            Log.AddDebugLogger();
            MemoryLogger ml = new MemoryLogger();

            ml.MetaInfo.Format._()._("@%D#");
            Log.SetVerbosity(ml, Verbosity.Verbose);
            Log.SetVerbosity(Log.DebugLogger, Verbosity.Verbose, ALox.InternalDomains);
            Log.SetDomain("REPLACE", Scope.Global);  Log.Info(""); SDCHECK("@/REPLACE#", ml);
            Log.SetDomain("GLOBAL", Scope.Global);  Log.Info(""); SDCHECK("@/GLOBAL#", ml);

            Log.SetDomain(null, Scope.Global);  Log.Info(""); SDCHECK("@/#", ml);

            // scope source
            Log.SetDomain("REPLACE", Scope.Filename);  Log.Info(""); SDCHECK("@/REPLACE#", ml);
            Log.SetDomain("FILE", Scope.Filename);  Log.Info(""); SDCHECK("@/FILE#", ml);

            // scope method
            Log.SetDomain("REPLACE", Scope.Method);  Log.Info(""); SDCHECK("@/FILE/REPLACE#", ml);
            Log.SetDomain("METHOD", Scope.Method);  Log.Info(""); SDCHECK("@/FILE/METHOD#", ml);
            Log.SetDomain("/ABS", Scope.Method);  Log.Info(""); SDCHECK("@/ABS#", ml);

            // unset method with null
            Log.SetDomain(null, Scope.Method);  Log.Info(""); SDCHECK("@/FILE#", ml);

            // unset method with ""
            Log.SetDomain("/METHOD", Scope.Method);  Log.Info(""); SDCHECK("@/METHOD#", ml);
            Log.SetDomain("", Scope.Method);  Log.Info(""); SDCHECK("@/FILE#", ml);
            Log.SetDomain("METHOD", Scope.Method);  Log.Info(""); SDCHECK("@/FILE/METHOD#", ml);

            // source path
            Log.SetDomain("REPLACE", Scope.Path);  Log.Info(""); SDCHECK("@/REPLACE/FILE/METHOD#", ml);
            Log.SetDomain("PATH", Scope.Path);  Log.Info(""); SDCHECK("@/PATH/FILE/METHOD#", ml);
            Log.SetDomain("REPLACE", Scope.Path, 1);  Log.Info(""); SDCHECK("@/REPLACE/PATH/FILE/METHOD#", ml);
            Log.SetDomain("PO1", Scope.Path, 1);  Log.Info(""); SDCHECK("@/PO1/PATH/FILE/METHOD#", ml);
            Log.SetDomain("REPLACE", Scope.Path, 2);  Log.Info(""); SDCHECK("@/REPLACE/PO1/PATH/FILE/METHOD#", ml);
            Log.SetDomain("PO2", Scope.Path, 2);  Log.Info(""); SDCHECK("@/PO2/PO1/PATH/FILE/METHOD#", ml);
            Log.SetDomain("PO50", Scope.Path, 50);  Log.Info(""); SDCHECK("@/PO50/PO2/PO1/PATH/FILE/METHOD#", ml);

            Log.SetDomain("GLOBAL", Scope.Global);  Log.Info("");          SDCHECK("@/GLOBAL/PO50/PO2/PO1/PATH/FILE/METHOD#", ml);
            CS_ALox_domains_helper.help(); SDCHECK("@/GLOBAL/PO50/PO2/PO1/PATH/HFILE/HMETHOD#", ml);
            Log.Info("");        SDCHECK("@/GLOBAL/PO50/PO2/PO1/PATH/FILE/METHOD#", ml);

            //Log.LogConfig( "", Verbosity.Info, "Configuration now is:" ); ml.MemoryLog._(); ml.AutoSizes.Reset();

            // remove all previous scope domains
            Log.SetDomain("", Scope.Global);
            Log.SetDomain("", Scope.Path);
            Log.SetDomain("", Scope.Path, 1);
            Log.SetDomain("", Scope.Path, 2);
            Log.SetDomain("", Scope.Path, 45);      // same as 50 above! (test)
            Log.SetDomain("", Scope.Filename);
            Log.SetDomain("", Scope.Method);  Log.Info("LOC", ""); SDCHECK("@/LOC#", ml);

            // Thread-related
            Log.SetDomain("T_O", Scope.ThreadOuter);  Log.Info("", ""); SDCHECK("@/T_O#", ml);
            Log.SetDomain("GL", Scope.Global);  Log.Info("", ""); SDCHECK("@/GL/T_O#", ml);
            Log.SetDomain("MET", Scope.Method);  Log.Info("", ""); SDCHECK("@/GL/T_O/MET#", ml);
            Log.SetDomain("MET", Scope.Method);  Log.Info("LOC", ""); SDCHECK("@/GL/T_O/MET/LOC#", ml);
            Log.SetDomain("T_I", Scope.ThreadInner);  Log.Info("", ""); SDCHECK("@/GL/T_O/MET/T_I#", ml);

            Log.Info("LOC", ""); SDCHECK("@/GL/T_O/MET/LOC/T_I#", ml);
            Log.SetDomain("T_O2", Scope.ThreadOuter);  Log.Info("", ""); SDCHECK("@/GL/T_O/T_O2/MET/T_I#", ml);
            Log.SetDomain("T_I2", Scope.ThreadInner);  Log.Info("", ""); SDCHECK("@/GL/T_O/T_O2/MET/T_I/T_I2#", ml);

            Log.SetDomain("/T_O3", Scope.ThreadOuter);  Log.Info("", ""); SDCHECK("@/T_O3/MET/T_I/T_I2#", ml);
            Log.SetDomain("/T_I3", Scope.ThreadInner);  Log.Info("", ""); SDCHECK("@/T_I3#", ml);

            Log.SetDomain("", Scope.ThreadInner);  Log.Info("", ""); SDCHECK("@/T_O3/MET/T_I/T_I2#", ml);
            Log.RemoveThreadDomain("T_IXX", Scope.ThreadInner);  Log.Info("", ""); SDCHECK("@/T_O3/MET/T_I/T_I2#", ml);
            Log.RemoveThreadDomain("T_I", Scope.ThreadInner);  Log.Info("", ""); SDCHECK("@/T_O3/MET/T_I2#", ml);
            Log.RemoveThreadDomain("", Scope.ThreadInner);  Log.Info("", ""); SDCHECK("@/T_O3/MET/T_I2#", ml);
            Log.SetDomain("", Scope.ThreadInner);  Log.Info("", ""); SDCHECK("@/T_O3/MET#", ml);
            Log.SetDomain("", Scope.ThreadOuter);  Log.Info("", ""); SDCHECK("@/GL/T_O/T_O2/MET#", ml);
            Log.SetDomain("T_O3", Scope.ThreadOuter);  Log.Info("", ""); SDCHECK("@/GL/T_O/T_O2/T_O3/MET#", ml);
            Log.RemoveThreadDomain("T_O2", Scope.ThreadOuter);  Log.Info("", ""); SDCHECK("@/GL/T_O/T_O3/MET#", ml);
            Log.RemoveThreadDomain("T_O", Scope.ThreadOuter);  Log.Info("", ""); SDCHECK("@/GL/T_O3/MET#", ml);
            Log.SetDomain("", Scope.ThreadOuter);  Log.Info("", ""); SDCHECK("@/GL/MET#", ml);
            Log.SetDomain("", Scope.Global);  Log.Info("", ""); SDCHECK("@/MET#", ml);
            Log.SetDomain("", Scope.Method);  Log.Info("", ""); SDCHECK("@/#", ml);

            // second thread
            Thread thread = new Thread(new ThreadStart(DomainTestThreadRun));

            Log.SetDomain("THIS_THREAD", Scope.ThreadOuter);
            Log.SetDomain("OTHER_THREAD", Scope.ThreadOuter, thread);
            thread.Start();
            while (thread.IsAlive)
            {
                ALIB.SleepMillis(1);
            }
            UT_EQ("@/OTHER_THREAD/DTT#", ml.MemoryLog);  ml.MemoryLog._(); ml.AutoSizes.Reset();
            Log.Info("ME", "");  UT_EQ("@/THIS_THREAD/ME#", ml.MemoryLog);  ml.MemoryLog._(); ml.AutoSizes.Reset();
        }
Example #21
0
        /** ****************************************************************************************
         * Removes an acquirer.
         * @param acquirerToRemove The acquirer to remove.
         * @return The new number of \e acquirers set.
         ******************************************************************************************/
        public virtual int RemoveAcquirer(ThreadLock acquirerToRemove)
        {
            int  count          = 0;
            bool errNotFound    = true;
            bool errWasAcquired = false;

            try { ALIB.Lock.Acquire();

                #if DEBUG
                  errWasAcquired = DbgCountAcquirements() != 0;
                #endif

                  // search acquirer
                  if (acquirers.IndexOf(acquirerToRemove) >= 0)
                  {
                      errNotFound = false;

                      // switch off?
                      if (acquirers.Count == 2)
                      {
                          ThreadLock acquirer1 = acquirers[0];
                          ThreadLock acquirer2 = acquirers[1];
                          if (acquirer1 == acquirerToRemove)
                          {
                              acquirer1 = null;
                          }
                          if (acquirer2 == acquirerToRemove)
                          {
                              acquirer2 = null;
                          }

                          // Aquire acquirers in their order of appearance
                          if (acquirer1 != null)
                          {
                              acquirer1.Acquire();
                          }
                          if (acquirer2 != null)
                          {
                              acquirer2.Acquire();
                          }
                          SetSafeness(Safeness.Unsafe);
                          acquirers.Remove(acquirerToRemove);
                          if (acquirer2 != null)
                          {
                              acquirer2.Release();
                          }
                          if (acquirer1 != null)
                          {
                              acquirer1.Release();
                          }
                      }

                      // just remove acquirer, keep mode
                      else
                      {
                          acquirers.Remove(acquirerToRemove);
                      }
                  }

                  count = acquirers.Count; } finally { ALIB.Lock.Release(); }

            ALIB.ASSERT_ERROR(!errNotFound, "Acquirer not found.");
            ALIB.ASSERT_ERROR(!errWasAcquired, "Aquired on release. Hint: Acquirers must acquire only when acquired themselves!");
            return(count);
        }
Example #22
0
 /** ****************************************************************************************
  * Returns logger of given number.
  * @param no  The number of the \e Logger to return.
  * @return The the \e Logger found with number \p no.
  ******************************************************************************************/
 public Logger  GetLogger(int no)
 {
     ALIB.ASSERT_ERROR(no >= 0 && no < (int)Data.Count, "Internal error: Illegal Logger Number");
     return(Data[no].Logger);
 }
Example #23
0
        public void Ages()
        {
            UT_INIT();

            Log.SetVerbosity(new ConsoleLogger(), Verbosity.Verbose, "/");
            Log.MapThreadName("UnitTest");
            Log.SetDomain("TickWatch", Scope.Method);

            TickWatch tt = new TickWatch();
            // minimum time measuring
            {
                tt.Start();
                tt.Sample();
                tt.Reset(); // we need to do this once before, otherwise C# might be
                // very slow. Obviously the optimizer...
                tt.Start();
                tt.Sample();

                long ttAverageInNanos  = tt.GetAverage().InNanos();
                long ttAverageInMicros = tt.GetAverage().InMicros();
                long ttAverageInMillis = tt.GetAverage().InMillis();

                Log.Info("TickWatch minimum measurement nanos:    " + ttAverageInNanos);
                Log.Info("TickWatch minimum measurement micros:   " + ttAverageInMicros);
                Log.Info("TickWatch minimum measurement millis:   " + ttAverageInMillis);
                UT_TRUE(ttAverageInNanos < 5000);
                UT_TRUE(ttAverageInMicros <= 5);
                UT_TRUE(ttAverageInMillis == 0);
            }

            // minimum sleep time measuring
            {
                tt.Reset();
                for (int i = 0; i < 100; i++)
                {
                    ALIB.SleepNanos(1);
                    tt.Sample();
                }
                Ticks avg = tt.GetAverage();
                Log.Info("100 probes of 1 ns of sleep leads to average sleep time of " + avg.InNanos() + " ns");
            }


            // sleep two times 20 ms and probe it to an average
            {
                tt.Reset();
                tt.Start();
                ALIB.SleepMillis(20);
                tt.Sample();


                ALIB.SleepMillis(80);

                tt.Start();
                ALIB.SleepMillis(20);
                tt.Sample();

                long   cnt   = tt.GetSampleCnt();
                long   avg   = tt.GetAverage().InMillis();
                double hertz = tt.GetAverage().InHertz(1);
                Log.Info("TickWatch sum is " + tt.GetCumulated().InMillis() + " after " + cnt + " times 20 ms sleep");
                Log.Info("  average is: " + avg + " ms");
                Log.Info("  in Hertz:   " + hertz);
                UT_TRUE(hertz < 53);
                UT_TRUE(hertz > 30);   // should work even on heavily loaded machines
                UT_EQ(2, cnt);
                UT_TRUE(avg >= 18);
                UT_TRUE(avg < 45);   // should work even on heavily loaded machines
            }

            // Ticks Since
            {
                Ticks tt1 = new Ticks(); tt1.FromSeconds(1000);
                Ticks tt2 = new Ticks(); tt2.FromSeconds(1001);

                UT_TRUE(tt2.Since(tt1).InMillis() == 1000L);
                UT_TRUE(tt2.Since(tt1).InMicros() == 1000L * 1000L);
                UT_TRUE(tt2.Since(tt1).InNanos() == 1000L * 1000L * 1000L);
            }
        }
        /** ****************************************************************************************
         * Writes hash tables stored in a ScopeStore. Keys are AStrings.
         * Value types currently supported are LogData and int (in C# different method).
         * @param store The store to use.
         * @return The total number of hash table entries written.
         ******************************************************************************************/
        public int writeStoreMap <T>(ScopeStore <Dictionary <AString, T> > store)
        {
            bool firstEntry = true;
            int  cnt        = 0;

            if (store.globalStore != null && store.globalStore.Count > 0)
            {
                cnt += store.globalStore.Count;
                if (firstEntry)
                {
                    firstEntry = false;
                }
                else
                {
                    target.NewLine();
                }
                target._NC("  Scope.Global:").NewLine();
                maxKeyLength = writeStoreMapHelper(store.globalStore, "    ");
            }

            foreach (KeyValuePair <Thread, List <Dictionary <AString, T> > > thread in store.threadOuterStore)
            {
                if (thread.Value.Count == 0)
                {
                    continue;
                }
                ALIB.ASSERT(thread.Value.Count == 1);
                if (firstEntry)
                {
                    firstEntry = false;
                }
                else
                {
                    target.NewLine();
                }
                target._NC("  Scope.ThreadOuter ");  storeThreadToScope(thread.Key)._(':').NewLine();
                cnt         += thread.Value[0].Count;
                maxKeyLength = writeStoreMapHelper(thread.Value[0], "    ");
            }

            foreach (PathMap <Dictionary <AString, T> > map in store.languageStore)
            {
                if (firstEntry)
                {
                    firstEntry = false;
                }
                else
                {
                    target.NewLine();
                }
                target._NC("  ");
                storeKeyToScope(map)._(':').NewLine();
                cnt         += map.Value.Count;
                maxKeyLength = writeStoreMapHelper(map.Value, "    ");
            }

            foreach (KeyValuePair <Thread, List <Dictionary <AString, T> > > thread in store.threadInnerStore)
            {
                if (thread.Value.Count == 0)
                {
                    continue;
                }
                ALIB.ASSERT(thread.Value.Count == 1);
                if (firstEntry)
                {
                    firstEntry = false;
                }
                else
                {
                    target.NewLine();
                }
                target._NC("  Scope.ThreadInner ");  storeThreadToScope(thread.Key)._(':').NewLine();
                cnt         += thread.Value[0].Count;
                maxKeyLength = writeStoreMapHelper(thread.Value[0], "    ");
            }

            return(cnt);
        }
Example #25
0
        // #############################################################################################
        // Interface
        // #############################################################################################

        /** ****************************************************************************************
         * Adds an acquirer.
         * @param newAcquirer The acquirer to add.
         * @return The new number of \e acquirers set.
         ******************************************************************************************/
        public virtual int AddAcquirer(ThreadLock newAcquirer)
        {
            int count = -1;

            #if DEBUG
            bool errAllreadyAdded    = true;
            bool errHasToBeRecursive = false;
            int  errWasAcquired      = 0;
            #endif

            try { ALIB.Lock.Acquire();

                  count = acquirers.Count;

                  // check doubly added
                  if (newAcquirer == null ||
                      acquirers.IndexOf(newAcquirer) < 0)
                  {
                    #if DEBUG
                      errAllreadyAdded = false;
                      errWasAcquired   = DbgCountAcquirements() == 0 ? 0 : 1;
                    #endif

                      // switch on?
                      if (acquirers.Count == 1)
                      {
                        #if DEBUG
                          errAllreadyAdded = false;
                        #endif
                          ThreadLock firstAcquirer = acquirers[0];

                          // non-anonymous acquirer?
                          if (firstAcquirer != null)
                          {
                              if (firstAcquirer.GetMode() == LockMode.Recursive)
                              {
                                  firstAcquirer.Acquire();
                                  SetSafeness(Safeness.Safe);
                                  acquirers.Add(newAcquirer);
                                  count++;
                                  firstAcquirer.Release();
                              }
                            #if DEBUG
                              else
                              {
                                  errHasToBeRecursive = false;
                              }
                            #endif
                          }
                          // critical section: our first acquirer is anonymous. As documented in class,
                          // this must happen only in situations, when we are sure, that we are safe, e.g. still
                          // single threaded execution of process bootstrap.
                          else
                          {
                              // If this assert happens, its only good luck: we detected a misuse. But it should
                              // be very seldom to be detected this way :-/
                            #if DEBUG
                              if (errWasAcquired == 1)
                              {
                                  errWasAcquired = 2;
                              }
                            #endif

                              SetSafeness(Safeness.Safe);
                              acquirers.Add(newAcquirer);
                              count++;
                          }
                      }
                      else
                      {
                          acquirers.Add(newAcquirer);
                      }
                  }
            } finally { ALIB.Lock.Release(); }

            #if DEBUG
            ALIB.ASSERT_ERROR(!errAllreadyAdded, "Acquirer already registered.");
            ALIB.ASSERT_ERROR(!errHasToBeRecursive, "Acquireres need to be in recursive mode ");
            ALIB.ASSERT_ERROR(errWasAcquired != 1, "Already aquired. Hint: Acquirer[0] must not acquire this before adding itself!");
            ALIB.ASSERT_ERROR(errWasAcquired != 2, "Aquired and acquirer[0] anonymous. Misuse of SmartLock!");
            #endif

            return(count);
        }
Example #26
0
        // #############################################################################################
        // Internals
        // #############################################################################################

        /** ****************************************************************************************
         * Internal, recursive helper of #Find.
         *
         * @param       domainPath  Path to search.
         * @param       sensitivity Denotes if domain name search is treated case sensitive or not.
         * @param       maxCreate   The maximum number of sub domains that are created if not
         *                          found at the end of the path.
         * @param[out]  wasCreated  Output parameter that is set \c true if domain was not found
         *                          and hence created.
         * @return The domain found or created.
         ******************************************************************************************/
        protected Domain findRecursive(Substring domainPath, Case sensitivity,
                                       int maxCreate, ref bool wasCreated)
        {
            //--- get act sub-name and rest of path
            domainPath.Consume(PathSeparator);
            int endSubName = domainPath.IndexOf(PathSeparator);

            ALIB.ASSERT_ERROR(endSubName != 0, "Internal Error");

            // find end of actual domain name and save rest
            Substring restOfDomainPath = tSubstring2;

            restOfDomainPath.SetNull();
            if (endSubName > 0)
            {
                domainPath.Split(endSubName, restOfDomainPath, 1);
            }

            // search sub-domain
            Domain subDomain = null;

            // "."
            if (domainPath.Equals("."))
            {
                subDomain = this;
            }

            // ".."
            else if (domainPath.Equals(".."))
            {
                subDomain = Parent != null ? Parent : this;
            }


            // search in sub-domain
            else
            {
                int  i;
                bool fixedOnce = false;
                for (;;)
                {
                    for (i = 0; i < SubDomains.Count; i++)
                    {
                        int comparison = SubDomains[i].Name.CompareTo(domainPath, sensitivity);
                        if (comparison >= 0)
                        {
                            if (comparison == 0)
                            {
                                subDomain = SubDomains[i];
                            }
                            break;
                        }
                    }

                    // domain found?
                    if (subDomain != null)
                    {
                        break;
                    }

                    // try and fix name
                    if (!fixedOnce)
                    {
                        fixedOnce = true;

                        bool illegalCharacterFound = false;
                        for (int cp = 0; cp < domainPath.Length(); ++cp)
                        {
                            char c = domainPath.CharAt(cp);
                            if (c < '-' || c > 'z' ||
                                c == '<' || c == '>' ||
                                c == '[' || c == ']' ||
                                c == '=' || c == '?' || c == ';' || c == ':' ||
                                c == '\\' || c == '\'' || c == '.' || c == ','
                                )
                            {
                                illegalCharacterFound = true;
                                domainPath.Buf[domainPath.Start + cp] = '#';
                            }
                        }

                        if (illegalCharacterFound)
                        {
                            continue;
                        }
                    }

                    // create
                    if (maxCreate == 0)
                    {
                        return(null);
                    }
                    wasCreated = true;
                    SubDomains.Insert(i, subDomain = new Domain(this, new AString(domainPath)));
                    maxCreate--;
                    if (maxCreate == 0)
                    {
                        return(subDomain);
                    }

                    break;
                }
            }
            // recursion?
            if (restOfDomainPath.IsNotEmpty())
            {
                domainPath.Set(restOfDomainPath);
                return(subDomain.findRecursive(domainPath, sensitivity, maxCreate, ref wasCreated));
            }

            // that's it
            return(subDomain);
        }
Example #27
0
        /** ********************************************************************************************
         * The implementation of the abstract method of parent class TextLogger.
         * Loops over the log text, removes or ignores ESC sequences (all but ESC.TAB) and invokes
         * abstract methods of descendants as follows:
         * - \ref notifyLogOp "notifyLogOp(true)"
         * -   #logSubstring()
         * -   ...
         * - \ref notifyLogOp "notifyLogOp(Phase.End)"
         *
         * @param domain        The <em>Log Domain</em>.
         * @param verbosity     The verbosity. This has been checked to be active already on this stage
         *                      and is provided to be able to be logged out only.
         * @param msg           The log message.
         * @param scope         Information about the scope of the <em>Log Statement</em>..
         * @param lineNumber    The line number of a multi-line message, starting with 0. For single
         *                      line messages this is -1.
         **********************************************************************************************/
        override protected void logText(Domain domain, Verbosity verbosity,
                                        AString msg,
                                        ScopeInfo scope, int lineNumber)
        {
            if (!notifyLogOp(Phase.Begin))
            {
                return;
            }
            // loop over message, print the parts between the escape sequences
            int msgLength = msg.Length();
            int start     = 0;
            int end;
            int column = 0;

            while (start < msgLength)
            {
                bool foundESC = true;
                end = msg.IndexOf('\x1B', start);
                if (end < 0)
                {
                    foundESC = false;
                    end      = msgLength;
                }


                if (end > start)
                {
                    if (!logSubstring(msg, start, end - start))
                    {
                        return;
                    }
                    column += end - start;
                }

                // interpret escape sequence
                if (foundESC)
                {
                    char c = msg[++end];

                    // auto tab or end of meta info part
                    if (c == 't' || c == 'A')
                    {
                        end++;
                        c = msg[end++];
                        int extraSpace = c >= '0' && c <= '9' ? (int)(c - '0')
                                                          : (int)(c - 'A') + 10;

                        int tabStop = AutoSizes.Next(column, extraSpace);

                        if (tabStop > column)
                        {
                            AString spaces       = Util.GetSpaces();
                            int     spacesLength = spaces.Length();
                            int     qty          = tabStop - column;
                            while (qty > 0)
                            {
                                int size = qty < spacesLength ? qty : spacesLength;
                                if (!logSubstring(spaces, 0, size))
                                {
                                    return;
                                }
                                qty -= size;
                            }
                            column = tabStop;
                        }
                    }

                    // prune or ignore all others
                    else
                    {
                        if (!PruneESCSequences)
                        {
                            if (!logSubstring(msg, end - 1, 3))
                            {
                                return;
                            }
                        }
                        end += 2;
                    }
                }

                // next
                start = end;
            } // write loop

            ALIB.ASSERT_WARNING(start == msgLength, "Loop error when pruning ESC codes");
            notifyLogOp(Phase.End);
        }
Example #28
0
        public void Basics()
        {
            UT_INIT();

            Log.SetVerbosity(new ConsoleLogger(), Verbosity.Verbose, "/");
            Log.MapThreadName("UnitTest");
            Log.SetDomain("TickWatch", Scope.Method);

            Log.Info("\n### TicksBasics ###");

            // check times
            {
                Ticks t = new Ticks();
                t.FromNanos(42);      // beyond resolution in C#:  UT_EQ( t.InNanos(),        42L);
                UT_EQ(t.InMicros(), 0L);
                UT_EQ(t.InMillis(), 0L);
                UT_EQ(t.InSeconds(), 0L);
                t.FromMicros(42);    UT_EQ(t.InNanos(), 42000L);
                UT_EQ(t.InMicros(), 42L);
                UT_EQ(t.InMillis(), 0L);
                UT_EQ(t.InSeconds(), 0L);
                t.FromMillis(42);    UT_EQ(t.InNanos(), 42000000L);
                UT_EQ(t.InMicros(), 42000L);
                UT_EQ(t.InMillis(), 42L);
                UT_EQ(t.InSeconds(), 0L);
                t.FromSeconds(42);    UT_EQ(t.InNanos(), 42000000000L);
                UT_EQ(t.InMicros(), 42000000L);
                UT_EQ(t.InMillis(), 42000L);
                UT_EQ(t.InSeconds(), 42L);
                Ticks diff = new Ticks();
                diff.FromMillis(100);
                t.Add(diff);            UT_EQ(t.InNanos(), 42100000000L);
                UT_EQ(t.InMicros(), 42100000L);
                UT_EQ(t.InMillis(), 42100L);
                UT_EQ(t.InSeconds(), 42L);
                t.Sub(diff);            UT_EQ(t.InNanos(), 42000000000L);
                UT_EQ(t.InMicros(), 42000000L);
                UT_EQ(t.InMillis(), 42000L);
                UT_EQ(t.InSeconds(), 42L);

                t.FromMillis(100); UT_EQ(t.InHertz(), 10.0);
                t.FromMillis(300); UT_EQ(t.InHertz(0), 3.0);
                UT_EQ(t.InHertz(1), 3.3);
                UT_EQ(t.InHertz(2), 3.33);
                UT_EQ(t.InHertz(5), 3.33333);
            }

            // check internal frequency
            {
                double freq = Ticks.InternalFrequency;
                Log.Info("TickWatch InternalFrequency:   " + freq);
                UT_TRUE(freq >= 1000000.0);
            }

            // check TickWatch creation time
            {
                Ticks creationTimeDiff = new Ticks();
                creationTimeDiff.Sub(Ticks.CreationTime);
                Log.Info("TickWatch library creation was: " + creationTimeDiff.InNanos() + "ns ago");
                Log.Info("TickWatch library creation was: " + creationTimeDiff.InMicros() + "µs ago");
                Log.Info("TickWatch library creation was: " + creationTimeDiff.InMillis() + "ms ago");
                Log.Info("TickWatch library creation was: " + creationTimeDiff.InSeconds() + "s ago");
                UT_TRUE(creationTimeDiff.InNanos() > 100);       // It should really take 100 nanoseconds to get here!
                UT_TRUE(creationTimeDiff.InSeconds() < 3600);    // these test will probably not last an hour
            }

            // check if we could sleep for 100ms
            {
                Ticks start = new Ticks();
                ALIB.SleepMillis(30);
                Ticks sleepTime = new Ticks();
                sleepTime.Sub(start);
                Log.Info("TickWatch diff after 100ms sleep: " + sleepTime.InMillis() + " ms");
                UT_TRUE(sleepTime.InMillis() > 28);
                UT_TRUE(sleepTime.InMillis() < 150);    // should work even on heavily loaded machines
            }
        }
Example #29
0
        /** ********************************************************************************************
         *  Processes the next command found in the format string, by writing formatted information
         *  into the given buffer.
         *  The given Substring holds the next command. When method returns, the command is cut
         *  from the front.
         *
         * @param logger    The logger that we are embedded in.
         * @param domain    The <em>Log Domain</em>.
         * @param verbosity The verbosity. This has been checked to be active already on this
         *                  stage and is provided to be able to be logged out only.
         * @param scope     Information about the scope of the <em>Log Statement</em>..
         * @param dest      The buffer to write meta information into.
         * @param variable  The variable to read (may have more characters appended)
         *
         * @return The number of tab sequences that were written (by adding ESC::TAB to the buffer).
         **********************************************************************************************/
        protected virtual int processVariable(TextLogger logger, Domain domain, Verbosity verbosity,
                                              ScopeInfo scope, AString dest, Substring variable)
        {
            // process commands
            char c2;

            switch (variable.Consume())
            {
            // scope info
            case 'S':
            {
                // read sub command
                AString val;
                switch (c2 = variable.Consume())
                {
                case 'P':       // SP: full path
                {
                    int    length;
                    String path = scope.GetFullPath(out length);
                    if (length > 0)
                    {
                        dest._(path, 0, length);
                        return(0);
                    }
                    val = NoSourceFileInfo;
                } break;

                case 'p':       // Sp: trimmed path
                {
                    val = scope.GetTrimmedPath();
                    if (val.IsEmpty())
                    {
                        val = NoSourceFileInfo;
                    }
                } break;

                case 'F':       // file name
                {
                    val = scope.GetFileName();
                    if (val.IsEmpty())
                    {
                        val = NoSourceFileInfo;
                    }
                } break;

                case 'f':       // file name without extension
                {
                    val = scope.GetFileNameWithoutExtension();
                    if (val.IsEmpty())
                    {
                        val = NoSourceFileInfo;
                    }
                } break;


                case 'M':       // method name
                {
                    String method = scope.GetMethod();
                    if (method.Length == 0)
                    {
                        dest._(NoMethodInfo);
                    }
                    else
                    {
                        dest._(method);
                    }
                    return(0);
                }

                case 'L':      // line number
                {
                    dest._(scope.GetLineNumber());
                    return(0);
                }

                default:
                {
                    if (!warnedOnce)
                    {
                        warnedOnce = true;
                        ALIB.WARNING("Unknown format variable '%S" + c2 + "\' (only one warning)");
                    }
                    dest._("%ERROR");
                    return(0);
                }
                }
                dest._(val);
                return(0);
            }

            // %Tx: Time
            case 'T':
            {
                // read sub command
                c2 = variable.Consume();

                // %TD: Date
                if (c2 == 'D')
                {
                    // get time stamp as DateTime once
                    if (callerDateTime == null)
                    {
                        callerDateTime = scope.GetTimeStamp().InDotNetDateTime();
                    }

                    // avoid the allocation of a) a StringBuilder (yes, a string builder is allocated inside StringBuilder.AppendFormat!)
                    // and b) a DateTime object, if the format is the unchanged standard. And it is faster anyhow.
                    if (DateFormat.Equals("yyyy-MM-dd"))
                    {
                        dest._(callerDateTime.Value.Year, 4)._('-')
                        ._(callerDateTime.Value.Month, 2)._('-')
                        ._(callerDateTime.Value.Day, 2);
                    }

                    // support user defined standards
                    else
                    {
                        // detect changes of format string since last log
                        if (detectDateFormatChanges != DateFormat)
                        {
                            detectDateFormatChanges = DateFormat;
                            dateFormatString        = "{0:" + DateFormat + "}";
                        }

                        // get date string from system and append to log buffer
                        formatSB.Clear();
                        formatSB.AppendFormat(CultureInfo.InvariantCulture, dateFormatString, callerDateTime);
                        dest._(formatSB);
                    }
                }

                // %TT: Time of Day
                else if (c2 == 'T')
                {
                    // get time stamp as DateTime once
                    if (callerDateTime == null)
                    {
                        callerDateTime = scope.GetTimeStamp().InDotNetDateTime();
                    }

                    // avoid the allocation of a) a StringBuilder (yes, a string builder is allocated inside StringBuilder.AppendFormat!)
                    // and b) a DateTime object, if the format is the unchanged standard. And it is faster anyhow.
                    if (TimeOfDayFormat.Equals("HH:mm:ss"))
                    {
                        dest._(callerDateTime.Value.Hour, 2)._(':')
                        ._(callerDateTime.Value.Minute, 2)._(':')
                        ._(callerDateTime.Value.Second, 2);
                    }

                    // support user defined standards
                    else
                    {
                        // detect changes of format string since last log
                        if (detectTimeOfDayFormatChanges != TimeOfDayFormat)
                        {
                            detectTimeOfDayFormatChanges = TimeOfDayFormat;
                            timeOfDayFormatString        = "{0:" + TimeOfDayFormat + "}";
                        }

                        // get time string from system and append to log buffer
                        formatSB.Clear();
                        formatSB.AppendFormat(CultureInfo.InvariantCulture, timeOfDayFormatString, callerDateTime);
                        dest._(formatSB);
                    }
                }

                // %TC: Time elapsed since created
                else if (c2 == 'C')
                {
                    // create TimeSpan object (on the stack by using new! :)
                    TimeSpan elapsed = new TimeSpan(scope.GetTimeStamp().Raw() - logger.TimeOfCreation.Raw());

                    if (elapsed.Days > 0)
                    {
                        dest._(elapsed.Days)._(TimeElapsedDays);
                    }

                    if (elapsed.Hours > 0)
                    {
                        dest._(elapsed.Hours)._(':');
                    }

                    dest._(elapsed.Minutes, 2)._(':')
                    ._(elapsed.Seconds, 2)._('.')
                    ._(elapsed.Milliseconds, 3);
                }

                // %TL: Time elapsed since last log call
                else if (c2 == 'L')
                {
                    writeTimeDiff(dest, scope.GetTimeStamp().Since(logger.TimeOfLastLog).InNanos());
                }

                else
                {
                    if (!warnedOnce)
                    {
                        warnedOnce = true;
                        ALIB.WARNING("Unknown format variable '%T" + c2 + "\' (only one warning)");
                    }
                    dest._("%ERROR");
                }
                return(0);
            }


            // thread name / ID
            case 't':
            {
                c2 = variable.Consume();

                if (c2 == 'N')
                {
                    dest.Field()
                    ._(scope.GetThreadName())
                    .Field(logger.AutoSizes.Next(scope.GetThreadName().Length(), 0), Alignment.Center);
                }
                else if (c2 == 'I')
                {
                    tmpAString._()._(scope.GetThreadID());
                    dest.Field()
                    ._(tmpAString)
                    .Field(logger.AutoSizes.Next(tmpAString.Length(), 0), Alignment.Center);
                }
                else
                {
                    if (!warnedOnce)
                    {
                        warnedOnce = true;
                        ALIB.WARNING("Unknown format variable '%t" + c2 + "\' (only one warning)");
                    }
                    dest._("%ERROR");
                }
                return(0);
            }

            case 'L':
            {
                c2 = variable.Consume();
                if (c2 == 'G')
                {
                    dest._NC(logger.GetName());
                }
                else if (c2 == 'X')
                {
                    dest._NC(scope.GetLoxName());
                }
                else
                {
                    if (!warnedOnce)
                    {
                        warnedOnce = true;
                        ALIB.WARNING("Unknown format variable '%L" + c2 + "\' (only one warning)");
                    }
                    dest._("%ERROR");
                    return(0);
                }
                return(0);
            }

            case 'P':
            {
                dest._NC(Util.GetProcessName());
                return(0);
            }

            case 'V':   dest._(verbosity == Verbosity.Error    ? VerbosityError
                                  : verbosity == Verbosity.Warning  ? VerbosityWarning
                                  : verbosity == Verbosity.Info     ? VerbosityInfo
                                  :                               VerbosityVerbose);
                return(0);

            case 'D':
            {
                dest.Field()._(domain.FullPath).Field(logger.AutoSizes.Next(domain.FullPath.Length(), 0), Alignment.Left);
                return(0);
            }

            case '#':    dest._(logger.CntLogs, LogNumberMinDigits);
                return(0);

            // A: Auto tab
            case 'A':
            {
                // read extra space from format string
                int oldStart = variable.Start;
                int extraSpace;  variable.ConsumeInteger(out extraSpace);
                if (oldStart == variable.Start)
                {
                    extraSpace = 1;
                }

                // insert ESC code to jump to next tab level
                extraSpace = Math.Min(extraSpace, 10 + ('Z' - 'A'));
                char escNo = extraSpace < 10 ?   (char)('0' + extraSpace)
                                            :   (char)('A' + extraSpace);

                dest._("\x1Bt")._(escNo);
                return(1);
            }

            default:
            {
                if (!warnedOnce)
                {
                    warnedOnce = true;
                    ALIB.WARNING("Unknown format variable \'" + variable.Buf[variable.Start - 1] + "\'");
                }
                dest._("%ERROR");
            }
                return(0);
            }
        }
Example #30
0
        /** ********************************************************************************************
         *
         *  The implementation of the abstract method of parent class TextLogger. Logs messages to the
         *  application console and/or the VStudio output window.
         *
         * @param domain      The <em>Log Domain</em>.
         * @param verbosity   The verbosity. This has been checked to be active already on this
         *                    stage and is provided to be able to be logged out only.
         * @param msg         The log message.
         * @param scope       Information about the scope of the <em>Log Statement</em>..
         * @param lineNumber  The line number of a multi-line message, starting with 0. For
         *                    single line messages this is -1.
         **********************************************************************************************/
        override protected void logText(Domain domain, Verbosity verbosity,
                                        AString msg,
                                        ScopeInfo scope, int lineNumber)
        {
            // get actual console attributes
            ConsoleColor actualFGCol = Console.ForegroundColor;
            ConsoleColor actualBGCol = Console.BackgroundColor;

            // loop over message, print the parts between the escape sequences
            Tokenizer msgParts = new Tokenizer(msg, '\x1B');
            Substring actual   = msgParts.Actual;
            Substring rest     = msgParts.Rest;
            int       column   = 0;

            for (;;)
            {
                if (msgParts.Next(Whitespaces.Keep).IsNotEmpty())
                {
                #if !(ALOX_WP71 || ALOX_WP8)
                    Console.Write(msg.Buffer(), actual.Start, actual.Length());
                #else
                    Console.Write(msg.ToString(0, actual.Start, actual.Length());
                #endif
                    column += actual.Length();
                }

                // end of loop?
                if (!msgParts.HasNext())
                {
                    break;
                }

                // found an ESC sequence
                char c = rest.Consume();

                // Colors
                bool isForeGround = true;
                if (c == 'C' || c == 'c')
                {
                    isForeGround = c == 'c';

                    c         = rest.Consume();
                    int colNo = c - '0';
                    ALIB.ASSERT_WARNING(colNo >= 0 && colNo <= 9, "Unknown ESC-c code");


                    // set color
                    if (colNo >= 0 && colNo <= 8 || colNo == 8)
                    {
                        ConsoleColor[] cols = (isForeGround ? !IsBackgroundLight : IsBackgroundLight)  ? lightColors : darkColors;
                        if (isForeGround)
                        {
                            Console.ForegroundColor = cols[colNo];
                        }
                        else
                        {
                            Console.BackgroundColor = cols[colNo];
                        }
                    }
                    else if (colNo == 9)
                    {
                        if (isForeGround)
                        {
                            Console.ForegroundColor = actualFGCol;
                        }
                        else
                        {
                            Console.BackgroundColor = actualBGCol;
                        }
                    }

                    else
                    {
                        ALIB.WARNING("Unknown ESC- code");
                    }
                }

                // Styles
                else if (c == 's')
                {
                    // bold/italics style not supported in Windows console

                    // reset all
                    if (rest.Consume() == 'a')
                    {
                        Console.ForegroundColor = actualFGCol;
                        Console.BackgroundColor = actualBGCol;
                    }
                }

                // auto tab / end of meta
                else if (c == 't' || c == 'A')
                {
                    bool endOfMeta = c == 'A';
                    c = rest.Consume();
                    int extraSpace = c >= '0' && c <= '9' ? (int)  (c - '0')
                                                      : (int)(c - 'A') + 10;

                    int tabStop = AutoSizes.Next(column, extraSpace);

                    Util.WriteSpaces(Console.Out, tabStop - column);
                    column = tabStop;

                    if (endOfMeta)
                    {
                        switch (verbosity)
                        {
                        case Verbosity.Verbose:   Console.ForegroundColor = MsgColorVerbose;     break;

                        case Verbosity.Info:      Console.ForegroundColor = MsgColorInfo;        break;

                        case Verbosity.Warning:   Console.ForegroundColor = MsgColorWarning;     break;

                        case Verbosity.Error:     Console.ForegroundColor = MsgColorError;       break;

                        default:                  break;
                        }
                    }
                }

                // Link (we just colorize links here)
                else if (c == 'l')
                {
                    if (rest.Consume() == 'S')
                    {
                        Console.ForegroundColor = IsBackgroundLight ? ConsoleColor.DarkBlue : ConsoleColor.Blue;
                    }
                    else
                    {
                        Console.ForegroundColor = actualFGCol;
                    }
                }

                else
                {
                    ALIB.WARNING("Unknown ESC code");
                }
            } // write loop

            // reset colors
            Console.ForegroundColor = actualFGCol;
            Console.BackgroundColor = actualBGCol;

            // write NL
        #if !(ALOX_WP71 || ALOX_WP8)
            Console.WriteLine();
        #else
            Console.WriteLine();
        #endif
        }