ConfigurationWatcher.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Configuration;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Reflection;
  7. using System.Text;
  8. using SuperSocket.Common;
  9. using SuperSocket.SocketBase;
  10. using SuperSocket.SocketBase.Config;
  11. namespace SuperSocket.SocketEngine
  12. {
  13. /// <summary>
  14. /// The configuration file watcher, it is used for hot configuration updating
  15. /// </summary>
  16. public static class ConfigurationWatcher
  17. {
  18. private static FileSystemWatcher m_Watcher;
  19. private static DateTime m_LastUpdatedTime;
  20. /// <summary>
  21. /// Watches the specified configuration section.
  22. /// </summary>
  23. /// <param name="configSection">The configuration section.</param>
  24. /// <param name="bootstrap">The bootstrap.</param>
  25. public static void Watch(ConfigurationSection configSection, IBootstrap bootstrap)
  26. {
  27. if (configSection == null)
  28. throw new ArgumentNullException("configSection");
  29. if (bootstrap == null)
  30. throw new ArgumentNullException("bootstrap");
  31. var sectionName = configSection.SectionInformation.Name;
  32. var configSourceFile = bootstrap.StartupConfigFile;
  33. if (string.IsNullOrEmpty(configSourceFile))
  34. throw new Exception("Cannot get your configuration file's location.");
  35. m_Watcher = new FileSystemWatcher(Path.GetDirectoryName(configSourceFile), Path.GetFileName(configSourceFile));
  36. m_Watcher.IncludeSubdirectories = false;
  37. m_Watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size;
  38. m_Watcher.Changed += (s, e) =>
  39. {
  40. var filePath = e.FullPath;
  41. if (!NeedsLoadConfig(filePath))
  42. return;
  43. lock (m_Watcher)
  44. {
  45. if (!NeedsLoadConfig(filePath))
  46. return;
  47. OnConfigFileUpdated(filePath, sectionName, bootstrap);
  48. m_LastUpdatedTime = DateTime.Now;
  49. }
  50. };
  51. m_Watcher.EnableRaisingEvents = true;
  52. }
  53. internal static void Pause()
  54. {
  55. m_Watcher.EnableRaisingEvents = false;
  56. }
  57. internal static void Resume()
  58. {
  59. m_Watcher.EnableRaisingEvents = true;
  60. }
  61. private static bool NeedsLoadConfig(string filePath)
  62. {
  63. return File.GetLastWriteTime(filePath) > m_LastUpdatedTime;
  64. }
  65. private static void OnConfigFileUpdated(string filePath, string sectionName, IBootstrap bootstrap)
  66. {
  67. var fileMap = new ExeConfigurationFileMap();
  68. fileMap.ExeConfigFilename = filePath;
  69. System.Configuration.Configuration config;
  70. try
  71. {
  72. config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
  73. }
  74. catch(Exception e)
  75. {
  76. var loggerProvider = bootstrap as ILoggerProvider;
  77. if (loggerProvider != null)
  78. {
  79. var logger = loggerProvider.Logger;
  80. if (logger != null)
  81. logger.Error("Configuraton loading error.", e);
  82. }
  83. return;
  84. }
  85. var configSource = config.GetSection(sectionName) as IConfigurationSource;
  86. if (configSource == null)
  87. return;
  88. foreach (var serverConfig in configSource.Servers)
  89. {
  90. var server = bootstrap.AppServers.FirstOrDefault(x =>
  91. x.Name.Equals(serverConfig.Name, StringComparison.OrdinalIgnoreCase));
  92. if (server == null)
  93. continue;
  94. server.ReportPotentialConfigChange(new ServerConfig(serverConfig));
  95. }
  96. }
  97. }
  98. }