public static void TestWhipLru_Stop_Fresh_DoesntThrow() { LOG.Info($"Executing {nameof(TestWhipLru_Stop_Fresh_DoesntThrow)}"); var whiplru = new WhipLru( ADDRESS, PORT, PASSWORD, PID_FILE_MANAGER, _storageManager ); Assert.DoesNotThrow(whiplru.Stop); }
public static void TestWhipLru_Start_Twice_InvalidOperationException() { LOG.Info($"Executing {nameof(TestWhipLru_Start_Twice_InvalidOperationException)}"); var whiplru = new WhipLru( ADDRESS, PORT, PASSWORD, PID_FILE_MANAGER, _storageManager ); whiplru.Start(); Assert.Throws <InvalidOperationException>(whiplru.Start); whiplru.Stop(); }
public static int Main(string[] args) { // First line, hook the appdomain to the crash reporter AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; var waitHandle = new EventWaitHandle(false, EventResetMode.AutoReset, "70a9f94f-59e8-4073-93ab-00aaacc26111", out var createdNew); if (!createdNew) { LOG.Error("Server process already started, please stop that server first."); return(2); } // Add the arguments supplied when running the application to the configuration var configSource = new ArgvConfigSource(args); // Commandline switches configSource.AddSwitch("Startup", "inifile"); configSource.AddSwitch("Startup", "logconfig"); configSource.AddSwitch("Startup", "pidfile"); configSource.AddSwitch("Startup", "purge"); var startupConfig = configSource.Configs["Startup"]; var pidFileManager = new PIDFileManager(startupConfig.GetString("pidfile", string.Empty)); // Configure Log4Net { var logConfigFile = startupConfig.GetString("logconfig", string.Empty); if (string.IsNullOrEmpty(logConfigFile)) { XmlConfigurator.Configure(); LogBootMessage(); LOG.Info("Configured log4net using ./WHIP_LRU.exe.config as the default."); } else { XmlConfigurator.Configure(new FileInfo(logConfigFile)); LogBootMessage(); LOG.Info($"Configured log4net using \"{logConfigFile}\" as configuration file."); } } // Configure nIni aliases and locale Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US", true); configSource.Alias.AddAlias("On", true); configSource.Alias.AddAlias("Off", false); configSource.Alias.AddAlias("True", true); configSource.Alias.AddAlias("False", false); configSource.Alias.AddAlias("Yes", true); configSource.Alias.AddAlias("No", false); var isRunning = true; WhipLru whipLru = null; // Handlers for signals. UnixSignal[] signals = null; if (ON_POSIX_COMPLAINT_OS) { signals = new [] { new UnixSignal(Signum.SIGINT), new UnixSignal(Signum.SIGTERM), new UnixSignal(Signum.SIGHUP), }; } else { Console.CancelKeyPress += (sender, cargs) => { LOG.Debug("CTRL-C pressed, terminating."); isRunning = false; whipLru?.Stop(); cargs.Cancel = true; waitHandle.Set(); }; } while (isRunning) { // Dump any known servers, we're going to reconfigure them. foreach (var server in _assetServersByName.Values) { server.Dispose(); } // TODO: might need to double buffer these, or something, so that old ones can finish out before being disposed. // Read in the ini file ReadConfigurationFromINI(configSource); // Read in a config list that lists the priority order of servers and their settings. var configRead = configSource.Configs["AssetsRead"]; var configWrite = configSource.Configs["AssetsWrite"]; var serversRead = GetServers(configSource, configRead, _assetServersByName); var serversWrite = GetServers(configSource, configWrite, _assetServersByName); var localStorageConfig = configSource.Configs["LocalStorage"]; var chattelConfigRead = GetConfig(localStorageConfig, serversRead); var chattelConfigWrite = GetConfig(localStorageConfig, serversWrite); var serverConfig = configSource.Configs["Server"]; var address = serverConfig?.GetString("Address", WHIPServer.DEFAULT_ADDRESS) ?? WHIPServer.DEFAULT_ADDRESS; var port = (uint?)serverConfig?.GetInt("Port", (int)WHIPServer.DEFAULT_PORT) ?? WHIPServer.DEFAULT_PORT; var password = serverConfig?.GetString("Password", WHIPServer.DEFAULT_PASSWORD); if (password == null) // Would only be null if serverConfig was null or DEFAULT_PASSWORD is null. Why not use the ?? operator? Compiler didn't like it. { password = WHIPServer.DEFAULT_PASSWORD; } var listenBacklogLength = (uint?)serverConfig?.GetInt("ConnectionQueueLength", (int)WHIPServer.DEFAULT_BACKLOG_LENGTH) ?? WHIPServer.DEFAULT_BACKLOG_LENGTH; var maxAssetLocalStorageDiskSpaceByteCount = (ulong?)localStorageConfig?.GetLong("MaxDiskSpace", (long)AssetLocalStorageLmdbPartitionedLRU.DB_MAX_DISK_BYTES_MIN_RECOMMENDED) ?? AssetLocalStorageLmdbPartitionedLRU.DB_MAX_DISK_BYTES_MIN_RECOMMENDED; var negativeCacheItemLifetime = TimeSpan.FromSeconds((uint?)localStorageConfig?.GetInt("NegativeCacheItemLifetimeSeconds", (int)StorageManager.DEFAULT_NC_LIFETIME_SECONDS) ?? StorageManager.DEFAULT_NC_LIFETIME_SECONDS); var partitionInterval = TimeSpan.FromMinutes((uint?)localStorageConfig?.GetInt("MinutesBetweenDatabasePartitions", (int)DEFAULT_DB_PARTITION_INTERVAL_MINUTES) ?? DEFAULT_DB_PARTITION_INTERVAL_MINUTES); var purgeAll = startupConfig.GetString("purge", string.Empty) == "all"; if (purgeAll) { LOG.Info("CLI request to purge all assets on startup specified."); } var readerLocalStorage = new AssetLocalStorageLmdbPartitionedLRU( chattelConfigRead, maxAssetLocalStorageDiskSpaceByteCount, partitionInterval ); var chattelReader = new ChattelReader(chattelConfigRead, readerLocalStorage, purgeAll); var chattelWriter = new ChattelWriter(chattelConfigWrite, readerLocalStorage, purgeAll); var storageManager = new StorageManager( readerLocalStorage, negativeCacheItemLifetime, chattelReader, chattelWriter ); whipLru = new WhipLru( address, port, password, pidFileManager, storageManager, listenBacklogLength ); whipLru.Start(); if (signals != null) { var signalIndex = UnixSignal.WaitAny(signals, -1); switch (signals[signalIndex].Signum) { case Signum.SIGHUP: whipLru.Stop(); break; case Signum.SIGINT: case Signum.SIGKILL: isRunning = false; whipLru.Stop(); break; default: // Signal unknown, ignore it. break; } } else { waitHandle.WaitOne(); } } foreach (var server in _assetServersByName.Values) { server.Dispose(); } return(0); }
public void Init() { // Configure Log4Net XmlConfigurator.Configure(new FileInfo(Constants.LOG_CONFIG_PATH)); // Set CWD so that native libs are found. Directory.SetCurrentDirectory(TestContext.CurrentContext.TestDirectory); // Load INI stuff var configSource = new ArgvConfigSource(new string[] { }); // Configure nIni aliases and locale Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US", true); configSource.Alias.AddAlias("On", true); configSource.Alias.AddAlias("Off", false); configSource.Alias.AddAlias("True", true); configSource.Alias.AddAlias("False", false); configSource.Alias.AddAlias("Yes", true); configSource.Alias.AddAlias("No", false); // Read in the ini file configSource.Merge(new IniConfigSource(Constants.INI_PATH)); #pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body try { Directory.Delete(DATABASE_FOLDER_PATH, true); } catch (Exception) { } try { File.Delete(WRITE_CACHE_FILE_PATH); } catch (Exception) { } #pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body Directory.CreateDirectory(DATABASE_FOLDER_PATH); // Start booting server var pidFileManager = new LibWhipLru.Util.PIDFileManager(Constants.PID_FILE_PATH); var chattelConfigRead = new ChattelConfiguration(DATABASE_FOLDER_PATH); var chattelConfigWrite = new ChattelConfiguration(DATABASE_FOLDER_PATH); var readerLocalStorage = new LibWhipLru.Cache.AssetLocalStorageLmdbPartitionedLRU( chattelConfigRead, DATABASE_MAX_SIZE_BYTES, TimeSpan.FromSeconds(1) ); var chattelReader = new ChattelReader(chattelConfigRead, readerLocalStorage); var chattelWriter = new ChattelWriter(chattelConfigWrite, readerLocalStorage); var storageManager = new LibWhipLru.Cache.StorageManager( readerLocalStorage, TimeSpan.FromMinutes(2), chattelReader, chattelWriter ); _service = new WhipLru( Constants.SERVICE_ADDRESS, Constants.SERVICE_PORT, Constants.PASSWORD, pidFileManager, storageManager ); _service.Start(); }