// /** // * File: SkyChecker.cs // * Author: haraldwolff // * // * This file and it's content is copyrighted by the Author and / or copyright holder. // * Any use wihtout proper permission is illegal and may lead to legal actions. // * // * // **/ using System; using System.IO; using ln.types.btree; using ln.perfdb.storage; using ln.skyscanner.entities; using ln.types.threads; using System.Threading; using System.Linq; using ln.logging; using ln.snmp; using ln.http.resources; using System.Collections.Generic; namespace ln.skyscanner.checks { public class SkyChecker { public string BasePath { get; } [Callable] public PoolJob[] CurrentJobs => checkPool.CurrentPoolJobs; [Callable] public PoolJob[] QueuedJobs => checkPool.QueuedJobs; [Callable] public string[] PerfNames => perfFiles.Keys.ToArray(); public bool ContainsPerfFile(String perfName) => perfFiles.ContainsKey(perfName); [Callable] public SkyCheckState[] Issues { get { SkyCheckState[] checkStates = null; lock (SkyScanner.Instance.Entities.SkyCheckStates) { checkStates = Timing.Meassure("scheduler: checkStates", () => SkyScanner.Instance.Entities.SkyCheckStates.ToArray()); } return checkStates.Where((cs) => (!String.Empty.Equals(cs.Node?.Vendor) && ((cs.CheckState != CheckState.OK) || ((cs.UnchangedTime < TimeSpan.FromMinutes(10)) && (cs.History.Length > 1) )))).ToArray(); } } [Callable] public SkyCheckState[] CheckStatesByHostID(Guid nodeID) { lock (SkyScanner.Instance.Entities.SkyCheckStates) { return SkyScanner.Instance.Entities.SkyCheckStates.Query("Node", nodeID).ToArray(); } } public SNMPEngine SNMPEngine { get; } BTree perfFiles = new BTree(); Pool checkPool = new Pool(0); Thread threadScheduler; bool stopping; List saveQueue = new List(); public SkyChecker() { BasePath = Path.Combine(SkyScanner.Instance.BasePath, "perfdb"); Logging.Log(LogLevel.INFO, "SkyChecker: created"); SNMPEngine = new SNMPEngine(); SNMPEngine.Timeout = 4000; } public void Start() { if ((threadScheduler != null) && (threadScheduler.IsAlive)) throw new NotSupportedException("SkyChecker.scheduler() already running"); checkPool.SetPoolSize(256); Thread.Sleep(2500); threadScheduler = new Thread(scheduler); threadScheduler.Start(); } public void Stop() { stopping = true; if (threadScheduler!=null && threadScheduler.IsAlive) { threadScheduler.Interrupt(); } checkPool.Abort(); checkPool.Close(); foreach (PerfFile perfFile in perfFiles.Values) { if (perfFile.IsOpen) perfFile.Close(); } perfFiles.Clear(); } public PerfFile GetPerfFile(params string[] perfPath) { lock (this) { string perfName = string.Join("/", perfPath); if (!perfFiles.ContainsKey(perfName)) { String perfDirectory = Path.Combine(BasePath, Path.Combine(perfPath.Take(perfPath.Length - 1).ToArray())); if (!Directory.Exists(perfDirectory)) Directory.CreateDirectory(perfDirectory); String perfFileName = Path.Combine(perfDirectory, String.Format("{0}.perf", perfPath[perfPath.Length-1])); PerfFile perfFile = new PerfFile(perfFileName); perfFile.Open(); if (perfFile.FirstSection == null) { PerfFile.PerfFileSection s1 = new PerfFile.PerfFileSection(perfFile, null, TimeSpan.FromDays(28), 60, AggregationMethod.AVERAGE); PerfFile.PerfFileSection s2 = new PerfFile.PerfFileSection(perfFile, s1, TimeSpan.FromDays(56), 300, AggregationMethod.AVERAGE); PerfFile.PerfFileSection s3 = new PerfFile.PerfFileSection(perfFile, s2, TimeSpan.FromDays(84), 900, AggregationMethod.AVERAGE); PerfFile.PerfFileSection s4 = new PerfFile.PerfFileSection(perfFile, s3, TimeSpan.FromDays(168), 1800, AggregationMethod.AVERAGE); PerfFile.PerfFileSection s5 = new PerfFile.PerfFileSection(perfFile, s4, TimeSpan.FromDays(750), 3600, AggregationMethod.AVERAGE); } perfFile.Close(); perfFiles.Add(perfName, perfFile); } return perfFiles[perfName]; } } private void scheduler() { long nextMinute = DateTimeOffset.Now.ToUnixTimeMilliseconds(); try { while (!stopping) { List checkJobs = new List(); Logging.Log(LogLevel.INFO, "SkyChecker.scheduler(): scheduler save CheckStates"); lock (saveQueue) { foreach (SkyCheckState checkState in saveQueue) { SkyScanner.Instance.Entities.SkyCheckStates.Upsert(checkState); } saveQueue.Clear(); } Logging.Log(LogLevel.INFO, "SkyChecker.scheduler(): scheduler starts"); foreach (Node node in SkyScanner.Instance.Entities.NodeCollection) { CheckJob checkJob = new CheckJob(node); checkJobs.Add(checkJob); } Logging.Log(LogLevel.INFO, "SkyChecker.scheduler(): prepared {0} checks", checkJobs.Count); Logging.Log(LogLevel.INFO, "SkyChecker.scheduler(): scheduled {0} checks", checkPool.Enqueue(checkJobs)); while ((nextMinute - DateTimeOffset.Now.ToUnixTimeMilliseconds()) < 0) nextMinute += 60000; Thread.Sleep((int)(nextMinute - DateTimeOffset.Now.ToUnixTimeMilliseconds())); } } catch (ThreadInterruptedException) { } catch (OperationCanceledException) { } } public void Save(SkyCheckState checkState) { lock (saveQueue) { saveQueue.Add(checkState); } } public ComponentState State { get { return ComponentState.INITIALIZED; } } } }