Beispiel #1
0
        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);
            }
        }
Beispiel #2
0
        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
                );
        }
Beispiel #3
0
        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);
            }
        }
Beispiel #4
0
        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
                );
        }
Beispiel #7
0
        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);
        }
Beispiel #8
0
        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));
            }
        }
Beispiel #10
0
        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);
        }