예제 #1
0
        async void DelayedNetworkConnectedUpdate(bool available, bool delayed = true)
        {
            // delay output, but output immediately if internet becomes available...

            if (!Atomic.Lock(ref DelayedNetworkUpdateLimiter))
            {
                return;
            }

            await Task.Delay(0).ConfigureAwait(false);             // asyncify

            try
            {
                if (available)
                {
                    CheckInet();
                    if (InternetAvailable)
                    {
                        needUpdate = true;
                        return;
                    }
                }

                if (netAntiFlicker && delayed)
                {
                    const int delay = 15;
                    int       sleep = Convert.ToInt32(DateTime.Now.TimeTo(lastnetworkchange.AddSeconds(delay)).TotalSeconds * 1000) + 250;

                    await Task.Delay(sleep.Constrain(1000, 16000));

                    if (DateTime.Now.TimeSince(lastnetworkchange).TotalSeconds < delay)
                    {
                        if (Taskmaster.DebugNet)
                        {
                            Log.Verbose("<Net> Delaying network status testing again: {Delay}<{Wait} is too soon",
                                        string.Format("{0:N0}s", DateTime.Now.TimeSince(lastnetworkchange).TotalSeconds), delay);
                        }
                        DelayedNetworkConnectedUpdate(NetworkAvailable);
                        return;
                    }
                    else
                    {
                        netAntiFlicker = false;
                    }
                }

                Log.Information("<Network> Status changed: " + (available ? "Connected" : "Disconnected"));
                netAntiFlicker = true;

                if (NetworkAvailable)
                {
                    needUpdate = true;
                }
            }
            catch { throw; }             // for finally block
            finally
            {
                Atomic.Unlock(ref DelayedNetworkUpdateLimiter);
            }
        }
예제 #2
0
        //async void TimerCheck(object state)
        async void TimerCheck(object sender, EventArgs ev)
        {
            // skip if already running...
            // happens sometimes when the timer keeps running but not the code here
            if (!Atomic.Lock(ref HealthCheck_lock))
            {
                return;
            }

            try
            {
                try
                {
                    await CheckErrors().ConfigureAwait(false);
                    await CheckLogs().ConfigureAwait(false);
                    await CheckMemory().ConfigureAwait(false);
                    await CheckNVM().ConfigureAwait(false);
                }
                catch (Exception ex) { Logging.Stacktrace(ex); }
            }
            catch { throw; }
            finally
            {
                Atomic.Unlock(ref HealthCheck_lock);
            }
        }
예제 #3
0
        void RestoreMainWindow(object sender, EventArgs e)
        {
            if (!Atomic.Lock(ref restoremainwindow_lock))
            {
                return;                                                       // already being done
            }
            try
            {
                Taskmaster.ShowMainWindow();

                if (Taskmaster.Trace)
                {
                    Log.Verbose("RestoreMainWindow done!");
                }
            }
            catch (Exception ex)
            {
                Logging.Stacktrace(ex);
                throw;
            }
            finally
            {
                Atomic.Unlock(ref restoremainwindow_lock);
            }
        }
예제 #4
0
        public void Tick(object state)
        {
            if (!Atomic.Lock(ref CallbackLimiter))
            {
                return;
            }

            try
            {
                var time = System.Diagnostics.Stopwatch.StartNew();

                long oldmem = GC.GetTotalMemory(false);

                System.Runtime.GCSettings.LargeObjectHeapCompactionMode = System.Runtime.GCLargeObjectHeapCompactionMode.CompactOnce;
                GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true, true);
                GC.WaitForPendingFinalizers();

                long newmem = GC.GetTotalMemory(true);

                Log.Debug("<Self-Maintenance> Done, saved {kBytes} kB.", (oldmem - newmem) / 1000);

                if (Taskmaster.Trace)
                {
                    Log.Verbose("Running periodic cleanup");
                }

                // TODO: This starts getting weird if cleanup interval is smaller than total delay of testing all items.
                // (15*60) / 2 = item limit, and -1 or -2 for safety margin. Unlikely, but should probably be covered anyway.

                if (Taskmaster.Components.processmanager != null)
                {
                    Taskmaster.processmanager.Cleanup();
                }

                Taskmaster.Config.Flush();

                time.Stop();

                Statistics.MaintenanceCount++;
                Statistics.MaintenanceTime += time.Elapsed.TotalSeconds;

                if (Taskmaster.Trace)
                {
                    Log.Verbose("Maintenance took: {Time}s", string.Format("{0:N2}", time.Elapsed.TotalSeconds));
                }
            }
            catch (Exception ex)
            {
                Logging.Stacktrace(ex);
                timer.Dispose();
                throw;
            }
            finally
            {
                Atomic.Unlock(ref CallbackLimiter);
            }
        }
