| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.IO.Abstractions;
- using System.Linq;
- using System.Net;
- using System.Net.Sockets;
- using BO.ProcessServer.Business.StatisticCounters;
- using BO.ProcessServer.Business.Workers;
- using BO.ProcessServer.Business.Workers.Contexts;
- using BO.ProcessServer.Options;
- using Connector.PS;
- using Quadarax.Foundation.Core.IO;
- using Quadarax.Foundation.Core.Logging;
- using Quadarax.Foundation.Core.Object;
- namespace BO.ProcessServer.Business
- {
- internal class Server : DisposableObject
- {
- #region *** Private fields ***
- private Configuration _configuration;
- private IFileSystem _fileSystem;
- private IList<ServerProcess> _processes;
- protected ILog Log { get; }
- protected ILog LogLifecycle { get; }
- protected Statistics Statistics { get; }
- private Pool _pool;
- private PullDocumentsWorker _wkPull;
- private RetentionWorker _wkRetention;
- private ProcessingDocumentsWorker _wkProcessing;
- private IConnectionPS _connection;
- #endregion
- #region *** Public properties ***
- public bool IsRunning { get; private set; }
- #endregion
- #region *** Constructors ***
- public Server(Configuration serverConfiguration, IFileSystem fileSystem, ILogger logger)
- {
- _configuration = serverConfiguration ?? throw new ArgumentNullException(nameof(serverConfiguration));
- _fileSystem = fileSystem ?? throw new ArgumentNullException(nameof(fileSystem));
- if (logger == null)
- throw new ArgumentNullException(nameof(logger));
- Log = logger.GetLogger(typeof(Server));
- LogLifecycle = logger.GetLogger("Lifecycle");
- Statistics = new Statistics();
- ValidateConfiguration();
-
- _processes = new List<ServerProcess>();
- _connection = new Connector(_configuration, _fileSystem);
- _pool = new Pool(_configuration, _fileSystem, logger);
- _wkPull = new PullDocumentsWorker(_connection, _configuration.System.PoolPullInterval, _fileSystem, Statistics, _pool, logger);
- _wkRetention = new RetentionWorker(new CfgCtx(_configuration, Statistics, _pool));
- _wkProcessing = new ProcessingDocumentsWorker(_configuration, _processes, _connection, _fileSystem, Statistics, _pool, logger);
- }
- #endregion
- #region *** Public operations ***
- public void Start()
- {
- if (IsRunning)
- {
- LogWarn($"Instance '{_configuration.System.Identification}' already running. Start skipped.");
- return;
- }
- LogDebug($"Starting instance '{_configuration.System.Identification}' ...");
- _wkPull.Start();
- _wkRetention.Start();
- _wkProcessing.Start();
- Statistics.GetCounter<TimespanCounter>(Statistics.CNT_PS_ONLINE_DUR).Start();
- IsRunning = true;
- LogInfo( $"Instance '{_configuration.System.Identification}' STARTED.");
- LogLifecycle.Log(LogSeverityEnum.Info, $"Instance '{_configuration.System.Identification}' STARTED.");
- }
- public void Stop()
- {
- if (!IsRunning)
- {
- LogWarn($"Instance '{_configuration.System.Identification}' already stopped. Stop skipped.");
- return;
- }
- LogDebug($"Stopping instance '{_configuration.System.Identification}' ...");
- StopAll();
- Statistics.GetCounter<TimespanCounter>(Statistics.CNT_PS_ONLINE_DUR).Stop();
- IsRunning = false;
- LogInfo( $"Instance '{_configuration.System.Identification}' STOPPED.");
- LogLifecycle.Log(LogSeverityEnum.Info, $"Instance '{_configuration.System.Identification}' STOPPED.");
- LogLifecycle.Log(LogSeverityEnum.Info, Statistics.ToString());
- }
- #endregion
- #region *** Overrides ***
- protected override void OnDisposing()
- {
- if (IsRunning)
- StopAll(true);
- _wkPull?.Dispose();
- _wkRetention?.Dispose();
- _wkProcessing?.Dispose();
- _connection?.Dispose();
- _pool?.Dispose();
- LogDebug($"Instance '{_configuration.System.Identification}' disposed.");
- _configuration = null;
- _fileSystem = null;
- _wkPull=null;
- _wkRetention=null;
- _wkProcessing = null;
- _connection=null;
- _pool = null;
- }
- #endregion
- #region *** Private Operations ***
- public void LogDebug(string message)
- {
- LogRaw(LogSeverityEnum.Debug, message);
- }
- public void LogInfo(string message)
- {
- LogRaw(LogSeverityEnum.Info, message);
- }
- public void LogWarn(string message)
- {
- LogRaw(LogSeverityEnum.Warn, message);
- }
- public void LogRaw(LogSeverityEnum severity, string message)
- {
- Log.Log(severity, message);
- }
- private void ValidateConfiguration()
- {
- if (string.IsNullOrEmpty(_configuration.System.Identification))
- throw new ArgumentNullException(nameof(_configuration.System.Identification),
- "Mandatory process server identification.");
- if (string.IsNullOrEmpty(_configuration.System.PreferredInterface))
- _configuration.System.PreferredInterface = "auto";
-
- var host = Dns.GetHostEntry(Dns.GetHostName());
- if (_configuration.System.PreferredInterface.Trim().ToLower() == "auto")
- {
- _configuration.System.PreferredInterface = host.AddressList.Where(x =>
- x.AddressFamily == AddressFamily.InterNetwork ||
- x.AddressFamily == AddressFamily.InterNetworkV6).OrderBy(x=>x.AddressFamily).FirstOrDefault()
- ?.ToString();
- }
- if (!host.AddressList.Any(x =>
- (x.AddressFamily == AddressFamily.InterNetwork ||
- x.AddressFamily == AddressFamily.InterNetworkV6) && x.ToString().ToLower() ==
- _configuration.System.PreferredInterface.Trim().ToLower()))
- throw new ArgumentNullException(nameof(_configuration.System.PreferredInterface),
- "Mandatory preferred interface (or auto) for server identification.");
- // Pool directories structure
- EnsureDirectory(_configuration.System.PoolPathBase);
- EnsureDirectory(_fileSystem.Path.Combine(_configuration.System.PoolPathBase, _configuration.System.PoolPathDone));
- EnsureDirectory(_fileSystem.Path.Combine(_configuration.System.PoolPathBase, _configuration.System.PoolPathFail));
- EnsureDirectory(_fileSystem.Path.Combine(_configuration.System.PoolPathBase, _configuration.System.PoolPathPending));
- EnsureDirectory(_fileSystem.Path.Combine(_configuration.System.PoolPathBase, _configuration.System.PoolPathWorking));
- // Scenario structure
- EnsureDirectory(_configuration.System.ScenarioPathBase);
- if (_fileSystem.Directory.GetFiles(TranslatePath(_configuration.System.ScenarioPathBase), "*.*").Length == 0)
- LogWarn($"Scenario directory '{TranslatePath(_configuration.System.ScenarioPathBase)}' is empty.");
- LogInfo("Configuration validated.");
- }
- private string EnsureDirectory(string path)
- {
- var dir = FileUtils.EnsurePathEndsWithDirSeparator(_fileSystem, TranslatePath(path));
- if (!_fileSystem.Directory.Exists(dir))
- {
- _fileSystem.Directory.CreateDirectory(dir);
- LogDebug($"Directory '{dir}' created.");
- }
- if (!_fileSystem.Directory.Exists(dir))
- throw new FileNotFoundException($"Directory '{dir}' not found!");
- return dir;
- }
- private string TranslatePath(string path)
- {
- if (string.IsNullOrEmpty(path))
- return path;
- return path.Replace("{CD}", _fileSystem.Directory.GetCurrentDirectory());
- }
- private void StopAll(bool silently = false)
- {
- _wkPull.Stop(silently);
- _wkRetention.Stop(silently);
- _wkProcessing.Stop(silently);
- foreach (var process in _processes)
- process.Stop(silently);
- foreach (var process in _processes)
- process.Dispose();
- _processes.Clear();
- }
- #endregion
- }
- }
|