ClusterRegistry.cs 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. /* Copyright 2010-present MongoDB Inc.
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. using System.Collections.Generic;
  16. using System.Linq;
  17. using System.Net;
  18. using System.Net.Security;
  19. using System.Net.Sockets;
  20. using System.Security.Cryptography.X509Certificates;
  21. using MongoDB.Driver.Core.Authentication;
  22. using MongoDB.Driver.Core.Clusters;
  23. using MongoDB.Driver.Core.Clusters.ServerSelectors;
  24. using MongoDB.Driver.Core.Configuration;
  25. using MongoDB.Driver.Core.ConnectionPools;
  26. using MongoDB.Driver.Core.Connections;
  27. using MongoDB.Driver.Core.Events;
  28. using MongoDB.Driver.Core.Events.Diagnostics;
  29. using MongoDB.Driver.Core.Misc;
  30. using MongoDB.Driver.Core.Servers;
  31. namespace MongoDB.Driver
  32. {
  33. /// <summary>
  34. /// Represents a registry of already created clusters.
  35. /// </summary>
  36. public class ClusterRegistry
  37. {
  38. #region static
  39. // static fields
  40. private static readonly ClusterRegistry __instance = new ClusterRegistry();
  41. // static properties
  42. /// <summary>
  43. /// Gets the default cluster registry.
  44. /// </summary>
  45. /// <value>
  46. /// The default cluster registry.
  47. /// </value>
  48. public static ClusterRegistry Instance
  49. {
  50. get { return __instance; }
  51. }
  52. #endregion
  53. // fields
  54. private readonly object _lock = new object();
  55. private readonly Dictionary<ClusterKey, ICluster> _registry = new Dictionary<ClusterKey, ICluster>();
  56. // methods
  57. private ICluster CreateCluster(ClusterKey clusterKey)
  58. {
  59. var builder = new ClusterBuilder()
  60. .ConfigureCluster(settings => ConfigureCluster(settings, clusterKey))
  61. .ConfigureServer(settings => ConfigureServer(settings, clusterKey))
  62. .ConfigureConnectionPool(settings => ConfigureConnectionPool(settings, clusterKey))
  63. .ConfigureConnection(settings => ConfigureConnection(settings, clusterKey))
  64. .ConfigureTcp(settings => ConfigureTcp(settings, clusterKey))
  65. .ConfigureSdamLogging(settings => ConfigureSdamLogging(settings, clusterKey));
  66. if (clusterKey.UseSsl)
  67. {
  68. builder.ConfigureSsl(settings => ConfigureSsl(settings, clusterKey));
  69. }
  70. if (clusterKey.ClusterConfigurator != null)
  71. {
  72. clusterKey.ClusterConfigurator(builder);
  73. }
  74. var cluster = builder.BuildCluster();
  75. cluster.Initialize();
  76. return cluster;
  77. }
  78. private ClusterSettings ConfigureCluster(ClusterSettings settings, ClusterKey clusterKey)
  79. {
  80. var endPoints = clusterKey.Servers.Select(s => EndPointHelper.Parse(s.ToString()));
  81. return settings.With(
  82. connectionMode: clusterKey.ConnectionMode.ToCore(),
  83. endPoints: Optional.Enumerable(endPoints),
  84. replicaSetName: clusterKey.ReplicaSetName,
  85. maxServerSelectionWaitQueueSize: clusterKey.WaitQueueSize,
  86. serverSelectionTimeout: clusterKey.ServerSelectionTimeout,
  87. postServerSelector: new LatencyLimitingServerSelector(clusterKey.LocalThreshold));
  88. }
  89. private ConnectionPoolSettings ConfigureConnectionPool(ConnectionPoolSettings settings, ClusterKey clusterKey)
  90. {
  91. return settings.With(
  92. // maintenanceInterval: TODO: should this be configurable?
  93. maxConnections: clusterKey.MaxConnectionPoolSize,
  94. minConnections: clusterKey.MinConnectionPoolSize,
  95. waitQueueSize: clusterKey.WaitQueueSize,
  96. waitQueueTimeout: clusterKey.WaitQueueTimeout);
  97. }
  98. private ConnectionSettings ConfigureConnection(ConnectionSettings settings, ClusterKey clusterKey)
  99. {
  100. var authenticators = clusterKey.Credentials.Select(c => c.ToAuthenticator());
  101. return settings.With(
  102. authenticators: Optional.Enumerable(authenticators),
  103. maxIdleTime: clusterKey.MaxConnectionIdleTime,
  104. maxLifeTime: clusterKey.MaxConnectionLifeTime,
  105. applicationName: clusterKey.ApplicationName);
  106. }
  107. private SdamLoggingSettings ConfigureSdamLogging(SdamLoggingSettings settings, ClusterKey clusterKey)
  108. {
  109. return settings.With(logFilename: clusterKey.SdamLogFilename);
  110. }
  111. private ServerSettings ConfigureServer(ServerSettings settings, ClusterKey clusterKey)
  112. {
  113. return settings.With(
  114. heartbeatInterval: clusterKey.HeartbeatInterval,
  115. heartbeatTimeout: clusterKey.HeartbeatTimeout);
  116. }
  117. private SslStreamSettings ConfigureSsl(SslStreamSettings settings, ClusterKey clusterKey)
  118. {
  119. if (clusterKey.UseSsl)
  120. {
  121. var sslSettings = clusterKey.SslSettings ?? new SslSettings();
  122. var validationCallback = sslSettings.ServerCertificateValidationCallback;
  123. if (validationCallback == null && !clusterKey.VerifySslCertificate)
  124. {
  125. validationCallback = AcceptAnySslCertificate;
  126. }
  127. return settings.With(
  128. clientCertificates: Optional.Enumerable(sslSettings.ClientCertificates ?? Enumerable.Empty<X509Certificate>()),
  129. checkCertificateRevocation: sslSettings.CheckCertificateRevocation,
  130. clientCertificateSelectionCallback: sslSettings.ClientCertificateSelectionCallback,
  131. enabledProtocols: sslSettings.EnabledSslProtocols,
  132. serverCertificateValidationCallback: validationCallback);
  133. }
  134. return settings;
  135. }
  136. private TcpStreamSettings ConfigureTcp(TcpStreamSettings settings, ClusterKey clusterKey)
  137. {
  138. if (clusterKey.IPv6)
  139. {
  140. settings = settings.With(addressFamily: AddressFamily.InterNetworkV6);
  141. }
  142. return settings.With(
  143. connectTimeout: clusterKey.ConnectTimeout,
  144. readTimeout: clusterKey.SocketTimeout,
  145. receiveBufferSize: clusterKey.ReceiveBufferSize,
  146. sendBufferSize: clusterKey.SendBufferSize,
  147. writeTimeout: clusterKey.SocketTimeout);
  148. }
  149. internal ICluster GetOrCreateCluster(ClusterKey clusterKey)
  150. {
  151. lock (_lock)
  152. {
  153. ICluster cluster;
  154. if (!_registry.TryGetValue(clusterKey, out cluster))
  155. {
  156. cluster = CreateCluster(clusterKey);
  157. _registry.Add(clusterKey, cluster);
  158. }
  159. return cluster;
  160. }
  161. }
  162. private static bool AcceptAnySslCertificate(
  163. object sender,
  164. X509Certificate certificate,
  165. X509Chain chain,
  166. SslPolicyErrors sslPolicyErrors
  167. )
  168. {
  169. return true;
  170. }
  171. /// <summary>
  172. /// Unregisters and disposes the cluster.
  173. /// </summary>
  174. /// <param name="cluster">The cluster.</param>
  175. public void UnregisterAndDisposeCluster(ICluster cluster)
  176. {
  177. Ensure.IsNotNull(cluster, nameof(cluster));
  178. lock (_lock)
  179. {
  180. ClusterKey clusterKey = null;
  181. foreach (var keyValuePair in _registry)
  182. {
  183. if (object.ReferenceEquals(keyValuePair.Value, cluster))
  184. {
  185. clusterKey = keyValuePair.Key;
  186. break;
  187. }
  188. }
  189. if (clusterKey != null)
  190. {
  191. _registry.Remove(clusterKey);
  192. }
  193. }
  194. cluster.Dispose();
  195. }
  196. }
  197. }