210 lines
7.1 KiB
C#
210 lines
7.1 KiB
C#
using System;
|
|
using ln.application;
|
|
using System.Threading;
|
|
using ln.logging;
|
|
using ln.application.service;
|
|
using ln.skyscanner.entities;
|
|
using ln.skyscanner.checks;
|
|
using System.Collections.Generic;
|
|
using ln.types.threads;
|
|
using System.Linq;
|
|
using ln.snmp;
|
|
using ln.types.odb.ng;
|
|
using ln.types.odb.ng.storage.session;
|
|
|
|
namespace ln.skyscanner.services
|
|
{
|
|
public class CheckService : ApplicationServiceBase
|
|
{
|
|
public static bool DEBUG = false;
|
|
|
|
Pool checkPool;
|
|
|
|
EntityService entityService;
|
|
PerformanceValueService performanceValueService;
|
|
|
|
public EntityService EntityService => entityService;
|
|
public PerformanceValueService PerformanceValueService => performanceValueService;
|
|
public SNMPEngine SNMPEngine { get; private set; }
|
|
|
|
SkyScanner.Service coreService;
|
|
CheckServiceRPC RPC;
|
|
|
|
Mapper SessionMapper { get; set; }
|
|
|
|
Dictionary<Node, CheckJob> checkJobs = new Dictionary<Node, CheckJob>();
|
|
|
|
public CheckService()
|
|
:base("Check Service")
|
|
{
|
|
DependOnService<SkyScanner.Service>();
|
|
DependOnService<EntityService>();
|
|
DependOnService<PerformanceValueService>();
|
|
}
|
|
|
|
public override void ServiceMain(IApplicationInterface applicationInterface)
|
|
{
|
|
coreService = Dependency<SkyScanner.Service>();
|
|
entityService = Dependency<EntityService>();
|
|
performanceValueService = Dependency<PerformanceValueService>();
|
|
|
|
HashSet<Node> currentNodes = new HashSet<Node>();
|
|
|
|
checkPool = new Pool(96);
|
|
checkPool.PoolJobFinished += PoolJobFinished;
|
|
checkPool.Start();
|
|
|
|
SNMPEngine = new SNMPEngine();
|
|
SNMPEngine.Timeout = 5000;
|
|
|
|
long nextMinute = DateTimeOffset.Now.ToUnixTimeMilliseconds();
|
|
|
|
RPC = new CheckServiceRPC(this);
|
|
coreService.RPCContainer.Add("CheckService",RPC);
|
|
|
|
using (SessionStorageContainer session = new SessionStorageContainer(entityService.StorageContainer))
|
|
{
|
|
SessionMapper = new Mapper(session);
|
|
|
|
Ready();
|
|
|
|
while (!StopRequested)
|
|
{
|
|
Logging.Log(LogLevel.INFO, "SkyChecker.scheduler(): scheduler starts");
|
|
|
|
UpdateNodeList();
|
|
|
|
foreach (CheckJob checkJob in checkJobs.Values)
|
|
checkJob.Prepare();
|
|
|
|
Logging.Log(LogLevel.INFO, "SkyChecker.scheduler(): currently knows {0} checks", checkJobs.Count);
|
|
Logging.Log(LogLevel.INFO, "SkyChecker.scheduler(): currently {0} checks alive", checkPool.NumQueuedJobs);
|
|
Logging.Log(LogLevel.INFO, "SkyChecker.scheduler(): scheduled {0} checks", checkPool.Enqueue(checkJobs.Values));
|
|
|
|
|
|
while (true)
|
|
{
|
|
while ((nextMinute - DateTimeOffset.Now.ToUnixTimeMilliseconds()) < 0)
|
|
nextMinute += 60000;
|
|
|
|
try
|
|
{
|
|
Thread.Sleep((int)(nextMinute - DateTimeOffset.Now.ToUnixTimeMilliseconds()));
|
|
break;
|
|
}
|
|
catch (ThreadInterruptedException)
|
|
{
|
|
Logging.Log(LogLevel.INFO, "CheckService: scheduler was interrupted");
|
|
if (StopRequested)
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Logging.Log(LogLevel.INFO, "CheckService: Aborting currently scheduled checks");
|
|
checkPool.Stop(true);
|
|
|
|
SNMPEngine.Close();
|
|
|
|
coreService.RPCContainer.Remove("CheckService");
|
|
entityService = null;
|
|
performanceValueService = null;
|
|
coreService = null;
|
|
|
|
Logging.Log(LogLevel.INFO, "CheckService: stopped");
|
|
|
|
}
|
|
|
|
private void UpdateNodeList()
|
|
{
|
|
lock (this)
|
|
{
|
|
Logging.Log(LogLevel.DEBUG, "CheckService: Synchronizing CheckJobs");
|
|
|
|
HashSet<Node> knownNodes = Timing.Meassure("knownNodes: ", () => new HashSet<Node>(SessionMapper.Load<Node>()));
|
|
HashSet<Node> currentNodes = Timing.Meassure("currentNodes: ", () => new HashSet<Node>(checkJobs.Keys));
|
|
|
|
Timing.Meassure("synchronization", () =>
|
|
{
|
|
foreach (Node node in knownNodes)
|
|
{
|
|
if (!currentNodes.Contains(node))
|
|
{
|
|
CheckJob checkJob = new CheckJob(this, node);
|
|
checkJobs.Add(node, checkJob);
|
|
}
|
|
}
|
|
foreach (Node node in currentNodes)
|
|
{
|
|
if (!knownNodes.Contains(node))
|
|
{
|
|
checkJobs.Remove(node);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
void PoolJobFinished(Pool pool, PoolJob job)
|
|
{
|
|
CheckJob checkJob = job as CheckJob;
|
|
SessionMapper.Save<Node>(checkJob.Node);
|
|
}
|
|
|
|
|
|
public SkyCheckState[] GetCheckStates(Node node)
|
|
{
|
|
Query stateQuery = Query.Equals<SkyCheckState>("Node", node.ID);
|
|
SkyCheckState[] skyCheckStates = SessionMapper.Load<SkyCheckState>(stateQuery).ToArray();
|
|
Dictionary<string, SkyCheckState> checkStates = new Dictionary<string, SkyCheckState>();
|
|
|
|
foreach (SkyCheckState checkState in skyCheckStates)
|
|
{
|
|
checkStates.Add(checkState.CheckName, checkState);
|
|
}
|
|
foreach (SkyCheck check in SkyCheck.SkyChecks)
|
|
{
|
|
if (!checkStates.ContainsKey(check.Name) && check.IsValid(node))
|
|
{
|
|
checkStates.Add(check.Name, check.PrepareCheckState(this, node));
|
|
SessionMapper.Save<SkyCheckState>(checkStates[check.Name]);
|
|
}
|
|
}
|
|
|
|
return checkStates.Values.ToArray();
|
|
}
|
|
|
|
|
|
class CheckServiceRPC
|
|
{
|
|
CheckService checkService;
|
|
|
|
public CheckServiceRPC(CheckService checkService)
|
|
{
|
|
this.checkService = checkService;
|
|
}
|
|
|
|
public Node[] GetIssueList()
|
|
{
|
|
List<Node> nodes = new List<Node>();
|
|
|
|
foreach (Node node in checkService.SessionMapper.Load<Node>())
|
|
{
|
|
foreach (SkyCheckState checkState in node.CheckStates)
|
|
{
|
|
if (!String.Empty.Equals(node.Vendor) && ((checkState.CheckState != CheckState.OK) || ((checkState.UnchangedTime < TimeSpan.FromMinutes(10)) && (checkState.History.Length > 1)))){
|
|
nodes.Add(node);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return nodes.ToArray();
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
}
|