Ejemplo n.º 1
0
        public static void TestChattelWriter_PutAssetSync_FullWriteCache_BadServer_AggregateException()
        {
            var server       = Substitute.For <IAssetServer>();
            var config       = new ChattelConfiguration(LOCAL_STORAGE_DIR_INFO.FullName, WRITE_CACHE_FILE_INFO.FullName, 4, server);
            var localStorage = Substitute.For <IChattelLocalStorage>();
            var writer       = new ChattelWriter(config, localStorage);

            server
            .WhenForAnyArgs(x => x.StoreAssetSync(Arg.Any <StratusAsset>()))
            .Do(x => {
                throw new Exception();                         // Just needs an error to cause remote storage failure.
            })
            ;

            var testAsset = new StratusAsset {
                Id = Guid.NewGuid(),
            };

            try {
                writer.PutAssetSync(testAsset);
            }
            catch (AggregateException) {
                // moving right along.
            }

            try {
                writer.PutAssetSync(testAsset);
            }
            catch (AggregateException) {
                // moving right along.
            }
            // Write cache currenlty requires one left empty.

            Assert.Throws <AggregateException>(() => writer.PutAssetSync(testAsset));
        }
Ejemplo n.º 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
                );
        }
Ejemplo n.º 3
0
        public static void TestChattelWriter_PutAssetSync_WritesBackupRemoteParallel_WithLocalStorage()
        {
            var server1 = Substitute.For <IAssetServer>();
            var server2 = Substitute.For <IAssetServer>();
            var config  = new ChattelConfiguration(LOCAL_STORAGE_DIR_INFO.FullName, new List <List <IAssetServer> > {
                new List <IAssetServer> {
                    server1,
                },
                new List <IAssetServer> {
                    server2,
                },
            });
            var localStorage = Substitute.For <IChattelLocalStorage>();
            var writer       = new ChattelWriter(config, localStorage);

            var testAsset = new StratusAsset {
                Id = Guid.NewGuid(),
            };

            server1.WhenForAnyArgs(x => x.StoreAssetSync(testAsset)).Do(x => throw new AssetWriteException(testAsset.Id));

            writer.PutAssetSync(testAsset);

            server2.Received(1).StoreAssetSync(testAsset);
        }
Ejemplo n.º 4
0
        public static void TestChattelWriter_PutAssetSync_ServerError_AggregateException_ContainsCorrectException()
        {
            var server       = Substitute.For <IAssetServer>();
            var config       = new ChattelConfiguration(LOCAL_STORAGE_DIR_INFO.FullName, WRITE_CACHE_FILE_INFO.FullName, 4, server);
            var localStorage = Substitute.For <IChattelLocalStorage>();
            var writer       = new ChattelWriter(config, localStorage);

            server
            .WhenForAnyArgs(x => x.StoreAssetSync(Arg.Any <StratusAsset>()))
            .Do(x => {
                throw new DriveNotFoundException();                         // Just needs an error to cause remote storage failure.
            })
            ;

            var testAsset = new StratusAsset {
                Id = Guid.NewGuid(),
            };

            try {
                writer.PutAssetSync(testAsset);
            }
            catch (AggregateException e) {
                Assert.IsInstanceOf(typeof(DriveNotFoundException), e.InnerException);
                return;
            }

            Assert.Fail();
        }
Ejemplo n.º 5
0
        public static void TestChattelWriter_PutAssetSync_MultipleParallel_AllReceived()
        {
            var server       = Substitute.For <IAssetServer>();
            var config       = new ChattelConfiguration(server);
            var localStorage = Substitute.For <IChattelLocalStorage>();
            var writer       = new ChattelWriter(config, localStorage);

            var testAsset1 = new StratusAsset {
                Id = Guid.NewGuid(),
            };

            var testAsset2 = new StratusAsset {
                Id = Guid.NewGuid(),
            };

            var testAsset3 = new StratusAsset {
                Id = Guid.NewGuid(),
            };

            Parallel.Invoke(
                () => writer.PutAssetSync(testAsset1),
                () => writer.PutAssetSync(testAsset2),
                () => writer.PutAssetSync(testAsset3)
                );

            server.Received(1).StoreAssetSync(testAsset1);
            server.Received(1).StoreAssetSync(testAsset2);
            server.Received(1).StoreAssetSync(testAsset3);
        }
Ejemplo n.º 6
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);
            }
        }
