public static ShardMapManager CreateSqlShardMapManager( SqlConnectionInfo connectionInfo, ShardMapManagerCreateMode createMode, RetryBehavior retryBehavior) { return(CreateSqlShardMapManagerImpl( connectionInfo, createMode, retryBehavior, null, GlobalConstants.GsmVersionClient)); }
/// <summary> /// Given a key value, obtains a SqlConnection to the shard in the mapping /// that contains the key value. /// </summary> /// <param name="key">Input key value.</param> /// <param name="connectionInfo"> /// Connection string with credential information, the DataSource and Database are /// obtained from the results of the lookup operation for key. /// </param> /// <param name="options">Options for validation operations to perform on opened connection.</param> /// <returns>An opened SqlConnection.</returns> public SqlConnection OpenConnectionForKey( TKey key, SqlConnectionInfo connectionInfo, ConnectionOptions options = ConnectionOptions.Validate) { return(this.OpenConnectionForKey <PointMapping <TKey>, TKey>( key, (smm, sm, ssm) => new PointMapping <TKey>(smm, sm, ssm), ShardManagementErrorCategory.ListShardMap, connectionInfo, options)); }
/// <summary> /// Given a key value, asynchronously obtains a SqlConnection to the shard in the mapping /// that contains the key value. /// </summary> /// <param name="key">Input key value.</param> /// <param name="connectionString"> /// Connection string with credential information, the DataSource and Database are /// obtained from the results of the lookup operation for key. /// </param> /// <param name="secureCredential">Secure SQL Credential.</param> /// <param name="options">Options for validation operations to perform on opened connection.</param> /// <returns>A Task encapsulating an opened SqlConnection.</returns> public async Task <SqlConnection> OpenConnectionForKeyAsync( TKey key, SqlConnectionInfo connectionInfo, ConnectionOptions options = ConnectionOptions.Validate) { return(await this.OpenConnectionForKeyAsync <RangeMapping <TKey>, TKey>( key, (smm, sm, ssm) => new RangeMapping <TKey>(smm, sm, ssm), ShardManagementErrorCategory.RangeShardMap, connectionInfo, options).ConfigureAwait(false)); }
/// <summary> /// Given a shard, asynchronously obtains a SqlConnection to the shard. The shard must exist in the mapper. /// </summary> /// <param name="key">Input shard.</param> /// <param name="connectionInfo"> /// Connection string with credential information, the DataSource and Database are /// obtained from the results of the lookup operation. /// </param> /// <param name="options">Options for validation operations to perform on opened connection.</param> /// <returns>An opened SqlConnection.</returns> public async Task <SqlConnection> OpenConnectionForKeyAsync( Shard key, SqlConnectionInfo connectionInfo, ConnectionOptions options = ConnectionOptions.Validate) { Debug.Assert(key != null); Debug.Assert(connectionInfo != null); return(await this.ShardMap.OpenConnectionAsync( this.Lookup(key, LookupOptions.LookupInCache | LookupOptions.LookupInStore), connectionInfo, options).ConfigureAwait(false)); }
/// <summary> /// Given a shard, obtains a SqlConnection to the shard. The shard must exist in the mapper. /// </summary> /// <param name="key">Input shard.</param> /// <param name="connectionInfo"> /// Connection info with credential information, the DataSource and Database are /// obtained from the results of the lookup operation. /// </param> /// <param name="options">Options for validation operations to perform on opened connection.</param> /// <returns>An opened SqlConnection.</returns> public SqlConnection OpenConnectionForKey( Shard key, SqlConnectionInfo connectionInfo, ConnectionOptions options = ConnectionOptions.Validate) { Debug.Assert(key != null); Debug.Assert(connectionInfo != null); return(this.ShardMap.OpenConnection( this.Lookup(key, LookupOptions.LookupInCache | LookupOptions.LookupInStore), connectionInfo, options)); }
public Task <SqlConnection> OpenConnectionForKeyAsync( TKey key, SqlConnectionInfo connectionInfo, ConnectionOptions options) { ExceptionUtils.DisallowNullArgument(connectionInfo, "connectionInfo"); using (ActivityIdScope activityIdScope = new ActivityIdScope(Guid.NewGuid())) { return(_lsm.OpenConnectionForKeyAsync( key, connectionInfo, options)); } }
/// <summary> /// Establishes connection to the target shard. /// </summary> private void EstablishConnnection() { // Open connection. SqlConnectionStringBuilder localConnectionString = new SqlConnectionStringBuilder(_credentials.ConnectionInfoShard.ConnectionString) { DataSource = this.Location.DataSource, InitialCatalog = this.Location.Database }; SqlConnectionInfo localConnectionInfo = _credentials.ConnectionInfoShard.CloneWithUpdatedConnectionString( localConnectionString.ConnectionString); _localConnection = new SqlStoreConnection( StoreConnectionKind.LocalSource, localConnectionInfo); _localConnection.Open(); }
private static ShardMapManager GetSqlShardMapManager( SqlConnectionInfo connectionInfo, ShardMapManagerLoadPolicy loadPolicy, RetryBehavior retryBehavior, EventHandler <RetryingEventArgs> retryEventHandler) { ExceptionUtils.DisallowNullArgument(connectionInfo, "connectionInfo"); ExceptionUtils.DisallowNullArgument(retryBehavior, "retryBehavior"); using (ActivityIdScope activityIdScope = new ActivityIdScope(Guid.NewGuid())) { Tracer.TraceInfo( TraceSourceConstants.ComponentNames.ShardMapManagerFactory, "GetSqlShardMapManager", "Start; "); Stopwatch stopwatch = Stopwatch.StartNew(); ShardMapManager shardMapManager = ShardMapManagerFactory.GetSqlShardMapManager( connectionInfo, loadPolicy, retryBehavior, retryEventHandler, true); stopwatch.Stop(); Debug.Assert(shardMapManager != null); Tracer.TraceInfo( TraceSourceConstants.ComponentNames.ShardMapManagerFactory, "GetSqlShardMapManager", "Complete; Duration: {0}", stopwatch.Elapsed); return(shardMapManager); } }
public static bool TryGetSqlShardMapManager( SqlConnectionInfo connectionInfo, ShardMapManagerLoadPolicy loadPolicy, RetryBehavior retryBehavior, out ShardMapManager shardMapManager) { ExceptionUtils.DisallowNullArgument(connectionInfo, "connectionInfo"); ExceptionUtils.DisallowNullArgument(retryBehavior, "retryBehavior"); using (ActivityIdScope activityIdScope = new ActivityIdScope(Guid.NewGuid())) { Tracer.TraceInfo( TraceSourceConstants.ComponentNames.ShardMapManagerFactory, "TryGetSqlShardMapManager", "Start; "); Stopwatch stopwatch = Stopwatch.StartNew(); shardMapManager = ShardMapManagerFactory.GetSqlShardMapManager( connectionInfo, loadPolicy, retryBehavior, null, false); stopwatch.Stop(); Tracer.TraceInfo( TraceSourceConstants.ComponentNames.ShardMapManagerFactory, "TryGetSqlShardMapManager", "Complete; Duration: {0}", stopwatch.Elapsed); return(shardMapManager != null); } }
/// <summary> /// Constructs a new instance of user connection. /// </summary> /// <param name="connectionInfo">Connection info.</param> /// <returns>An unopened instance of the user connection.</returns> public virtual IUserStoreConnection GetUserConnection(SqlConnectionInfo connectionInfo) { return(new SqlUserStoreConnection(connectionInfo)); }
/// <summary> /// Constructs a new instance of store connection. /// </summary> /// <param name="kind">Type of store connection.</param> /// <param name="connectionInfo">Connection info.</param> /// <returns>An unopened instance of the store connection.</returns> public virtual IStoreConnection GetConnection( StoreConnectionKind kind, SqlConnectionInfo connectionInfo) { return(new SqlStoreConnection(kind, connectionInfo)); }
private static ShardMapManager CreateSqlShardMapManagerImpl( SqlConnectionInfo connectionInfo, ShardMapManagerCreateMode createMode, RetryBehavior retryBehavior, EventHandler <RetryingEventArgs> retryEventHandler, Version targetVersion) { ExceptionUtils.DisallowNullArgument(connectionInfo, "connectionInfo"); ExceptionUtils.DisallowNullArgument(retryBehavior, "retryBehavior"); if (createMode != ShardMapManagerCreateMode.KeepExisting && createMode != ShardMapManagerCreateMode.ReplaceExisting) { throw new ArgumentException( StringUtils.FormatInvariant( Errors._General_InvalidArgumentValue, createMode, "createMode"), "createMode"); } using (ActivityIdScope activityIdScope = new ActivityIdScope(Guid.NewGuid())) { Tracer.TraceInfo( TraceSourceConstants.ComponentNames.ShardMapManagerFactory, "CreateSqlShardMapManager", "Start; "); Stopwatch stopwatch = Stopwatch.StartNew(); SqlShardMapManagerCredentials credentials = new SqlShardMapManagerCredentials(connectionInfo); TransientFaultHandling.RetryPolicy retryPolicy = new TransientFaultHandling.RetryPolicy( new ShardManagementTransientErrorDetectionStrategy(retryBehavior), RetryPolicy.DefaultRetryPolicy.GetRetryStrategy()); EventHandler <TransientFaultHandling.RetryingEventArgs> handler = (sender, args) => { if (retryEventHandler != null) { retryEventHandler(sender, new RetryingEventArgs(args)); } }; try { retryPolicy.Retrying += handler; // specifying targetVersion as GlobalConstants.GsmVersionClient to deploy latest store by default. using (IStoreOperationGlobal op = new StoreOperationFactory().CreateCreateShardMapManagerGlobalOperation( credentials, retryPolicy, "CreateSqlShardMapManager", createMode, targetVersion)) { op.Do(); } stopwatch.Stop(); Tracer.TraceInfo( TraceSourceConstants.ComponentNames.ShardMapManagerFactory, "CreateSqlShardMapManager", "Complete; Duration: {0}", stopwatch.Elapsed); } finally { retryPolicy.Retrying -= handler; } return(new ShardMapManager( credentials, new SqlStoreConnectionFactory(), new StoreOperationFactory(), new CacheStore(), ShardMapManagerLoadPolicy.Lazy, RetryPolicy.DefaultRetryPolicy, retryBehavior, retryEventHandler)); } }
/// <summary> /// Given a key value, asynchronously obtains a SqlConnection to the shard in the mapping /// that contains the key value. /// </summary> /// <typeparam name="TMapping">Mapping type.</typeparam> /// <typeparam name="TKey">Key type.</typeparam> /// <param name="key">Input key value.</param> /// <param name="constructMapping">Delegate to construct a mapping object.</param> /// <param name="errorCategory">Error category.</param> /// <param name="connectionInfo"> /// Connection info with credential information, the DataSource and Database are /// obtained from the results of the lookup operation for key. /// </param> /// <param name="options">Options for validation operations to perform on opened connection.</param> /// <returns>A task encapsulating an opened SqlConnection as the result.</returns> protected async Task <SqlConnection> OpenConnectionForKeyAsync <TMapping, TKey>( TKey key, Func <ShardMapManager, ShardMap, IStoreMapping, TMapping> constructMapping, ShardManagementErrorCategory errorCategory, SqlConnectionInfo connectionInfo, ConnectionOptions options = ConnectionOptions.Validate) where TMapping : class, IShardProvider { ShardKey sk = new ShardKey(ShardKey.ShardKeyTypeFromType(typeof(TKey)), key); // Try to find the mapping within the cache. ICacheStoreMapping csm = this.Manager.Cache.LookupMappingByKey(this.ShardMap.StoreShardMap, sk); IStoreMapping sm; if (csm != null) { sm = csm.Mapping; } else { sm = await this.LookupMappingForOpenConnectionForKeyAsync( sk, CacheStoreMappingUpdatePolicy.OverwriteExisting, errorCategory).ConfigureAwait(false); } SqlConnection result; bool lookupMappingOnEx = false; CacheStoreMappingUpdatePolicy cacheUpdatePolicyOnEx = CacheStoreMappingUpdatePolicy.OverwriteExisting; try { // Initially attempt to connect based on lookup results from either cache or GSM. result = await this.ShardMap.OpenConnectionAsync( constructMapping(this.Manager, this.ShardMap, sm), connectionInfo, options).ConfigureAwait(false); csm.ResetTimeToLiveIfNecessary(); return(result); } catch (ShardManagementException smme) { // If we hit a validation failure due to stale version of mapping, we will perform one more attempt. if (((options & ConnectionOptions.Validate) == ConnectionOptions.Validate) && smme.ErrorCategory == ShardManagementErrorCategory.Validation && smme.ErrorCode == ShardManagementErrorCode.MappingDoesNotExist) { // Assumption here is that this time the attempt should succeed since the cache entry // has already been either evicted, or updated based on latest data from the server. lookupMappingOnEx = true; cacheUpdatePolicyOnEx = CacheStoreMappingUpdatePolicy.OverwriteExisting; } else { // The error was not due to validation but something else e.g. // 1) Shard map does not exist // 2) Mapping could not be found. throw; } } catch (SqlException) { // We failed to connect. If we were trying to connect from an entry in cache and mapping expired in cache. if (csm != null && csm.HasTimeToLiveExpired()) { using (IdLock _idLock = new IdLock(csm.Mapping.StoreShard.Id)) { // Similar to DCL pattern, we need to refresh the mapping again to see if we still need to go to the store // to lookup the mapping after acquiring the shard lock. It might be the case that a fresh version has already // been obtained by some other thread. csm = this.Manager.Cache.LookupMappingByKey(this.ShardMap.StoreShardMap, sk); // Only go to store if the mapping is stale even after refresh. if (csm == null || csm.HasTimeToLiveExpired()) { // Refresh the mapping in cache. And try to open the connection after refresh. lookupMappingOnEx = true; cacheUpdatePolicyOnEx = CacheStoreMappingUpdatePolicy.UpdateTimeToLive; } else { sm = csm.Mapping; } } } else { // Either: // 1) The mapping is still within the TTL. No refresh. // 2) Mapping was not in cache, we originally did a lookup for mapping in GSM and even then could not connect. throw; } } if (lookupMappingOnEx) { sm = await this.LookupMappingForOpenConnectionForKeyAsync( sk, cacheUpdatePolicyOnEx, errorCategory).ConfigureAwait(false); } // One last attempt to open the connection after a cache refresh result = await this.ShardMap.OpenConnectionAsync( constructMapping(this.Manager, this.ShardMap, sm), connectionInfo, options).ConfigureAwait(false); // Reset TTL on successful connection. csm.ResetTimeToLiveIfNecessary(); return(result); }
/// <summary> /// Ensures that the provided connection string is valid and builds the connection string /// to be used for DDR connection to the given shard provider. /// </summary> /// <param name="shardProvider">Shard provider containing shard to be connected to.</param> /// <param name="connectionInfo">Input connection info.</param> /// <returns>Connection string for DDR connection.</returns> private SqlConnectionInfo ValidateAndPrepareConnectionString( IShardProvider shardProvider, SqlConnectionInfo connectionInfo) { Debug.Assert(shardProvider != null); Debug.Assert(connectionInfo != null); Debug.Assert(connectionInfo.ConnectionString != null); // Devnote: If connection string specifies Active Directory authentication and runtime is not // .NET 4.6 or higher, then below call will throw. SqlConnectionStringBuilder connectionStringBuilder = new SqlConnectionStringBuilder(connectionInfo.ConnectionString); // DataSource must not be set. if (!string.IsNullOrEmpty(connectionStringBuilder.DataSource)) { throw new ArgumentException( StringUtils.FormatInvariant( Errors._ShardMap_OpenConnection_ConnectionStringPropertyDisallowed, "DataSource"), "connectionString"); } // InitialCatalog must not be set. if (!string.IsNullOrEmpty(connectionStringBuilder.InitialCatalog)) { throw new ArgumentException( StringUtils.FormatInvariant( Errors._ShardMap_OpenConnection_ConnectionStringPropertyDisallowed, "Initial Catalog"), "connectionString"); } // ConnectRetryCount must not be set (default value is 1) if (ShardMapUtils.IsConnectionResiliencySupported && (int)connectionStringBuilder[ShardMapUtils.ConnectRetryCount] > 1) { throw new ArgumentException( StringUtils.FormatInvariant( Errors._ShardMap_OpenConnection_ConnectionStringPropertyDisallowed, ShardMapUtils.ConnectRetryCount), "connectionString"); } // Verify that either UserID/Password or provided or integrated authentication is enabled. SqlShardMapManagerCredentials.EnsureCredentials( connectionStringBuilder, "connectionString", connectionInfo.Credential, connectionInfo.AccessTokenFactory); Shard s = shardProvider.ShardInfo; connectionStringBuilder.DataSource = s.Location.DataSource; connectionStringBuilder.InitialCatalog = s.Location.Database; // Append the proper post-fix for ApplicationName connectionStringBuilder.ApplicationName = ApplicationNameHelper.AddApplicationNameSuffix( connectionStringBuilder.ApplicationName, this.ApplicationNameSuffix); // Disable connection resiliency if necessary if (ShardMapUtils.IsConnectionResiliencySupported) { connectionStringBuilder[ShardMapUtils.ConnectRetryCount] = 0; } return(connectionInfo.CloneWithUpdatedConnectionString(connectionStringBuilder.ConnectionString)); }
/// <summary> /// Initializes a new instance of the <see cref="SqlStoreConnection"/> class. /// </summary> /// <param name="kind"> /// Type of store connection. /// </param> /// <param name="connectionInfo"> /// The connection info. /// </param> protected internal SqlStoreConnection(StoreConnectionKind kind, SqlConnectionInfo connectionInfo) { this.Kind = kind; this._conn = connectionInfo.CreateConnection(); }
/// <summary> /// Creates a new instance of user store connection. /// </summary> /// <param name="connectionInfo">Connection info.</param> internal SqlUserStoreConnection(SqlConnectionInfo connectionInfo) { _conn = connectionInfo.CreateConnection(); }
/// <summary> /// Instantiates the object that holds the credentials for accessing SQL Servers /// containing the shard map manager data. /// </summary> /// <param name="connectionInfo"> /// Connection info for shard map manager data source. /// </param> public SqlShardMapManagerCredentials(SqlConnectionInfo connectionInfo) { ExceptionUtils.DisallowNullArgument(connectionInfo, "connectionInfo"); // Devnote: If connection string specifies Active Directory authentication and runtime is not // .NET 4.6 or higher, then below call will throw. SqlConnectionStringBuilder connectionStringBuilder = new SqlConnectionStringBuilder(connectionInfo.ConnectionString); #region GSM Validation // DataSource must be set. if (string.IsNullOrEmpty(connectionStringBuilder.DataSource)) { throw new ArgumentException( StringUtils.FormatInvariant( Errors._SqlShardMapManagerCredentials_ConnectionStringPropertyRequired, "DataSource"), "connectionString"); } // InitialCatalog must be set. if (string.IsNullOrEmpty(connectionStringBuilder.InitialCatalog)) { throw new ArgumentException( StringUtils.FormatInvariant( Errors._SqlShardMapManagerCredentials_ConnectionStringPropertyRequired, "Initial Catalog"), "connectionString"); } // Ensure credentials are specified for GSM connectivity. SqlShardMapManagerCredentials.EnsureCredentials( connectionStringBuilder, "connectionString", connectionInfo.Credential, connectionInfo.AccessTokenFactory); #endregion GSM Validation // Generate connectionInfoShardMapManager SqlConnectionStringBuilder connectionStringShardMapManager = new SqlConnectionStringBuilder(connectionStringBuilder.ConnectionString); connectionStringShardMapManager.ApplicationName = ApplicationNameHelper.AddApplicationNameSuffix( connectionStringShardMapManager.ApplicationName, GlobalConstants.ShardMapManagerInternalConnectionSuffixGlobal); _smmDataSource = connectionStringShardMapManager.DataSource; _smmInitialCatalog = connectionStringShardMapManager.InitialCatalog; this.ConnectionInfoShardMapManager = connectionInfo.CloneWithUpdatedConnectionString(connectionStringShardMapManager.ConnectionString); // Generate connectionInfoShard SqlConnectionStringBuilder connectionStringShard = new SqlConnectionStringBuilder(connectionStringBuilder.ConnectionString); connectionStringShard.Remove("Data Source"); connectionStringShard.Remove("Initial Catalog"); connectionStringShard.ApplicationName = ApplicationNameHelper.AddApplicationNameSuffix( connectionStringShard.ApplicationName, GlobalConstants.ShardMapManagerInternalConnectionSuffixLocal); this.ConnectionInfoShard = connectionInfo.CloneWithUpdatedConnectionString(connectionStringShard.ConnectionString); }