예제 #5
0
        void RecordDeviceState(bool online_state, bool address_changed)
        {
            if (!Atomic.Lock(ref DeviceStateRecordLimiter))
            {
                return;
            }

            try
            {
                if (online_state != lastOnlineState)
                {
                    lastOnlineState = online_state;

                    if (online_state)
                    {
                        lastUptimeStart = DateTime.Now;

                        Task.Delay(new TimeSpan(0, 5, 0)).ContinueWith(x => ReportCurrentUpstate());
                    }
                    else                     // went offline
                    {
                        lock (uptime_lock)
                        {
                            var newUptime = (DateTime.Now - lastUptimeStart).TotalMinutes;
                            upTime.Add(newUptime);
                            uptimeTotal   += newUptime;
                            uptimeSamples += 1;
                            if (uptimeSamples > 20)
                            {
                                uptimeTotal   -= upTime[0];
                                uptimeSamples -= 1;
                                upTime.RemoveAt(0);
                            }
                        }

                        ReportUptime();
                    }

                    return;
                }
                else if (address_changed)
                {
                    // same state but address change was detected
                    Console.WriteLine("<Network> DEBUG: Address changed but internet connectivity unaffected.");
                }
            }
            catch (Exception ex)
            {
                Logging.Stacktrace(ex);
                throw;
            }
            finally
            {
                Atomic.Unlock(ref DeviceStateRecordLimiter);
            }
        }
예제 #6
0
        public async Task ScanTemp()
        {
            if (!Atomic.Lock(ref scantemp_lock))
            {
                return;
            }

            try
            {
                await Task.Delay(0);

                var dst = new DirectoryStats {
                    Files = 0, Dirs = 0, Size = 0
                };

                ReScanBurden = 0;

                Log.Information("Temp folders scanning initiated...");
                onTempScan?.Invoke(null, new DiskEventArgs {
                    State = ScanState.Start, Stats = dst
                });
                DirectorySize(new System.IO.DirectoryInfo(systemTemp), ref dst);
                if (systemTemp != userTemp)
                {
                    onTempScan?.Invoke(null, new DiskEventArgs {
                        State = ScanState.Segment, Stats = dst
                    });
                    DirectorySize(new System.IO.DirectoryInfo(userTemp), ref dst);
                }

                onTempScan?.Invoke(null, new DiskEventArgs {
                    State = ScanState.End, Stats = dst
                });
                Log.Information("Temp contents: {Files} files, {Dirs} dirs, {Size} MBs", dst.Files, dst.Dirs, string.Format("{0:N2}", dst.Size / 1000f / 1000f));
            }
            catch { throw; }             // for finally block
            finally
            {
                Atomic.Unlock(ref scantemp_lock);
            }
        }