Ejemplo n.º 7
0
        public static void TestChattelWriter_PutAssetSync_WritesRemoteSeries_CorrectOrder()
        {
            var server1 = Substitute.For <IAssetServer>();
            var server2 = Substitute.For <IAssetServer>();
            var config  = new ChattelConfiguration(new List <List <IAssetServer> > {
                new List <IAssetServer> {
                    server1,
                },
                new List <IAssetServer> {
                    server2,
                },
            });
            var writer = new ChattelWriter(config);

            var testAsset = new StratusAsset {
                Id = Guid.NewGuid(),
            };

            server1.WhenForAnyArgs(x => x.StoreAssetSync(testAsset)).Do(x => throw new AssetWriteException(testAsset.Id));

            writer.PutAssetSync(testAsset);

            Received.InOrder(() => {
                server1.StoreAssetSync(testAsset);
                server2.StoreAssetSync(testAsset);
            });
        }
Ejemplo n.º 8
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);
            }
        }
Ejemplo n.º 9
0
        public static void TestWriteCache_Ctor_ExistingFile_MockWriter_MockLocalStorage_CallsLocalStorageGet()
        {
            var firstId = Guid.NewGuid();
            var lastId  = Guid.NewGuid();
            var records = new Tuple <Guid, bool>[] {
                new Tuple <Guid, bool>(firstId, false),
                new Tuple <Guid, bool>(Guid.Empty, true),
                new Tuple <Guid, bool>(lastId, true),
            };

            CreateWriteCache(WRITE_CACHE_FILE_INFO, records);

            var localStorage = Substitute.For <IChattelLocalStorage>();
            var server       = Substitute.For <IAssetServer>();
            var writer       = new ChattelWriter(new ChattelConfiguration(server), localStorage, false);

            localStorage.TryGetAsset(firstId, out var asset1).Returns(false);

            new WriteCache(
                WRITE_CACHE_FILE_INFO,
                (uint)records.Length,
                writer,
                localStorage
                );

            localStorage.Received().TryGetAsset(firstId, out var assetJunk1);
            localStorage.DidNotReceive().TryGetAsset(Guid.Empty, out var assetJunk2);
            localStorage.DidNotReceive().TryGetAsset(lastId, out var assetJunk3);
        }
Ejemplo n.º 10
0
        public static void TestChattelWriter_PutAssetSync_FullWriteCache_HitsRemote()
        {
            var server       = Substitute.For <IAssetServer>();
            var config       = new ChattelConfiguration(LOCAL_STORAGE_DIR_INFO.FullName, WRITE_CACHE_FILE_INFO.FullName, 4, server);
            var localStorage = Substitute.For <IChattelLocalStorage>();
            var writer       = new ChattelWriter(config, localStorage);

            var testAsset = new StratusAsset {
                Id = Guid.NewGuid(),
            };

            try {
                writer.PutAssetSync(testAsset);
            }
            catch (AggregateException) {
                // moving right along.
            }

            try {
                writer.PutAssetSync(testAsset);
            }
            catch (AggregateException) {
                // moving right along.
            }

            try {
                writer.PutAssetSync(testAsset);
            }
            catch (WriteCacheFullException) {
                // moving right along.
            }
            // Write cache currently requires one left empty.

            server.Received(3).StoreAssetSync(testAsset);
        }
Ejemplo n.º 11
0
        public static void TestWriteCache_Ctor_ExistingFile_MockWriter_MockLocalStorage_ClearsWriteCache()
        {
            var firstId = Guid.NewGuid();
            var lastId  = Guid.NewGuid();
            var records = new Tuple <Guid, bool>[] {
                new Tuple <Guid, bool>(firstId, false),
                new Tuple <Guid, bool>(Guid.Empty, true),
                new Tuple <Guid, bool>(lastId, true),
            };

            CreateWriteCache(WRITE_CACHE_FILE_INFO, records);

            var localStorage = Substitute.For <IChattelLocalStorage>();
            var server       = Substitute.For <IAssetServer>();
            var writer       = new ChattelWriter(new ChattelConfiguration(new List <List <IAssetServer> > {
                new List <IAssetServer> {
                    server
                }
            }), localStorage, false);

            var firstAsset = new StratusAsset {
                Id = firstId,
            };

            var lastAsset = new StratusAsset {
                Id = lastId,
            };

            localStorage.TryGetAsset(firstId, out var asset1).Returns(parms => { parms[1] = firstAsset; return(true); });
            localStorage.TryGetAsset(lastId, out var asset2).Returns(parms => { parms[1] = lastAsset; return(true); });

            localStorage.StoreAsset(firstAsset);
            localStorage.StoreAsset(lastAsset);

            new WriteCache(
                WRITE_CACHE_FILE_INFO,
                (uint)records.Length,
                writer,
                localStorage
                );

            using (var fs = new FileStream(WRITE_CACHE_FILE_INFO.FullName, FileMode.Open, FileAccess.Read)) {
                try {
                    // Skip the header
                    fs.Seek(WRITE_CACHE_MAGIC_NUMBER.Length, SeekOrigin.Begin);

                    // Check each row.
                    for (var recordIndex = 0; recordIndex < WRITE_CACHE_MAX_RECORD_COUNT; ++recordIndex)
                    {
                        var buffer = new byte[WriteCacheNode.BYTE_SIZE];
                        fs.Read(buffer, 0, buffer.Length);
                        Assert.AreEqual(0, buffer[0], $"Record #{recordIndex + 1} is not marked as available!");
                    }
                }
                finally {
                    fs.Close();
                }
            }
        }
