示例#1
0
        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);
        }
示例#2
0
        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();
        }
示例#3
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);
        }
示例#4
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();
        }