예제 #7
0
        protected override void WndProc(ref Message m)
        {
            if (m.Msg == NativeMethods.WM_HOTKEY)
            {
                //Keys key = (Keys)(((int)m.LParam >> 16) & 0xFFFF);
                //NativeMethods.KeyModifier modifier = (NativeMethods.KeyModifier)((int)m.LParam & 0xFFFF);
                int id = m.WParam.ToInt32();                 // registered hotkey id

                if (Atomic.Lock(ref hotkeyinprogress))
                {
                    if (Taskmaster.Trace)
                    {
                        Log.Verbose("<Tray> Hotkey ctrl-alt-shift-m detected!!!");
                    }
                    Task.Run(new Action(async() =>
                    {
                        try
                        {
                            int ignorepid = Taskmaster.activeappmonitor?.Foreground ?? -1;
                            Log.Information("<Tray> Hotkey detected, freeing memory while ignoring foreground{Ign} if possible.",
                                            ignorepid > 4 ? string.Format(" (#{0})", ignorepid) : string.Empty);
                            await processmanager.FreeMemory(ignorepid).ConfigureAwait(false);
                        }
                        catch (Exception ex)
                        {
                            Logging.Stacktrace(ex);
                        }
                        finally
                        {
                            Atomic.Unlock(ref hotkeyinprogress);
                        }
                    }));
                }
            }

            base.WndProc(ref m);             // is this necessary?
        }
예제 #8
0
        public async void EnsureVisible()
        {
            if (!Atomic.Lock(ref ensuringvisibility))
            {
                return;
            }

            try
            {
                Enable();

                int attempts = 0;
                while (!Tray.Visible)
                {
                    Log.Debug("<Tray> Not visible, fixing...");

                    RefreshVisibility();

                    await Task.Delay(15 * 1000).ConfigureAwait(true);

                    if (++attempts >= 5)
                    {
                        Log.Fatal("<Tray> Failure to become visible after 5 attempts. Exiting to avoid ghost status.");
                        Taskmaster.UnifiedExit();
                    }
                }
            }
            catch (Exception ex)
            {
                Logging.Stacktrace(ex);
            }
            finally
            {
                Atomic.Unlock(ref ensuringvisibility);
            }
        }
예제 #9
0
        static int correcting;      // = 0;
        async void VolumeChangedHandler(NAudio.CoreAudioApi.AudioVolumeNotificationData data)
        {
            var    oldVol = Volume;
            double newVol = data.MasterVolume * 100;

            if (Math.Abs(newVol - Target) <= SmallVolumeHysterisis)
            {
                if (Taskmaster.ShowInaction)
                {
                    Log.Verbose("<Microphone> Volume change too small ({VolumeChange:N1}%) to act on.", Math.Abs(newVol - Target));
                }
                return;
            }

            if (Taskmaster.Trace)
            {
                Log.Verbose("<Microphone> Volume changed from {OldVolume:N1}% to {NewVolume:N1}%", oldVol, newVol);
            }

            // This is a light HYSTERISIS limiter in case someone is sliding a volume bar around,
            // we act on it only once every [AdjustDelay] ms.
            // HOPEFULLY there are no edge cases with this triggering just before last adjustment
            // and the notification for the last adjustment coming slightly before. Seems super unlikely tho.
            // TODO: Delay this even more if volume is changed ~2 seconds before we try to do so.
            if (Math.Abs(newVol - Target) >= VolumeHysterisis)             // Volume != Target for double
            {
                if (Taskmaster.Trace)
                {
                    Log.Verbose("<Microphone> DEBUG: Volume changed = [{OldVolume:N1} -> {NewVolume:N1}], Off.Target: {VolumeOffset:N1}",
                                oldVol, newVol, Math.Abs(newVol - Target));
                }

                if (Atomic.Lock(ref correcting))
                {
                    try
                    {
                        await System.Threading.Tasks.Task.Delay(AdjustDelay);                         // actual hysterisis, this should be cancellable

                        oldVol = Control.Percent;
                        Log.Information("<Microphone> Correcting volume from {OldVolume:N1} to {NewVolume:N1}", oldVol, Target);
                        Volume        = Target;
                        Corrections  += 1;
                        micstatsdirty = true;

                        VolumeChanged?.Invoke(this, new VolumeChangedEventArgs {
                            Old = oldVol, New = Target, Corrections = Corrections
                        });
                    }
                    catch { throw; }                      // required for finally to be guaranteed
                    finally
                    {
                        Atomic.Unlock(ref correcting);
                    }
                }
                else
                {
                    if (Taskmaster.Trace)
                    {
                        Log.Verbose("<Microphone> DEBUG CorrectionAlreadyQueued");
                    }
                }
            }
            else
            {
                if (Taskmaster.Trace)
                {
                    Log.Verbose("<Microphone> DEBUG NotCorrected");
                }
            }
        }
