Summary

Class:CBAM.Abstractions.Implementation.ConnectionAcquireInfoImpl`3
Assembly:CBAM.Abstractions.Implementation
File(s):/repo-dir/contents/Source/Code/CBAM.Abstractions.Implementation/ConnectionPool.cs
Covered lines:7
Uncovered lines:1
Coverable lines:8
Total lines:273
Line coverage:87.5%
Branch coverage:83.3%

Coverage History

Metrics

MethodCyclomatic complexity NPath complexity Sequence coverage Branch coverage
.ctor(...)101%0%
Dispose(...)601%0.833%
PublicResourceCanBeReturnedToPool()100%0%

File(s)

/repo-dir/contents/Source/Code/CBAM.Abstractions.Implementation/ConnectionPool.cs

#LineLine coverage
 1/*
 2 * Copyright 2017 Stanislav Muhametsin. All rights Reserved.
 3 *
 4 * Licensed  under the  Apache License,  Version 2.0  (the "License");
 5 * you may not use  this file  except in  compliance with the License.
 6 * You may obtain a copy of the License at
 7 *
 8 *   http://www.apache.org/licenses/LICENSE-2.0
 9 *
 10 * Unless required by applicable law or agreed to in writing, software
 11 * distributed  under the  License is distributed on an "AS IS" BASIS,
 12 * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
 13 * implied.
 14 *
 15 * See the License for the specific language governing permissions and
 16 * limitations under the License.
 17 */
 18using CBAM.Abstractions;
 19using CBAM.Abstractions.Implementation;
 20using ResourcePooling.Async.Abstractions;
 21using System;
 22using System.Collections.Generic;
 23using System.Text;
 24using System.Threading;
 25using System.Threading.Tasks;
 26using UtilPack;
 27
 28namespace CBAM.Abstractions.Implementation
 29{
 30   /// <summary>
 31   /// This class implements <see cref="AsyncResourceFactory{TResource, TParams}"/> in order to create instances of <see
 32   /// </summary>
 33   /// <typeparam name="TConnection">The public type of <see cref="Connection{TStatement, TStatementInformation, TStatem
 34   /// <typeparam name="TPrivateConnection">The actual type of <see cref="Connection{TStatement, TStatementInformation, 
 35   /// <typeparam name="TConnectionFunctionality">The actual type of <see cref="PooledConnectionFunctionality"/>.</typep
 36   /// <typeparam name="TConnectionCreationParameters">The type of parameter containing enough information to create an 
 37   public abstract class DefaultConnectionFactory<TConnection, TPrivateConnection, TConnectionFunctionality, TConnection
 38      where TConnection : class
 39      where TPrivateConnection : class, TConnection
 40      where TConnectionFunctionality : class, PooledConnectionFunctionality
 41   {
 42      /// <summary>
 43      /// Initializes a new instance of <see cref="PooledConnectionFunctionality"/> with given connection creation param
 44      /// </summary>
 45      /// <param name="creationParameters">The connection creation parameters.</param>
 46      public DefaultConnectionFactory(
 47         TConnectionCreationParameters creationParameters
 48         ) : base( creationParameters )
 49      {
 50
 51      }
 52
 53
 54      /// <summary>
 55      /// This method implements <see cref="DefaultBoundAsyncResourceFactory{TConnection, TConnectionCreationParameters}
 56      /// </summary>
 57      /// <param name="token">The <see cref="CancellationToken"/> to use.</param>
 58      /// <returns>Potentially asynchronously returns <see cref="AsyncResourceAcquireInfo{TResource}"/> for given resour
 59      /// <remarks>
 60      /// The methods called are, in this order:
 61      /// <list type="number">
 62      /// <item><description>the <see cref="CreateConnectionFunctionality(CancellationToken)"/>,</description></item>
 63      /// <item><description>the <see cref="CreateConnection(TConnectionFunctionality)"/>, and</description></item>
 64      /// <item><description>the <see cref="CreateConnectionAcquireInfo(TConnectionFunctionality, TPrivateConnection)"/>
 65      /// </list>
 66      ///
 67      /// In case of an error, the <see cref="OnConnectionAcquirementError(TConnectionFunctionality, TPrivateConnection,
 68      /// </remarks>
 69      protected override async ValueTask<AsyncResourceAcquireInfo<TConnection>> AcquireResourceAsync( CancellationToken 
 70      {
 71         TConnectionFunctionality functionality = null;
 72         TPrivateConnection connection = null;
 73         try
 74         {
 75            functionality = await this.CreateConnectionFunctionality( token );
 76            functionality.CurrentCancellationToken = token;
 77            connection = await this.CreateConnection( functionality );
 78            return this.CreateConnectionAcquireInfo( functionality, connection );
 79         }
 80         catch ( Exception exc )
 81         {
 82            try
 83            {
 84               await this.OnConnectionAcquirementError( functionality, connection, token, exc );
 85            }
 86            catch
 87            {
 88               // Ignore this one
 89            }
 90            throw;
 91         }
 92         finally
 93         {
 94            functionality?.ResetCancellationToken();
 95         }
 96      }
 97
 98
 99      /// <summary>
 100      /// This method is called by <see cref="AcquireResourceAsync(CancellationToken)"/> initially, to create <see cref=
 101      /// </summary>
 102      /// <param name="token">The <see cref="CancellationToken"/> to use.</param>
 103      /// <returns>A task which will result in <see cref="PooledConnectionFunctionality"/> when completed.</returns>
 104      protected abstract ValueTask<TConnectionFunctionality> CreateConnectionFunctionality( CancellationToken token );
 105
 106      /// <summary>
 107      /// This method is called after <see cref="CreateConnectionFunctionality(CancellationToken)"/>, in order to create
 108      /// </summary>
 109      /// <param name="functionality">The <see cref="PooledConnectionFunctionality"/> created by <see cref="CreateConnec
 110      /// <returns>A task which will result in <see cref="ConnectionImpl{TStatement, TStatementInformation, TStatementCr
 111      protected abstract ValueTask<TPrivateConnection> CreateConnection( TConnectionFunctionality functionality );
 112
 113      /// <summary>
 114      /// This method is called after <see cref="CreateConnection(TConnectionFunctionality)"/> in order to create instan
 115      /// </summary>
 116      /// <param name="functionality">The <see cref="PooledConnectionFunctionality"/> created by <see cref="CreateConnec
 117      /// <param name="connection">The <see cref="ConnectionImpl{TStatement, TStatementInformation, TStatementCreationAr
 118      /// <returns>A new instance of <see cref="AsyncResourceAcquireInfo{TResource}"/>.</returns>
 119      protected abstract AsyncResourceAcquireInfo<TPrivateConnection> CreateConnectionAcquireInfo( TConnectionFunctional
 120
 121      /// <summary>
 122      /// This method is called whenever an error occurs within <see cref="AcquireResourceAsync(CancellationToken)"/> me
 123      /// </summary>
 124      /// <param name="functionality">The <see cref="PooledConnectionFunctionality"/> or <c>null</c> if error occurred d
 125      /// <param name="connection">The <see cref="ConnectionImpl{TStatement, TStatementInformation, TStatementCreationAr
 126      /// <param name="token">The <see cref="CancellationToken"/> passed to <see cref="AcquireResourceAsync(Cancellation
 127      /// <param name="error">The error which occurred.</param>
 128      /// <returns>A task which completes after error handling is done.</returns>
 129      protected abstract Task OnConnectionAcquirementError( TConnectionFunctionality functionality, TPrivateConnection c
 130   }
 131
 132   /// <summary>
 133   /// This class provides CBAM-related implementation for <see cref="AsyncResourceAcquireInfoImpl{TConnection, TChannel
 134   /// </summary>
 135   /// <typeparam name="TConnection">The actual type of <see cref="ConnectionImpl{TConnectionFunctionality}"/>.</typepar
 136   /// <typeparam name="TConnectionFunctionality">The actual type of <see cref="PooledConnectionFunctionality"/>.</typep
 137   /// <typeparam name="TStream">The actual type of underlying stream or other disposable resource.</typeparam>
 138   public abstract class ConnectionAcquireInfoImpl<TConnection, TConnectionFunctionality, TStream> : AsyncResourceAcquir
 139      where TConnection : class
 140      where TConnectionFunctionality : class, PooledConnectionFunctionality
 141      where TStream : IDisposable
 142   {
 143      /// <summary>
 144      /// Creates a new instance of <see cref="ConnectionAcquireInfoImpl{TConnection, TConnectionFunctionality, TStream}
 145      /// </summary>
 146      /// <param name="connection">The <typeparamref name="TConnection"/>.</param>
 147      /// <param name="functionality">The <typeparamref name="TConnectionFunctionality"/>.</param>
 148      /// <param name="associatedStream">The underlying stream or other disposable resource.</param>
 149      /// <exception cref="ArgumentNullException">If <paramref name="connection"/> is <c>null</c>.</exception>
 150      public ConnectionAcquireInfoImpl(
 151         TConnection connection,
 152         TConnectionFunctionality functionality,
 153         TStream associatedStream
 96154         ) : base( ArgumentValidator.ValidateNotNull( nameof( connection ), connection ), associatedStream, ( c, t ) => 
 155      {
 30156         this.Functionality = ArgumentValidator.ValidateNotNull( nameof( functionality ), functionality );
 30157      }
 158
 159      /// <summary>
 160      /// Gets the <typeparamref name="TConnectionFunctionality"/> of this <see cref="ConnectionAcquireInfoImpl{TConnect
 161      /// </summary>
 162      /// <value>The <typeparamref name="TConnectionFunctionality"/> of this <see cref="ConnectionAcquireInfoImpl{TConne
 24163      protected TConnectionFunctionality Functionality { get; }
 164
 165      /// <summary>
 166      /// This method overrides <see cref="AbstractDisposable.Dispose(Boolean)"/> and will dispose this <see cref="Async
 167      /// </summary>
 168      /// <param name="disposing">Whether this method is callsed from <see cref="IDisposable.Dispose"/> method.</param>
 169      protected override void Dispose( Boolean disposing )
 170      {
 30171         if ( disposing )
 172         {
 30173            this.Channel?.DisposeSafely();
 174         }
 30175      }
 176
 177      /// <summary>
 178      /// Overrides the abstract <see cref="AsyncResourceAcquireInfoImpl{TConnection, TStream}.PublicResourceCanBeReturn
 179      /// </summary>
 180      /// <returns>The value indicating whether this <see cref="ConnectionAcquireInfoImpl{TConnection, TConnectionFuncti
 181      protected override Boolean PublicResourceCanBeReturnedToPool()
 182      {
 0183         return this.Functionality.CanBeReturnedToPool;
 184      }
 185
 186   }
 187
 188   /// <summary>
 189   /// This class extends <see cref="ConnectionAcquireInfoImpl{TConnection, TConnectionFunctionality, TStream}"/> for si
 190   /// </summary>
 191   /// <typeparam name="TConnection">The actual type of <see cref="ConnectionImpl{TConnectionFunctionality}"/>.</typepar
 192   /// <typeparam name="TConnectionFunctionality">The actual type of <see cref="PooledConnectionFunctionality"/>.</typep
 193   /// <typeparam name="TStream">The actual type of underlying stream or other disposable resource.</typeparam>
 194   public sealed class StatelessConnectionAcquireInfo<TConnection, TConnectionFunctionality, TStream> : ConnectionAcquir
 195      where TConnection : class
 196      where TConnectionFunctionality : class, PooledConnectionFunctionality
 197      where TStream : IDisposable
 198   {
 199      /// <summary>
 200      /// Creates a new instance of <see cref="StatelessConnectionAcquireInfo{TConnection, TConnectionFunctionality, TSt
 201      /// </summary>
 202      /// <param name="connection">The <typeparamref name="TConnection"/>.</param>
 203      /// <param name="functionality">The <typeparamref name="TConnectionFunctionality"/>.</param>
 204      /// <param name="associatedStream">The underlying stream or other disposable resource.</param>
 205      /// <exception cref="ArgumentNullException">If <paramref name="connection"/> is <c>null</c>.</exception>
 206      public StatelessConnectionAcquireInfo(
 207         TConnection connection,
 208         TConnectionFunctionality functionality,
 209         TStream associatedStream
 210         ) : base( connection, functionality, associatedStream )
 211      {
 212      }
 213
 214      /// <summary>
 215      /// This method does nothing and returns completed task, since there should be nothing to do.
 216      /// </summary>
 217      /// <param name="token">The <see cref="CancellationToken"/> to use.</param>
 218      /// <returns>Always returns completed task.</returns>
 219      protected override Task DisposeBeforeClosingChannel( CancellationToken token )
 220      {
 221         return TaskUtils.CompletedTask;
 222      }
 223   }
 224
 225
 226   /// <summary>
 227   /// This class extends <see cref="DefaultConnectionFactory{TConnection, TPrivateConnection, TConnectionCreationParame
 228   /// </summary>
 229   /// <typeparam name="TConnection">The public type of <see cref="Connection{TStatement, TStatementInformation, TStatem
 230   /// <typeparam name="TPrivateConnection">The actual type of <see cref="Connection{TStatement, TStatementInformation, 
 231   /// <typeparam name="TConnectionFunctionality">The actual type of <see cref="PooledConnectionFunctionality{TStatement
 232   /// <typeparam name="TConnectionCreationParameters">The type of parameter containing enough information to create an 
 233   public abstract class ConnectionFactoryStream<TConnection, TPrivateConnection, TConnectionFunctionality, TConnectionC
 234      where TConnection : class
 235      where TPrivateConnection : class, TConnection
 236      where TConnectionFunctionality : class, PooledConnectionFunctionality
 237   {
 238      /// <summary>
 239      /// Initializes a new instance of <see cref="ConnectionFactoryStream{TConnection, TPrivateConnection, TConnectionC
 240      /// </summary>
 241      /// <param name="creationParameters">The connection creation parameters.</param>
 242      public ConnectionFactoryStream(
 243         TConnectionCreationParameters creationParameters
 244         ) : base( creationParameters )
 245      {
 246      }
 247
 248      /// <summary>
 249      /// This task overrides <see cref="DefaultConnectionFactory{TConnection, TPrivateConnection, TConnectionCreationPa
 250      /// </summary>
 251      /// <param name="functionality">The <see cref="PooledConnectionFunctionality{TStatement, TStatementInformation, TS
 252      /// <param name="connection">The <see cref="ConnectionImpl{TStatement, TStatementInformation, TStatementCreationAr
 253      /// <param name="token">The <see cref="CancellationToken"/> passed to <see cref="DefaultConnectionFactory{TConnect
 254      /// <param name="error">The error which occurred.</param>
 255      /// <returns>A completed task.</returns>
 256      protected override Task OnConnectionAcquirementError( TConnectionFunctionality functionality, TPrivateConnection c
 257      {
 258         this.ExtractStreamOnConnectionAcquirementError( functionality, connection, token, error ).DisposeSafely();
 259         return TaskUtils.CompletedTask;
 260      }
 261
 262      /// <summary>
 263      /// This method should be implemented by derived class in order to extract underlying stream or other <see cref="I
 264      /// </summary>
 265      /// <param name="functionality">The <see cref="PooledConnectionFunctionality{TStatement, TStatementInformation, TS
 266      /// <param name="connection">The <see cref="ConnectionImpl{TStatement, TStatementInformation, TStatementCreationAr
 267      /// <param name="token">The <see cref="CancellationToken"/> passed to <see cref="DefaultConnectionFactory{TConnect
 268      /// <param name="error">The error which occurred.</param>
 269      /// <returns>The underlying stream or other <see cref="IDisposable"/> object.</returns>
 270      protected abstract IDisposable ExtractStreamOnConnectionAcquirementError( TConnectionFunctionality functionality, 
 271   }
 272
 273}