Skip to content

Commit

Permalink
CSHARP-589: isolating the core from the public api.
Browse files Browse the repository at this point in the history
  • Loading branch information
craiggwilson committed Dec 18, 2012
1 parent 7be9756 commit f7bdc76
Show file tree
Hide file tree
Showing 10 changed files with 117 additions and 121 deletions.
39 changes: 19 additions & 20 deletions MongoDB.Driver/Communication/MongoConnection.cs
Expand Up @@ -198,10 +198,10 @@ internal void Authenticate(string databaseName, MongoCredentials credentials)
// (with the restriction that a particular database can only be authenticated against once and therefore with only one set of credentials) // (with the restriction that a particular database can only be authenticated against once and therefore with only one set of credentials)


// assume that IsAuthenticated was called first and returned false // assume that IsAuthenticated was called first and returned false
internal bool CanAuthenticate(MongoDatabase database) internal bool CanAuthenticate(string databaseName, MongoCredentials credentials)
{ {
if (_state == MongoConnectionState.Closed) { throw new InvalidOperationException("Connection is closed."); } if (_state == MongoConnectionState.Closed) { throw new InvalidOperationException("Connection is closed."); }
if (database == null) if (databaseName == null)
{ {
return true; return true;
} }
Expand All @@ -214,13 +214,13 @@ internal bool CanAuthenticate(MongoDatabase database)
else else
{ {
// a connection with existing authentications can't be used without credentials // a connection with existing authentications can't be used without credentials
if (database.Credentials == null) if (credentials == null)
{ {
return false; return false;
} }


// a connection with existing authentications can't be used with new admin credentials // a connection with existing authentications can't be used with new admin credentials
if (database.Credentials.Admin) if (credentials.Admin)
{ {
return false; return false;
} }
Expand All @@ -232,7 +232,7 @@ internal bool CanAuthenticate(MongoDatabase database)
} }


// a connection with an existing authentication to a database can't authenticate for the same database again // a connection with an existing authentication to a database can't authenticate for the same database again
if (_authentications.ContainsKey(database.Name)) if (_authentications.ContainsKey(databaseName))
{ {
return false; return false;
} }
Expand All @@ -241,10 +241,10 @@ internal bool CanAuthenticate(MongoDatabase database)
} }
} }


internal void CheckAuthentication(MongoDatabase database) internal void CheckAuthentication(string databaseName, MongoCredentials credentials)
{ {
if (_state == MongoConnectionState.Closed) { throw new InvalidOperationException("Connection is closed."); } if (_state == MongoConnectionState.Closed) { throw new InvalidOperationException("Connection is closed."); }
if (database.Credentials == null) if (credentials == null)
{ {
if (_authentications.Count != 0) if (_authentications.Count != 0)
{ {
Expand All @@ -253,12 +253,11 @@ internal void CheckAuthentication(MongoDatabase database)
} }
else else
{ {
var credentials = database.Credentials; var authenticationDatabaseName = credentials.Admin ? "admin" : databaseName;
var authenticationDatabaseName = credentials.Admin ? "admin" : database.Name;
Authentication authentication; Authentication authentication;
if (_authentications.TryGetValue(authenticationDatabaseName, out authentication)) if (_authentications.TryGetValue(authenticationDatabaseName, out authentication))
{ {
if (authentication.Credentials != database.Credentials) if (authentication.Credentials != credentials)
{ {
// this shouldn't happen because a connection would have been chosen from the connection pool only if it was viable // this shouldn't happen because a connection would have been chosen from the connection pool only if it was viable
if (authenticationDatabaseName == "admin") if (authenticationDatabaseName == "admin")
Expand All @@ -279,7 +278,7 @@ internal void CheckAuthentication(MongoDatabase database)
// this shouldn't happen because a connection would have been chosen from the connection pool only if it was viable // this shouldn't happen because a connection would have been chosen from the connection pool only if it was viable
throw new MongoInternalException("The connection cannot be authenticated against the admin database because it is already authenticated against other databases."); throw new MongoInternalException("The connection cannot be authenticated against the admin database because it is already authenticated against other databases.");
} }
Authenticate(authenticationDatabaseName, database.Credentials); Authenticate(authenticationDatabaseName, credentials);
} }
} }
} }
Expand Down Expand Up @@ -310,27 +309,27 @@ internal void Close()
} }
} }