예제 #10
0
        public void UpdateInterfaces()
        {
            if (!Atomic.Lock(ref InterfaceUpdateLimiter))
            {
                return;
            }

            needUpdate = false;

            try
            {
                // TODO: Rate limit
                if (Taskmaster.DebugNet)
                {
                    Log.Verbose("<Network> Enumerating network interfaces...");
                }

                var ifacelistt = new List <NetDevice>();
                // var ifacelist = new List<string[]>();

                var index = 0;
                NetworkInterface[] adapters = NetworkInterface.GetAllNetworkInterfaces();
                foreach (NetworkInterface dev in adapters)
                {
                    var ti = index++;
                    if (dev.NetworkInterfaceType == NetworkInterfaceType.Loopback || dev.NetworkInterfaceType == NetworkInterfaceType.Tunnel)
                    {
                        continue;
                    }

                    var stats = dev.GetIPStatistics();

                    IPAddress _ipv4 = IPAddress.None, _ipv6 = IPAddress.None;
                    foreach (UnicastIPAddressInformation ip in dev.GetIPProperties().UnicastAddresses)
                    {
                        // TODO: Maybe figure out better way and early bailout from the foreach
                        switch (ip.Address.AddressFamily)
                        {
                        case System.Net.Sockets.AddressFamily.InterNetwork:
                            _ipv4 = ip.Address;
                            break;

                        case System.Net.Sockets.AddressFamily.InterNetworkV6:
                            _ipv6 = ip.Address;
                            break;
                        }
                    }

                    var devi = new NetDevice
                    {
                        Index       = ti,
                        Name        = dev.Name,
                        Type        = dev.NetworkInterfaceType,
                        Status      = dev.OperationalStatus,
                        Speed       = dev.Speed,
                        IPv4Address = _ipv4,
                        IPv6Address = _ipv6,
                    };

                    devi.Incoming.From(stats, true);
                    devi.Outgoing.From(stats, false);
                    // devi.PrintStats();
                    ifacelistt.Add(devi);

                    if (Taskmaster.DebugNet)
                    {
                        Log.Verbose("<Network> Interface: {InterfaceName}", dev.Name);
                    }
                }

                lock (interfaces_lock) CurrentInterfaceList = ifacelistt;
            }
            finally
            {
                Atomic.Unlock(ref InterfaceUpdateLimiter);
            }
        }