Ejemplo n.º 12
0
        public static void TestChattelWriter_PutAssetSync_Null_ArgumentNullException()
        {
            var config = new ChattelConfiguration(LOCAL_STORAGE_DIR_INFO.FullName);

            var writer = new ChattelWriter(config);

            Assert.Throws <ArgumentNullException>(() => writer.PutAssetSync(null));
        }
Ejemplo n.º 13
0
        public static void TestChattelWriter_HasUpstream_None_False()
        {
            var config = new ChattelConfiguration(LOCAL_STORAGE_DIR_INFO.FullName);

            var writer = new ChattelWriter(config);

            Assert.False(writer.HasUpstream);
        }
Ejemplo n.º 14
0
        public static void TestChattelWriter_HasUpstream_Mocked_True()
        {
            var server = Substitute.For <IAssetServer>();
            var config = new ChattelConfiguration(server);

            var writer = new ChattelWriter(config);

            Assert.True(writer.HasUpstream);
        }
Ejemplo n.º 15
0
        public static void TestChattelWriter_PutAssetSync_EmptyId_ArgumentException()
        {
            var config = new ChattelConfiguration(LOCAL_STORAGE_DIR_INFO.FullName);

            var writer = new ChattelWriter(config);

            Assert.Throws <ArgumentException>(() => writer.PutAssetSync(new StratusAsset {
                Id = Guid.Empty,
            }));
        }
Ejemplo n.º 16
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);
        }
Ejemplo n.º 17
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);
        }
Ejemplo n.º 18
0
        public static void TestChattelWriter_PutAssetSync_WritesLocalStorage_NoRemote()
        {
            var config       = new ChattelConfiguration(LOCAL_STORAGE_DIR_INFO.FullName);
            var localStorage = Substitute.For <IChattelLocalStorage>();
            var writer       = new ChattelWriter(config, localStorage);

            var testAsset = new StratusAsset {
                Id = Guid.NewGuid(),
            };

            writer.PutAssetSync(testAsset);

            localStorage.Received(1).StoreAsset(testAsset);
        }
Ejemplo n.º 19
0
        public static void TestChattelWriter_PutAssetSync_WritesRemote_NoLocalStorage()
        {
            var server       = Substitute.For <IAssetServer>();
            var config       = new ChattelConfiguration(server);
            var localStorage = Substitute.For <IChattelLocalStorage>();
            var writer       = new ChattelWriter(config, localStorage);

            var testAsset = new StratusAsset {
                Id = Guid.NewGuid(),
            };

            writer.PutAssetSync(testAsset);

            server.Received(1).StoreAssetSync(testAsset);
        }
Ejemplo n.º 20
0
        public static void TestChattelWriter_PutAssetSync_Duplicates_AssetExistsException()
        {
            var config       = new ChattelConfiguration(LOCAL_STORAGE_DIR_INFO.FullName);
            var localStorage = Substitute.For <IChattelLocalStorage>();
            var writer       = new ChattelWriter(config, localStorage);

            var testAsset = new StratusAsset {
                Id = Guid.NewGuid(),
            };

            localStorage.TryGetAsset(testAsset.Id, out var junk).Returns(x => {
                x[1] = testAsset;
                return(true);
            });

            Assert.Throws <AssetExistsException>(() => writer.PutAssetSync(testAsset));
        }
Ejemplo n.º 21
0
        public static void TestChattelWriter_PutAssetSync_WritesLocalBeforeRemote()
        {
            var server       = Substitute.For <IAssetServer>();
            var config       = new ChattelConfiguration(LOCAL_STORAGE_DIR_INFO.FullName, WRITE_CACHE_FILE_INFO.FullName, 4, server);
            var localStorage = Substitute.For <IChattelLocalStorage>();
            var writer       = new ChattelWriter(config, localStorage);

            var testAsset = new StratusAsset {
                Id = Guid.NewGuid(),
            };

            writer.PutAssetSync(testAsset);

            Received.InOrder(() => {
                localStorage.StoreAsset(testAsset);
                server.StoreAssetSync(testAsset);
            });
        }
