ConfigurationWatcher.cs 4.0 KB

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