예제 #11
0
        int InetCheckLimiter;         // = 0;
        bool CheckInet(bool address_changed = false)
        {
            // TODO: Figure out how to get Actual start time of internet connectivity.

            if (!Atomic.Lock(ref InetCheckLimiter))
            {
                return(InternetAvailable);
            }

            if (Taskmaster.Trace)
            {
                Log.Verbose("<Network> Checking internet connectivity...");
            }

            try
            {
                var oldInetAvailable = InternetAvailable;
                if (NetworkAvailable)
                {
                    try
                    {
                        Dns.GetHostEntry(dnstestaddress);                         // FIXME: There should be some other method than DNS testing
                        InternetAvailable = true;
                        Notified          = false;
                        // TODO: Don't rely on DNS?
                    }
                    catch (System.Net.Sockets.SocketException ex)
                    {
                        InternetAvailable = false;
                        switch (ex.SocketErrorCode)
                        {
                        case System.Net.Sockets.SocketError.AccessDenied:
                        case System.Net.Sockets.SocketError.SystemNotReady:
                            break;

                        case System.Net.Sockets.SocketError.TryAgain:
                        case System.Net.Sockets.SocketError.TimedOut:
                        default:
                            Log.Information("<Network> Internet availability test inconclusive, assuming connected.");
                            InternetAvailable = true;
                            return(InternetAvailable);

                        case System.Net.Sockets.SocketError.SocketError:
                        case System.Net.Sockets.SocketError.Interrupted:
                        case System.Net.Sockets.SocketError.Fault:
                            if (!Notified)
                            {
                                Log.Warning("<Network> Internet check interrupted. Potential hardware/driver issues.");
                                Notified = true;
                            }
                            break;

                        case System.Net.Sockets.SocketError.HostUnreachable:
                        case System.Net.Sockets.SocketError.HostNotFound:
                        case System.Net.Sockets.SocketError.HostDown:
                            if (!Notified)
                            {
                                Log.Warning("<Network> DNS test failed, test host unreachable. Test host may be down.");
                                Notified = true;
                            }
                            break;

                        case System.Net.Sockets.SocketError.NetworkDown:
                        case System.Net.Sockets.SocketError.NetworkReset:
                        case System.Net.Sockets.SocketError.NetworkUnreachable:
                            break;
                        }
                    }
                }
                else
                {
                    InternetAvailable = false;
                }

                RecordDeviceState(InternetAvailable, address_changed);

                if (oldInetAvailable != InternetAvailable)
                {
                    string status = "All OK";
                    if (NetworkAvailable && !InternetAvailable)
                    {
                        status = "ISP/route problems";
                    }
                    else if (!NetworkAvailable)
                    {
                        status = "Cable unplugged or router/modem down";
                    }

                    Log.Information("<Network> Status: {NetworkAvailable}, Internet: {InternetAvailable} – {Status}",
                                    (NetworkAvailable ? "Up" : "Down"),
                                    (InternetAvailable ? "Connected" : "Disconnected"),
                                    status);
                }
                else
                {
                    if (Taskmaster.Trace)
                    {
                        Log.Verbose("<Network> Connectivity unchanged.");
                    }
                }
            }
            finally
            {
                Atomic.Unlock(ref InetCheckLimiter);
            }

            InternetStatusChange?.Invoke(this, new InternetStatus {
                Available = InternetAvailable, Start = lastUptimeStart, Uptime = Uptime
            });

            return(InternetAvailable);
        }
예제 #12
0
        void AnalyzeTrafficBehaviour()
        {
            Debug.Assert(CurrentInterfaceList != null);

            if (!Atomic.Lock(ref TrafficAnalysisLimiter))
            {
                return;
            }

            try
            {
                PacketWarning.Leak();

                var oldifaces = CurrentInterfaceList;
                UpdateInterfaces();                 // force refresh
                var ifaces = CurrentInterfaceList;

                if (ifaces == null)
                {
                    return;                                 // no interfaces, just quit
                }
                for (int index = 0; index < ifaces.Count; index++)
                {
                    outgoing    = ifaces[index].Outgoing;
                    incoming    = ifaces[index].Incoming;
                    oldoutgoing = oldifaces[index].Outgoing;
                    oldincoming = oldifaces[index].Incoming;

                    long totalerrors   = outgoing.Errors + incoming.Errors;
                    long totaldiscards = outgoing.Errors + incoming.Errors;
                    long totalunicast  = outgoing.Errors + incoming.Errors;
                    long errors        = (incoming.Errors - oldincoming.Errors) + (outgoing.Errors - oldoutgoing.Errors);
                    long discards      = (incoming.Discards - oldincoming.Discards) + (outgoing.Discards - oldoutgoing.Discards);
                    long packets       = (incoming.Unicast - oldincoming.Unicast) + (outgoing.Unicast - oldoutgoing.Unicast);

                    // Console.WriteLine("{0} : Packets(+{1}), Errors(+{2}), Discarded(+{3})", ifaces[index].Name, packets, errors, discards);

                    if (errors > 0 &&                  // only if errors
                        Taskmaster.ShowNetworkErrors &&                         // user wants to see this
                        !ErrorReports.Peaked &&                         // we're not waiting for report counter to go down
                        ErrorReports.Pump())                            // error reporting not full
                    {
                        Log.Warning("<Network> {Device} is suffering from traffic errors! (+{Rate} since last sample)",
                                    ifaces[index].Name, errors);
                    }
                    else
                    {
                        ErrorReports.Leak();
                    }

                    onSampling?.Invoke(this, new NetDeviceTrafficEventArgs
                    {
                        Traffic =
                            new NetDeviceTraffic
                        {
                            Index = index,
                            Delta = new NetTraffic {
                                Unicast = packets, Errors = errors, Discards = discards
                            },
                            Total = new NetTraffic {
                                Unicast = totalunicast, Errors = totalerrors, Discards = totaldiscards, Bytes = incoming.Bytes + outgoing.Bytes
                            },
                        }
                    });
                }
            }
            catch (Exception ex)
            {
                Logging.Stacktrace(ex);
            }
            finally
            {
                Atomic.Unlock(ref TrafficAnalysisLimiter);
            }
        }
