DbConnectionPoolAuthenticationContext.cs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. //------------------------------------------------------------------------------
  2. // <copyright file="DbConnectionPoolAuthenticationContext.cs" company="Microsoft">
  3. // Copyright (c) Microsoft Corporation. All rights reserved.
  4. // </copyright>
  5. // <owner current="true" primary="true">harsudan</owner>
  6. // <owner current="true" primary="false">yuronhe</owner>
  7. //------------------------------------------------------------------------------
  8. using System;
  9. using System.Diagnostics;
  10. using System.Runtime.ConstrainedExecution;
  11. using System.Threading;
  12. namespace System.Data.ProviderBase
  13. {
  14. /// <summary>
  15. /// Represents the context of an authentication attempt when using the new active directory based authentication mechanisms.
  16. /// All data members, except_isUpdateInProgressCounter, should be immutable.
  17. /// </summary>
  18. sealed internal class DbConnectionPoolAuthenticationContext
  19. {
  20. /// <summary>
  21. /// The value expected in _isUpdateInProgress if a thread has taken a lock on this context,
  22. /// to perform the update on the context.
  23. /// </summary>
  24. private const int STATUS_LOCKED = 1;
  25. /// <summary>
  26. /// The value expected in _isUpdateInProgress if no thread has taken a lock on this context.
  27. /// </summary>
  28. private const int STATUS_UNLOCKED = 0;
  29. /// <summary>
  30. /// Access Token, which is obtained from Active Directory Authentication Library for SQL Server, and needs to be sent to SQL Server
  31. /// as part of TDS Token type Federated Authentication Token.
  32. /// </summary>
  33. private readonly byte[] _accessToken;
  34. /// <summary>
  35. /// Expiration time of the above access token.
  36. /// </summary>
  37. private readonly DateTime _expirationTime;
  38. /// <summary>
  39. /// A member which is used to achieve a lock to control refresh attempt on this context.
  40. /// </summary>
  41. private int _isUpdateInProgress;
  42. /// <summary>
  43. /// Constructor.
  44. /// </summary>
  45. /// <param name="accessToken">Access Token that will be used to connect to SQL Server. Carries identity information about a user.</param>
  46. /// <param name="expirationTime">The expiration time in UTC for the above accessToken.</param>
  47. internal DbConnectionPoolAuthenticationContext(byte[] accessToken, DateTime expirationTime) {
  48. Debug.Assert(accessToken != null && accessToken.Length > 0);
  49. Debug.Assert(expirationTime > DateTime.MinValue && expirationTime < DateTime.MaxValue);
  50. _accessToken = accessToken;
  51. _expirationTime = expirationTime;
  52. _isUpdateInProgress = STATUS_UNLOCKED;
  53. }
  54. /// <summary>
  55. /// Static Method.
  56. /// Given two contexts, choose one to update in the cache. Chooses based on expiration time.
  57. /// </summary>
  58. /// <param name="context1">Context1</param>
  59. /// <param name="context2">Context2</param>
  60. internal static DbConnectionPoolAuthenticationContext ChooseAuthenticationContextToUpdate(DbConnectionPoolAuthenticationContext context1, DbConnectionPoolAuthenticationContext context2) {
  61. Debug.Assert(context1 != null, "context1 should not be null.");
  62. Debug.Assert(context2 != null, "context2 should not be null.");
  63. return context1.ExpirationTime > context2.ExpirationTime ? context1 : context2;
  64. }
  65. internal byte[] AccessToken {
  66. get {
  67. return _accessToken;
  68. }
  69. }
  70. internal DateTime ExpirationTime {
  71. get {
  72. return _expirationTime;
  73. }
  74. }
  75. /// <summary>
  76. /// Try locking the variable _isUpdateInProgressCounter and return if this thread got the lock to update.
  77. /// Whichever thread got the chance to update this variable to 1 wins the lock.
  78. /// </summary>
  79. internal bool LockToUpdate() {
  80. int oldValue = Interlocked.CompareExchange(ref _isUpdateInProgress, STATUS_LOCKED, STATUS_UNLOCKED);
  81. return (oldValue == STATUS_UNLOCKED);
  82. }
  83. /// <summary>
  84. /// Release the lock which was obtained through LockToUpdate.
  85. /// </summary>
  86. [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
  87. internal void ReleaseLockToUpdate() {
  88. int oldValue = Interlocked.CompareExchange(ref _isUpdateInProgress, STATUS_UNLOCKED, STATUS_LOCKED);
  89. Debug.Assert(oldValue == STATUS_LOCKED);
  90. }
  91. }
  92. }