Ejemplo n.º 22
0
        public static void TestWriteCache_Ctor_ExistingFile_MockWriter_NullCache_ChattelConfigurationException()
        {
            var records = new Tuple <Guid, bool>[] {
                new Tuple <Guid, bool>(Guid.NewGuid(), false),
                new Tuple <Guid, bool>(Guid.NewGuid(), false),
            };

            CreateWriteCache(WRITE_CACHE_FILE_INFO, records);

            var localStorage = Substitute.For <IChattelLocalStorage>();
            var server       = Substitute.For <IAssetServer>();
            var writer       = new ChattelWriter(new ChattelConfiguration(server), localStorage, false);

            Assert.Throws <ChattelConfigurationException>(() => new WriteCache(
                                                              WRITE_CACHE_FILE_INFO,
                                                              (uint)records.Length,
                                                              writer,
                                                              null
                                                              ));
        }
Ejemplo n.º 23
0
        public static void TestChattelWriter_PutAssetSync_ServerError_AggregateException()
        {
            var server       = Substitute.For <IAssetServer>();
            var config       = new ChattelConfiguration(LOCAL_STORAGE_DIR_INFO.FullName, WRITE_CACHE_FILE_INFO.FullName, 4, server);
            var localStorage = Substitute.For <IChattelLocalStorage>();
            var writer       = new ChattelWriter(config, localStorage);

            server
            .WhenForAnyArgs(x => x.StoreAssetSync(Arg.Any <StratusAsset>()))
            .Do(x => {
                throw new Exception();                         // Just needs an error to cause remote storage failure.
            })
            ;

            var testAsset = new StratusAsset {
                Id = Guid.NewGuid(),
            };

            Assert.Throws <AggregateException>(() => writer.PutAssetSync(testAsset));
        }
Ejemplo n.º 24
0
        /// <summary>
        /// Initializes a new instance of the <see cref="T:LibWhipLru.Cache.StorageManager"/> class.
        /// A zero or negative value for the negativeCacheItemLifetime results in the negative cache being disabled.
        /// </summary>
        /// <param name="localStorage">Local storage for assets.</param>
        /// <param name="negativeCacheItemLifetime">Negative cache item lifetime.</param>
        /// <param name="reader">Reader.</param>
        /// <param name="writer">Writer.</param>
        public StorageManager(
            AssetLocalStorageLmdbPartitionedLRU localStorage,
            TimeSpan negativeCacheItemLifetime,
            ChattelReader reader,
            ChattelWriter writer
            )
        {
            _localStorage = localStorage ?? throw new ArgumentNullException(nameof(localStorage));
            _assetReader  = reader ?? throw new ArgumentNullException(nameof(reader));
            _assetWriter  = writer ?? throw new ArgumentNullException(nameof(writer));

            if (negativeCacheItemLifetime.TotalSeconds > 0)
            {
                _negativeCache     = System.Runtime.Caching.MemoryCache.Default;
                _negativeCacheLock = new ReaderWriterLockSlim();

                _negativeCachePolicy = new System.Runtime.Caching.CacheItemPolicy {
                    SlidingExpiration = negativeCacheItemLifetime,
                };
            }
        }
Ejemplo n.º 25
0
        public static void TestWriteCache_Ctor_ExistingFile_MockWriter_MockLocalStorage_CallsServerStore()
        {
            var firstId = Guid.NewGuid();
            var lastId  = Guid.NewGuid();
            var records = new Tuple <Guid, bool>[] {
                new Tuple <Guid, bool>(firstId, false),
                new Tuple <Guid, bool>(Guid.Empty, true),
                new Tuple <Guid, bool>(lastId, true),
            };

            CreateWriteCache(WRITE_CACHE_FILE_INFO, records);

            var localStorage = Substitute.For <IChattelLocalStorage>();
            var server       = Substitute.For <IAssetServer>();
            var writer       = new ChattelWriter(new ChattelConfiguration(server), localStorage, false);

            var firstAsset = new StratusAsset {
                Id = firstId,
            };

            var lastAsset = new StratusAsset {
                Id = lastId,
            };

            localStorage.TryGetAsset(firstId, out var asset1).Returns(parms => { parms[1] = firstAsset; return(true); });
            localStorage.TryGetAsset(lastId, out var asset2).Returns(parms => { parms[1] = lastAsset; return(true); });

            localStorage.StoreAsset(firstAsset);
            localStorage.StoreAsset(lastAsset);

            new WriteCache(
                WRITE_CACHE_FILE_INFO,
                (uint)records.Length,
                writer,
                localStorage
                );

            server.Received().StoreAssetSync(firstAsset);
            server.DidNotReceive().StoreAssetSync(lastAsset);
        }
Ejemplo n.º 26
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);
        }
Ejemplo n.º 27
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();
        }