using System; using System.Collections.Generic; using System.Configuration; using System.IO; using System.Linq; using System.Reflection; using System.Text; using SuperSocket.Common; using SuperSocket.SocketBase; using SuperSocket.SocketBase.Config; namespace SuperSocket.SocketEngine { /// /// The configuration file watcher, it is used for hot configuration updating /// public static class ConfigurationWatcher { private static FileSystemWatcher m_Watcher; private static DateTime m_LastUpdatedTime; /// /// Watches the specified configuration section. /// /// The configuration section. /// The bootstrap. public static void Watch(ConfigurationSection configSection, IBootstrap bootstrap) { if (configSection == null) throw new ArgumentNullException("configSection"); if (bootstrap == null) throw new ArgumentNullException("bootstrap"); var sectionName = configSection.SectionInformation.Name; var configSourceFile = bootstrap.StartupConfigFile; if (string.IsNullOrEmpty(configSourceFile)) throw new Exception("Cannot get your configuration file's location."); m_Watcher = new FileSystemWatcher(Path.GetDirectoryName(configSourceFile), Path.GetFileName(configSourceFile)); m_Watcher.IncludeSubdirectories = false; m_Watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size; m_Watcher.Changed += (s, e) => { var filePath = e.FullPath; if (!NeedsLoadConfig(filePath)) return; lock (m_Watcher) { if (!NeedsLoadConfig(filePath)) return; OnConfigFileUpdated(filePath, sectionName, bootstrap); m_LastUpdatedTime = DateTime.Now; } }; m_Watcher.EnableRaisingEvents = true; } internal static void Pause() { m_Watcher.EnableRaisingEvents = false; } internal static void Resume() { m_Watcher.EnableRaisingEvents = true; } private static bool NeedsLoadConfig(string filePath) { return File.GetLastWriteTime(filePath) > m_LastUpdatedTime; } private static void OnConfigFileUpdated(string filePath, string sectionName, IBootstrap bootstrap) { var fileMap = new ExeConfigurationFileMap(); fileMap.ExeConfigFilename = filePath; System.Configuration.Configuration config; try { config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None); } catch(Exception e) { var loggerProvider = bootstrap as ILoggerProvider; if (loggerProvider != null) { var logger = loggerProvider.Logger; if (logger != null) logger.Error("Configuraton loading error.", e); } return; } var configSource = config.GetSection(sectionName) as IConfigurationSource; if (configSource == null) return; foreach (var serverConfig in configSource.Servers) { var server = bootstrap.AppServers.FirstOrDefault(x => x.Name.Equals(serverConfig.Name, StringComparison.OrdinalIgnoreCase)); if (server == null) continue; server.ReportPotentialConfigChange(new ServerConfig(serverConfig)); } } } }