ln.application/service/ApplicationServiceBase.cs

109 lines
3.5 KiB
C#

using System;
using System.Threading;
using ln.logging;
using System.Collections.Generic;
using System.Linq;
namespace ln.application.service
{
public abstract class ApplicationServiceBase : IDisposable
{
public int TimeOut { get; set; } = 10000;
public String ServiceName { get; protected set; }
public virtual bool IsAlive => ((ServiceThread != null) && ServiceThread.IsAlive);
public bool StopRequested { get; protected set; }
public Thread ServiceThread { get; protected set; }
public string ServiceStateText { get; protected set; }
public IApplicationInterface CurrentApplicationInterface { get; protected set; }
public Type[] DependingServiceTypes => dependingServiceTypes.ToArray();
HashSet<Type> dependingServiceTypes = new HashSet<Type>();
public ApplicationServiceBase(String serviceName)
{
ServiceName = serviceName;
ServiceStateText = "Initialized";
}
public void Dispose()
{
ServiceStateText = "Disposed";
}
protected void DependOnService<S>() => dependingServiceTypes.Add(typeof(S));
public T Dependency<T>() where T : ApplicationServiceBase
{
T serviceBase = (T)CurrentApplicationInterface.ServiceContainer[typeof(T)].ServiceBase;
if (serviceBase == null)
throw new EntryPointNotFoundException(String.Format("depending service not found: {0}",typeof(T).ToString()));
return serviceBase;
}
public virtual void ServiceMain(IApplicationInterface applicationInterface) => throw new NotImplementedException();
public virtual bool Start(IApplicationInterface applicationInterface, String[] arguments)
{
if (IsAlive)
throw new NotSupportedException("Service is already alive");
CurrentApplicationInterface = applicationInterface;
foreach (Type dep in dependingServiceTypes)
{
ServiceDefinition depService = CurrentApplicationInterface.ServiceContainer[dep];
if (!depService.IsAlive)
{
CurrentApplicationInterface.ServiceContainer.Start(depService);
if (!depService.IsAlive)
{
Logging.Log(LogLevel.ERROR, "service {0} could not start depending service {1}", ServiceName, depService.ServiceClassName);
return false;
}
}
}
StopRequested = false;
ServiceThread = new Thread(() => ServiceMain(applicationInterface));
ServiceThread.Start();
return true;
}
public virtual bool Stop() => Stop(false);
public virtual bool Stop(bool force)
{
if (IsAlive)
{
StopRequested = true;
lock (ServiceThread)
{
Monitor.PulseAll(ServiceThread);
}
ServiceThread.Join(TimeOut);
if (IsAlive && force)
{
Logging.Log(LogLevel.INFO, "Service did not shutdown, enforcing {0}",ServiceName);
ServiceThread.Abort();
ServiceThread.Join(TimeOut);
}
if (!ServiceThread.IsAlive)
CurrentApplicationInterface = null;
return !ServiceThread.IsAlive;
}
return true;
}
}
}