public static void TestStorageManager_GetAsset_DoubleNoExist_CallsServerRequestOnlyOnce() { LOG.Info($"Executing {nameof(TestStorageManager_GetAsset_DoubleNoExist_CallsServerRequestOnlyOnce)}"); // Tests the existence of a negative cache. var server = Substitute.For <IAssetServer>(); var config = new ChattelConfiguration(TestAssetLocalStorageLmdbPartitionedLRUCtor.DATABASE_FOLDER_PATH, WRITE_CACHE_FILE_PATH, WRITE_CACHE_MAX_RECORD_COUNT, server); using (var localStorage = new AssetLocalStorageLmdbPartitionedLRU( config, TestAssetLocalStorageLmdbPartitionedLRUCtor.DATABASE_MAX_SIZE_BYTES, TestAssetLocalStorageLmdbPartitionedLRUCtor.DATABASE_PARTITION_INTERVAL )) { var reader = new ChattelReader(config, localStorage, false); var writer = new ChattelWriter(config, localStorage, false); var assetId = Guid.NewGuid(); var mgr = new StorageManager( localStorage, TimeSpan.FromMinutes(2), reader, writer ); mgr.GetAsset(assetId, result => { }, () => { }); mgr.GetAsset(assetId, result => { }, () => { }); server.Received(1).RequestAssetSync(assetId); } }
public static void BeforeEveryTest() { #pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body try { Directory.Delete(TestAssetLocalStorageLmdbPartitionedLRUCtor.DATABASE_FOLDER_PATH, true); } catch { } #pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body Directory.CreateDirectory(TestAssetLocalStorageLmdbPartitionedLRUCtor.DATABASE_FOLDER_PATH); var chattelConfigRead = new ChattelConfiguration(TestAssetLocalStorageLmdbPartitionedLRUCtor.DATABASE_FOLDER_PATH); var chattelConfigWrite = new ChattelConfiguration(TestAssetLocalStorageLmdbPartitionedLRUCtor.DATABASE_FOLDER_PATH); _readerLocalStorage = new AssetLocalStorageLmdbPartitionedLRU( chattelConfigRead, TestAssetLocalStorageLmdbPartitionedLRUCtor.DATABASE_MAX_SIZE_BYTES, TestAssetLocalStorageLmdbPartitionedLRUCtor.DATABASE_PARTITION_INTERVAL ); _chattelReader = new ChattelReader(chattelConfigRead, _readerLocalStorage); _chattelWriter = new ChattelWriter(chattelConfigWrite, _readerLocalStorage); _storageManager = new StorageManager( _readerLocalStorage, TimeSpan.FromMinutes(2), _chattelReader, _chattelWriter ); }
public static void TestStorageManager_StoreAsset_CallsServerPutAsset() { LOG.Info($"Executing {nameof(TestStorageManager_StoreAsset_CallsServerPutAsset)}"); var server = Substitute.For <IAssetServer>(); var config = new ChattelConfiguration(TestAssetLocalStorageLmdbPartitionedLRUCtor.DATABASE_FOLDER_PATH, server); using (var readerLocalStorage = new AssetLocalStorageLmdbPartitionedLRU( config, uint.MaxValue, TestAssetLocalStorageLmdbPartitionedLRUCtor.DATABASE_PARTITION_INTERVAL )) { var reader = new ChattelReader(config, readerLocalStorage); var writer = new ChattelWriter(config, readerLocalStorage); var mgr = new StorageManager( readerLocalStorage, TimeSpan.FromMinutes(2), reader, writer ); var asset = new StratusAsset { Id = Guid.NewGuid(), }; var wait = new AutoResetEvent(false); mgr.StoreAsset(asset, result => wait.Set()); wait.WaitOne(); server.Received(1).StoreAssetSync(asset); } }
public static void CleanupAfterEveryTest() { IDisposable readerDispose = _readerLocalStorage; _readerLocalStorage = null; readerDispose.Dispose(); Directory.Delete(TestAssetLocalStorageLmdbPartitionedLRUCtor.DATABASE_FOLDER_PATH, true); }
public static void CleanupAfterEveryTest() { _localStorage = null; IDisposable localStorageDisposal = _localStorageLmdb; _localStorageLmdb = null; localStorageDisposal.Dispose(); TestAssetLocalStorageLmdbPartitionedLRUCtor.CleanLocalStorageFolder(DATABASE_FOLDER_PATH, TestStorageManager.WRITE_CACHE_FILE_PATH); }
public static void BeforeEveryTest() { TestAssetLocalStorageLmdbPartitionedLRUCtor.RebuildLocalStorageFolder(DATABASE_FOLDER_PATH, TestStorageManager.WRITE_CACHE_FILE_PATH); _localStorage = _localStorageLmdb = new AssetLocalStorageLmdbPartitionedLRU( _chattelConfigRead, DATABASE_MAX_SIZE_BYTES, TestAssetLocalStorageLmdbPartitionedLRUCtor.DATABASE_PARTITION_INTERVAL ); }
public static void CleanupAfterEveryTest() { LOG.Info($"Executing {nameof(CleanupAfterEveryTest)}"); _chattelReader = null; _chattelWriter = null; IDisposable localStorageDisposal = _readerLocalStorage; _readerLocalStorage = null; localStorageDisposal.Dispose(); TestAssetLocalStorageLmdbPartitionedLRUCtor.CleanLocalStorageFolder(TestAssetLocalStorageLmdbPartitionedLRUCtor.DATABASE_FOLDER_PATH, WRITE_CACHE_FILE_PATH); }
public static void BeforeEveryTest() { LOG.Info($"Executing {nameof(BeforeEveryTest)}"); TestAssetLocalStorageLmdbPartitionedLRUCtor.RebuildLocalStorageFolder(TestAssetLocalStorageLmdbPartitionedLRUCtor.DATABASE_FOLDER_PATH, WRITE_CACHE_FILE_PATH); _readerLocalStorage = new AssetLocalStorageLmdbPartitionedLRU( _chattelConfigRead, TestAssetLocalStorageLmdbPartitionedLRUCtor.DATABASE_MAX_SIZE_BYTES, TestAssetLocalStorageLmdbPartitionedLRUCtor.DATABASE_PARTITION_INTERVAL ); _chattelReader = new ChattelReader(_chattelConfigRead, _readerLocalStorage); _chattelWriter = new ChattelWriter(_chattelConfigWrite, _readerLocalStorage); }
public static void TestAssetLocalStorageLmdbPartitionedLRU_Ctor2_RestoresIndex() { var asset = new StratusAsset { Id = Guid.NewGuid(), }; using (var localStorage = new AssetLocalStorageLmdbPartitionedLRU( _chattelConfigRead, DATABASE_MAX_SIZE_BYTES, DATABASE_PARTITION_INTERVAL )) { IChattelLocalStorage localStorageViaInterface = localStorage; localStorageViaInterface.StoreAsset(asset); } using (var localStorage = new AssetLocalStorageLmdbPartitionedLRU( _chattelConfigRead, DATABASE_MAX_SIZE_BYTES, DATABASE_PARTITION_INTERVAL )) { Assert.True(localStorage.Contains(asset.Id)); } }
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); }