Exemple #1
0
        private void threadSpin()
        {
            var lastPileCompact = DateTime.UtcNow;

            log(MessageType.Info, "threadSpin()", "Entering...");
            try
            {
                var wasActive = App.Active;  //remember whether app was active during start
                                             //this is needed so that CacheStore works without app container (using NOPApplication) in which case
                                             //service must be .Disposed() to stop this thread
                var timer = Stopwatch.StartNew();
                while ((App.Active | !wasActive) && Running)
                {
                    var utcNow = DateTime.UtcNow;

                    var tc = m_Tables.Count;
                    var maxTimePerTableMs = THREAD_MAX_TIME_FOR_SWEEP_ALL_MS / (tc != 0 ? tc : 1);
                    if (maxTimePerTableMs < 2)
                    {
                        maxTimePerTableMs = 2;
                    }

                    foreach (var table in m_Tables)
                    {
                        if (!Running)
                        {
                            break;
                        }
                        try
                        {
                            var sweptToEnd = table.Sweep(timer, maxTimePerTableMs);
                            if (m_InstrumentationEnabled)
                            {
                                Instrumentation.CacheTableSwept.Happened(Name);                    //for cache
                                Instrumentation.CacheTableSwept.Happened(Name + "." + table.Name); //for table
                            }

                            if (sweptToEnd)
                            {
                                if (table.Count == 0)
                                {
                                    if (!table.SweepWhenBecameEmpty.HasValue)
                                    {
                                        table.SweepWhenBecameEmpty = utcNow;
                                    }
                                    else
                                    if ((utcNow - table.SweepWhenBecameEmpty.Value).TotalSeconds > EMPTY_TABLE_LIFE_SEC)
                                    {
                                        m_Tables.Unregister(table);//can mutate m_Tables because foreach does a snapshot via GetEnumerator
                                    }
                                }
                                else
                                {
                                    table.SweepWhenBecameEmpty = null;
                                }
                            }
                        }
                        catch (Exception error)
                        {
                            log(MessageType.Critical,
                                "threadSpin().foreach.Sweep",
                                "Leaked exception while sweeping table '{0}': {1}'"
                                .Args(table.Name, error.ToMessageWithType()), error);
                        }
                    }


                    try
                    {
                        dumpInstruments();
                    }
                    catch (Exception error)
                    {
                        log(MessageType.Critical,
                            "threadSpin().dumpInstruments",
                            "Leaked exception dumping instrumentation: {0}'"
                            .Args(error.ToMessageWithType()), error);
                    }

                    try
                    {
                        if ((utcNow - lastPileCompact).TotalSeconds > 5 * 60)
                        {
                            var freed = m_Pile.Compact();
                            lastPileCompact = utcNow;
                            if (freed > 0)
                            {
                                log(MessageType.Info, "threadSpin().pile.compact()", "Freed {0:n0} bytes".Args(freed));
                            }
                        }
                    }
                    catch (Exception error)
                    {
                        log(MessageType.Critical,
                            "threadSpin().pile.compact()",
                            "Leaked exception compacting pile: {0}'"
                            .Args(error.ToMessageWithType()), error);
                    }

                    m_Trigger.WaitOne(THREAD_MIN_GRANULARITY_MS + ExternalRandomGenerator.Instance.NextScaledRandomInteger(0, THREAD_GRANULARITY_VARIANCE_MS));
                }  //while
            }
            catch (Exception e)
            {
                log(MessageType.Emergency, "threadSpin()", "Leaked exception, the tables are not swept anymore" + e.ToMessageWithType(), e);
            }

            log(MessageType.Info, "threadSpin()", "...Exiting");
        }