Ejemplo n.º 1
0
        private bool reinitialize()
        {
            // If we are already initialized and the settings file hasn’t changed, we don’t need to do anything.
            var firstRunEver = _server == null;

            if (_server != null && File.GetLastWriteTimeUtc(_settingsPath) <= _settingsLastChangedTime)
            {
                return(false);
            }

            // This may load *and re-write* the settings file...
            var newSettings = PropellerUtil.LoadSettings(_settingsPath, firstRunEver ? new ConsoleLogger() : _log, firstRunEver);

            // ... so remember the file date/time stamp *after* the writing
            _settingsLastChangedTime = File.GetLastWriteTimeUtc(_settingsPath);

            _log = PropellerUtil.GetLogger(true, newSettings.LogFile, newSettings.LogVerbosity);
            _log.Info(firstRunEver ? "Initializing Propeller" : "Reinitializing Propeller");

            // If either port number or the bind-to address have changed, stop and restart the server’s listener.
            var startListening = false;

            if (_server == null || CurrentSettings == null ||
                !CurrentSettings.ServerOptions.Endpoints.Values.SequenceEqual(newSettings.ServerOptions.Endpoints.Values))
            {
                var removed = CurrentSettings == null ? new HttpEndpoint[0] : CurrentSettings.ServerOptions.Endpoints.Values.Except(newSettings.ServerOptions.Endpoints.Values).ToArray();
                var added   = CurrentSettings == null?newSettings.ServerOptions.Endpoints.Values.ToArray() : newSettings.ServerOptions.Endpoints.Values.Except(CurrentSettings.ServerOptions.Endpoints.Values).ToArray();

                if (_server == null || removed.Length > 0 || added.Length > 0)
                {
                    if (removed.Length > 0)
                    {
                        _log.Info("Disabling {0}".Fmt(removed.Select(ep => "HTTP{0} on port {1}".Fmt(ep.Secure ? "S" : null, ep.Port)).JoinString(", ", lastSeparator: " and ")));
                    }
                    if (added.Length > 0)
                    {
                        _log.Info("Enabling {0}".Fmt(added.Select(ep => "HTTP{0} on port {1}".Fmt(ep.Secure ? "S" : null, ep.Port)).JoinString(", ", lastSeparator: " and ")));
                    }

                    if (_server == null)
                    {
                        _server = new HttpServer
                        {
                            Options                  = newSettings.ServerOptions,
                            ErrorHandler             = errorHandler,
                            ResponseExceptionHandler = responseExceptionHandler
                        }
                    }
                    ;
                    else
                    {
                        _server.StopListening();
                    }
                    startListening = true;
                }
            }

            CurrentSettings = newSettings;

            // Create a new instance of all the modules
            var newAppDomains = new HashSet <AppDomainInfo>();

            foreach (var module in newSettings.Modules)
            {
                _log.Info("Initializing module: " + module.ModuleName);
                try
                {
                    var inf = new AppDomainInfo(_log, newSettings, module, new SettingsSaver(s =>
                    {
                        module.Settings        = s;
                        _settingsSavedByModule = true;
                    }));
                    newAppDomains.Add(inf);
                }
                catch (Exception e)
                {
                    _log.Error("Failed to initialize module {0}:".Fmt(module.ModuleName));
                    _log.Exception(e);
                }
            }

            // Switcheroo!
            lock (_lockObject)
            {
                _log.Info("AppDomain Switcheroo");
                _inactiveAppDomains.AddRange(_activeAppDomains);
                _activeAppDomains = newAppDomains;
                _server.Options   = newSettings.ServerOptions;
                _server.Handler   = createResolver().Handle;
                _server.Log       = PropellerUtil.GetLogger(newSettings.HttpAccessLogToConsole, newSettings.HttpAccessLogFile, newSettings.HttpAccessLogVerbosity);
                if (startListening)
                {
                    _server.StartListening();
                }
            }

            // Delete any remaining temp folders no longer in use
            HashSet <string> tempFoldersInUse;

            lock (_lockObject)
                tempFoldersInUse = _activeAppDomains.Concat(_inactiveAppDomains).Select(ad => ad.TempPathUsed).ToHashSet();
            foreach (var tempFolder in Directory.EnumerateDirectories(CurrentSettings.TempFolder ?? Path.GetTempPath(), "propeller-tmp-*"))
            {
                if (tempFoldersInUse.Contains(tempFolder))
                {
                    continue;
                }
                try { Directory.Delete(tempFolder, recursive: true); }
                catch { }
            }

            return(true);
        }