예제 #13
0
파일: Cache.cs 프로젝트: ICGLabs/taskmaster
        /// <summary>
        /// Prune cache.
        /// </summary>
        void Prune()
        {
            if (!Atomic.Lock(ref prune_in_progress))
            {
                return;                                                  // only one instance.
            }
            try
            {
                if (Items.Count <= MinCache)
                {
                    return;                                          // just don't bother
                }
                if (Items.Count <= MaxCache && CacheEvictStrategy == EvictStrategy.LeastUsed)
                {
                    return;
                }

                lock (cache_lock)
                {
                    var list = Items.Values.ToList();                     // would be nice to cache this list

                    list.Sort(delegate(CacheItem <K1, K2, T> x, CacheItem <K1, K2, T> y)
                    {
                        if (CacheEvictStrategy == EvictStrategy.LeastRecent)
                        {
                            if (x.Access < y.Access)
                            {
                                return(-1);
                            }
                            if (x.Access > y.Access)
                            {
                                return(1);
                            }
                            // Both have equal at this point
                            if (x.Desirability < y.Desirability)
                            {
                                return(-1);
                            }
                            if (x.Desirability > y.Desirability)
                            {
                                return(1);
                            }
                        }
                        else
                        {
                            if (x.Desirability < y.Desirability)
                            {
                                return(-1);
                            }
                            if (x.Desirability > y.Desirability)
                            {
                                return(1);
                            }
                            // Both have equal at this point
                            if (x.Access < y.Access)
                            {
                                return(-1);
                            }
                            if (x.Access > y.Access)
                            {
                                return(1);
                            }
                        }

                        return(0);
                    });

                    // Log.Debug("CACHE STATE: FIRST({First}) LAST({LAST})", list.First().Access, list.Last().Access);
                    // Log.Debug("CACHE ITEMS BEFORE PRUNE: {Items}", Items.Count);
                    while (Items.Count > MaxCache)
                    {
                        var bu  = list.ElementAt(0);
                        var key = bu.AccessKey;
                        // Log.Debug("--- REMOVING: Key:{Key}, Last Access: {Date}, Desirability: {Value}",
                        //        key, bu.Access, bu.Desirability);
                        Items.Remove(key);
                        list.RemoveAt(0);
                    }
                    // Log.Debug("CACHE ITEMS AFTER PRUNE: {Items}", Items.Count);

                    double bi = double.NaN;

                    var deleteItem = new Action <K1>(
                        (K1 key) =>
                    {
                        if (Taskmaster.Trace)
                        {
                            Log.Verbose("Removing {time} min old item.", string.Format("{0:N1}", bi));
                        }
                        Items.Remove(key);
                        list.RemoveAt(0);
                    }
                        );

                    var now = DateTime.Now;
                    while (list.Count > 0)
                    {
                        var bu = list.ElementAt(0);
                        bi = now.TimeSince(bu.Access).TotalMinutes;

                        if (CacheEvictStrategy == EvictStrategy.LeastRecent)
                        {
                            if (bi > MaxAge)
                            {
                                deleteItem(bu.AccessKey);
                            }
                            else
                            {
                                break;
                            }
                        }
                        else                         // .LeastUsed, TM is never going to reach this.
                        {
                            if (bi > MinAge)
                            {
                                deleteItem(bu.AccessKey);
                            }
                            else
                            {
                                break;
                            }
                        }
                    }
                }
            }
            finally
            {
                Atomic.Unlock(ref prune_in_progress);
            }
        }