internal bool IsAuthenticated(MongoDatabase database) internal bool IsAuthenticated(string databaseName, MongoCredentials credentials)
{ {
if (_state == MongoConnectionState.Closed) { throw new InvalidOperationException("Connection is closed."); } if (_state == MongoConnectionState.Closed) { throw new InvalidOperationException("Connection is closed."); }
if (database == null) if (databaseName == null)
{ {
return true; return true;
} }


lock (_connectionLock) lock (_connectionLock)
{ {
if (database.Credentials == null) if (credentials == null)
{ {
return _authentications.Count == 0; return _authentications.Count == 0;
} }
else else
{ {
var authenticationDatabaseName = database.Credentials.Admin ? "admin" : database.Name; var authenticationDatabaseName = credentials.Admin ? "admin" : databaseName;
Authentication authentication; Authentication authentication;
if (_authentications.TryGetValue(authenticationDatabaseName, out authentication)) if (_authentications.TryGetValue(authenticationDatabaseName, out authentication))
{ {
return database.Credentials == authentication.Credentials; return credentials == authentication.Credentials;
} }
else else
{ {
Expand Down Expand Up @@ -373,10 +372,10 @@ internal void Open()
tcpClient.Connect(ipEndPoint); tcpClient.Connect(ipEndPoint);


var stream = (Stream)tcpClient.GetStream(); var stream = (Stream)tcpClient.GetStream();
if (_serverInstance.Server.Settings.UseSsl) if (_serverInstance.Settings.UseSsl)
{ {
SslStream sslStream; SslStream sslStream;
if (_serverInstance.Server.Settings.VerifySslCertificate) if (_serverInstance.Settings.VerifySslCertificate)
{ {
sslStream = new SslStream(stream, false); // don't leave inner stream open sslStream = new SslStream(stream, false); // don't leave inner stream open
} }
Expand Down Expand Up @@ -458,7 +457,7 @@ internal void Open()
using (var buffer = new BsonBuffer()) using (var buffer = new BsonBuffer())
{ {
var networkStream = GetNetworkStream(); var networkStream = GetNetworkStream();
var readTimeout = (int)_serverInstance.Server.Settings.SocketTimeout.TotalMilliseconds; var readTimeout = (int)_serverInstance.Settings.SocketTimeout.TotalMilliseconds;
if (readTimeout != 0) if (readTimeout != 0)
{ {
networkStream.ReadTimeout = readTimeout; networkStream.ReadTimeout = readTimeout;
Expand Down Expand Up @@ -511,7 +510,7 @@ internal WriteConcernResult SendMessage(MongoRequestMessage message, WriteConcer
try try
{ {
var networkStream = GetNetworkStream(); var networkStream = GetNetworkStream();
var writeTimeout = (int)_serverInstance.Server.Settings.SocketTimeout.TotalMilliseconds; var writeTimeout = (int)_serverInstance.Settings.SocketTimeout.TotalMilliseconds;
if (writeTimeout != 0) if (writeTimeout != 0)
{ {
networkStream.WriteTimeout = writeTimeout; networkStream.WriteTimeout = writeTimeout;
Expand Down
33 changes: 14 additions & 19 deletions MongoDB.Driver/Communication/MongoConnectionPool.cs
Expand Up @@ -29,7 +29,7 @@ public class MongoConnectionPool
{ {
// private fields // private fields
private object _connectionPoolLock = new object(); private object _connectionPoolLock = new object();
private MongoServer _server; private MongoServerSettings _settings;
private MongoServerInstance _serverInstance; private MongoServerInstance _serverInstance;
private int _poolSize; private int _poolSize;
private List<MongoConnection> _availableConnections = new List<MongoConnection>(); private List<MongoConnection> _availableConnections = new List<MongoConnection>();
Expand All @@ -42,7 +42,7 @@ public class MongoConnectionPool
// constructors // constructors
internal MongoConnectionPool(MongoServerInstance serverInstance) internal MongoConnectionPool(MongoServerInstance serverInstance)
{ {
_server = serverInstance.Server; _settings = serverInstance.Settings;
_serverInstance = serverInstance; _serverInstance = serverInstance;
_poolSize = 0; _poolSize = 0;
} }
Expand Down Expand Up @@ -81,32 +81,27 @@ public MongoServerInstance ServerInstance
} }


// internal methods // internal methods
internal MongoConnection AcquireConnection(MongoDatabase database) internal MongoConnection AcquireConnection(string databaseName, MongoCredentials credentials)
{ {
if (database != null && database.Server != _server)
{
throw new ArgumentException("This connection pool is for a different server.", "database");
}

lock (_connectionPoolLock) lock (_connectionPoolLock)
{ {
if (_waitQueueSize >= _server.Settings.WaitQueueSize) if (_waitQueueSize >= _settings.WaitQueueSize)
{ {
throw new MongoConnectionException("Too many threads are already waiting for a connection."); throw new MongoConnectionException("Too many threads are already waiting for a connection.");
} }


_waitQueueSize += 1; _waitQueueSize += 1;
try try
{ {
DateTime timeoutAt = DateTime.UtcNow + _server.Settings.WaitQueueTimeout; DateTime timeoutAt = DateTime.UtcNow + _settings.WaitQueueTimeout;
while (true) while (true)
{ {
if (_availableConnections.Count > 0) if (_availableConnections.Count > 0)
{ {
// first try to find the most recently used connection that is already authenticated for this database // first try to find the most recently used connection that is already authenticated for this database
for (int i = _availableConnections.Count - 1; i >= 0; i--) for (int i = _availableConnections.Count - 1; i >= 0; i--)
{ {
if (_availableConnections[i].IsAuthenticated(database)) if (_availableConnections[i].IsAuthenticated(databaseName, credentials))
{ {
var connection = _availableConnections[i]; var connection = _availableConnections[i];
_availableConnections.RemoveAt(i); _availableConnections.RemoveAt(i);
Expand All @@ -117,7 +112,7 @@ internal MongoConnection AcquireConnection(MongoDatabase database)
// otherwise find the most recently used connection that can be authenticated for this database // otherwise find the most recently used connection that can be authenticated for this database
for (int i = _availableConnections.Count - 1; i >= 0; i--) for (int i = _availableConnections.Count - 1; i >= 0; i--)
{ {
if (_availableConnections[i].CanAuthenticate(database)) if (_availableConnections[i].CanAuthenticate(databaseName, credentials))
{ {
var connection = _availableConnections[i]; var connection = _availableConnections[i];
_availableConnections.RemoveAt(i); _availableConnections.RemoveAt(i);
Expand All @@ -133,7 +128,7 @@ internal MongoConnection AcquireConnection(MongoDatabase database)
} }


// create a new connection if maximum pool size has not been reached // create a new connection if maximum pool size has not been reached
if (_poolSize < _server.Settings.MaxConnectionPoolSize) if (_poolSize < _settings.MaxConnectionPoolSize)
{ {
// make sure connection is created successfully before incrementing poolSize // make sure connection is created successfully before incrementing poolSize
// connection will be opened later outside of the lock // connection will be opened later outside of the lock
Expand Down Expand Up @@ -208,11 +203,11 @@ internal void MaintainPoolSize()


// remove old connections before idle connections // remove old connections before idle connections
var now = DateTime.UtcNow; var now = DateTime.UtcNow;
if (oldestConnection != null && now > oldestConnection.CreatedAt + _server.Settings.MaxConnectionLifeTime) if (oldestConnection != null && now > oldestConnection.CreatedAt + _settings.MaxConnectionLifeTime)
{ {
connectionToRemove = oldestConnection; connectionToRemove = oldestConnection;
} }
else if (_poolSize > _server.Settings.MinConnectionPoolSize && lruConnection != null && now > lruConnection.LastUsedAt + _server.Settings.MaxConnectionIdleTime) else if (_poolSize > _settings.MinConnectionPoolSize && lruConnection != null && now > lruConnection.LastUsedAt + _settings.MaxConnectionIdleTime)
{ {
connectionToRemove = lruConnection; connectionToRemove = lruConnection;
} }
Expand All @@ -226,7 +221,7 @@ internal void MaintainPoolSize()
RemoveConnection(connectionToRemove); RemoveConnection(connectionToRemove);
} }


if (_poolSize < _server.Settings.MinConnectionPoolSize) if (_poolSize < _settings.MinConnectionPoolSize)
{ {
ThreadPool.QueueUserWorkItem(EnsureMinConnectionPoolSizeWorkItem, _generationId); ThreadPool.QueueUserWorkItem(EnsureMinConnectionPoolSizeWorkItem, _generationId);
} }
Expand Down Expand Up @@ -255,7 +250,7 @@ internal void ReleaseConnection(MongoConnection connection)
// but only remove one connection at most per timer tick to avoid connection storms // but only remove one connection at most per timer tick to avoid connection storms
if (_connectionsRemovedSinceLastTimerTick == 0) if (_connectionsRemovedSinceLastTimerTick == 0)
{ {
if (DateTime.UtcNow - connection.CreatedAt > _server.Settings.MaxConnectionLifeTime) if (DateTime.UtcNow - connection.CreatedAt > _settings.MaxConnectionLifeTime)
{ {
RemoveConnection(connection); RemoveConnection(connection);
return; return;
Expand Down Expand Up @@ -303,7 +298,7 @@ private void EnsureMinConnectionPoolSizeWorkItem(object state)
lock (_connectionPoolLock) lock (_connectionPoolLock)
{ {
// stop if the connection pool generationId has changed or we have already reached MinConnectionPoolSize // stop if the connection pool generationId has changed or we have already reached MinConnectionPoolSize
if (_generationId != forGenerationId || _poolSize >= _server.Settings.MinConnectionPoolSize) if (_generationId != forGenerationId || _poolSize >= _settings.MinConnectionPoolSize)
{ {
return; return;
} }
Expand All @@ -320,7 +315,7 @@ private void EnsureMinConnectionPoolSizeWorkItem(object state)
var added = false; var added = false;
lock (_connectionPoolLock) lock (_connectionPoolLock)
{ {
if (_generationId == forGenerationId && _poolSize < _server.Settings.MaxConnectionPoolSize) if (_generationId == forGenerationId && _poolSize < _settings.MaxConnectionPoolSize)
{ {
_availableConnections.Add(connection); _availableConnections.Add(connection);
_poolSize++; _poolSize++;
Expand Down
26 changes: 14 additions & 12 deletions MongoDB.Driver/Communication/MongoServerInstance.cs
Expand Up @@ -43,7 +43,7 @@ public sealed class MongoServerInstance


// private fields // private fields
private readonly object _serverInstanceLock = new object(); private readonly object _serverInstanceLock = new object();
private readonly MongoServer _server; private readonly MongoServerSettings _settings;
private readonly MongoConnectionPool _connectionPool; private readonly MongoConnectionPool _connectionPool;
private readonly PingTimeAggregator _pingTimeAggregator; private readonly PingTimeAggregator _pingTimeAggregator;
private MongoServerAddress _address; private MongoServerAddress _address;
Expand All @@ -60,11 +60,11 @@ public sealed class MongoServerInstance
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="MongoServerInstance"/> class. /// Initializes a new instance of the <see cref="MongoServerInstance"/> class.
/// </summary> /// </summary>
/// <param name="server">The server.</param> /// <param name="settings">The settings.</param>
/// <param name="address">The address.</param> /// <param name="address">The address.</param>
internal MongoServerInstance(MongoServer server, MongoServerAddress address) internal MongoServerInstance(MongoServerSettings settings, MongoServerAddress address)
{ {
_server = server; _settings = settings;
_address = address; _address = address;
_sequentialId = Interlocked.Increment(ref __nextSequentialId); _sequentialId = Interlocked.Increment(ref __nextSequentialId);
_state = MongoServerState.Disconnected; _state = MongoServerState.Disconnected;
Expand Down Expand Up @@ -284,9 +284,9 @@ public int SequentialId
/// <summary> /// <summary>
/// Gets the server for this server instance. /// Gets the server for this server instance.
/// </summary> /// </summary>
public MongoServer Server public MongoServerSettings Settings
{ {
get { return _server; } get { return _settings; }
} }


/// <summary> /// <summary>
Expand Down Expand Up @@ -315,7 +315,7 @@ public IPEndPoint GetIPEndPoint()
var ipEndPoint = Interlocked.CompareExchange(ref _ipEndPoint, null, null); var ipEndPoint = Interlocked.CompareExchange(ref _ipEndPoint, null, null);
if (ipEndPoint == null) if (ipEndPoint == null)
{ {
var addressFamily = _server.Settings.IPv6 ? AddressFamily.InterNetworkV6 : AddressFamily.InterNetwork; var addressFamily = _settings.IPv6 ? AddressFamily.InterNetworkV6 : AddressFamily.InterNetwork;
ipEndPoint = _address.ToIPEndPoint(addressFamily); ipEndPoint = _address.ToIPEndPoint(addressFamily);
Interlocked.CompareExchange(ref _ipEndPoint, _ipEndPoint, null); Interlocked.CompareExchange(ref _ipEndPoint, _ipEndPoint, null);
} }
Expand Down Expand Up @@ -369,9 +369,11 @@ public void VerifyState()
/// <summary> /// <summary>
/// Acquires the connection. /// Acquires the connection.
/// </summary> /// </summary>
/// <param name="database">The database.</param> /// <param name="databaseName">Name of the database.</param>
/// <param name="credentials">The credentials.</param>
/// <returns>A MongoConnection.</returns> /// <returns>A MongoConnection.</returns>
internal MongoConnection AcquireConnection(MongoDatabase database) /// <exception cref="System.InvalidOperationException"></exception>
internal MongoConnection AcquireConnection(string databaseName, MongoCredentials credentials)
{ {
MongoConnection connection; MongoConnection connection;
lock (_serverInstanceLock) lock (_serverInstanceLock)
Expand All @@ -383,11 +385,11 @@ internal MongoConnection AcquireConnection(MongoDatabase database)
} }
} }


connection = _connectionPool.AcquireConnection(database); connection = _connectionPool.AcquireConnection(databaseName, credentials);


try try
{ {
connection.CheckAuthentication(database); // will authenticate if necessary connection.CheckAuthentication(databaseName, credentials); // will authenticate if necessary
} }
catch (MongoAuthenticationException) catch (MongoAuthenticationException)
{ {
Expand Down Expand Up @@ -424,7 +426,7 @@ internal void Connect()


try try
{ {
var connection = _connectionPool.AcquireConnection(null); var connection = _connectionPool.AcquireConnection(null, null);
try try
{ {
Ping(connection); Ping(connection);
Expand Down

0 comments on commit f7bdc76

Please sign in to comment.