Ejemplo n.º 2
0
        private static int _appDomainCount = 0;     // only used to give each AppDomain a unique name

        public AppDomainInfo(LoggerBase log, PropellerSettings settings, PropellerModuleSettings moduleSettings, ISettingsSaver saver)
        {
            ModuleSettings     = moduleSettings;
            Saver              = saver;
            _log               = log;
            _activeConnections = 0;

            // Determine the temporary folder that DLLs will be copied to
            var tempFolder = settings.TempFolder ?? Path.GetTempPath();

            Directory.CreateDirectory(tempFolder);

            // Find a new folder to put the DLL/EXE files into
            int j = 1;

            do
            {
                TempPathUsed = Path.Combine(tempFolder, "propeller-tmp-" + (j++));
            }while (Directory.Exists(TempPathUsed));
            Directory.CreateDirectory(TempPathUsed);

            // Copy all the DLLs/EXEs to the temporary folder
            foreach (var sourceFile in
                     new[] { typeof(PropellerEngine), typeof(IPropellerModule), typeof(HttpServer), typeof(Ut) }.Select(type => type.Assembly.Location).Concat(
                         new[] { "*.exe", "*.dll", "*.pdb" }.SelectMany(ext => Directory.EnumerateFiles(Path.GetDirectoryName(moduleSettings.ModuleDll), ext))))
            {
                var destFile = Path.Combine(TempPathUsed, Path.GetFileName(sourceFile));
                if (File.Exists(destFile))
                {
                    _log.Warn(2, "Skipping file {0} because destination file {1} already exists.".Fmt(sourceFile, destFile));
                }
                else
                {
                    _log.Info(2, "Copying file {0} to {1}".Fmt(sourceFile, destFile));
                    File.Copy(sourceFile, destFile);
                }
            }

            // Create an AppDomain
            var setup = new AppDomainSetup {
                ApplicationBase = TempPathUsed, PrivateBinPath = TempPathUsed
            };

            AppDomain   = AppDomain.CreateDomain("Propeller AppDomain #{0}, module {1}".Fmt(_appDomainCount++, moduleSettings.ModuleName), null, setup);
            RunnerProxy = (AppDomainRunner)AppDomain.CreateInstanceAndUnwrap("Propeller", "RT.Propeller.AppDomainRunner");
            RunnerProxy.Init(
                Path.Combine(TempPathUsed, Path.GetFileName(moduleSettings.ModuleDll)),
                moduleSettings.ModuleType,
                moduleSettings.ModuleName,
                moduleSettings.Settings,
                _log,
                saver);

            IEnumerable <string> filters = moduleSettings.MonitorFilters ?? Enumerable.Empty <string>();

            if (RunnerProxy.FileFiltersToBeMonitoredForChanges != null)
            {
                filters = filters.Concat(RunnerProxy.FileFiltersToBeMonitoredForChanges);
            }
            foreach (var filter in filters.Concat(moduleSettings.ModuleDll))
            {
                addFileSystemWatcher(Path.GetDirectoryName(filter), Path.GetFileName(filter));
            }

            UrlMappings = moduleSettings.Hooks.Select(hook => new UrlMapping(hook, Handle, true)).ToArray();

            _log.Info("Module {0} URLs: {1}".Fmt(moduleSettings.ModuleName, moduleSettings.Hooks.JoinString("; ")));
        }