ln.skyscanner/checks/SkyChecker.cs

211 lines
7.0 KiB
C#

// /**
// * 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<string, PerfFile> perfFiles = new BTree<string, PerfFile>();
Pool checkPool = new Pool(0);
Thread threadScheduler;
bool stopping;
List<SkyCheckState> saveQueue = new List<SkyCheckState>();
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<CheckJob> checkJobs = new List<CheckJob>();
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;
}
}
}
}