internal async Task <SqlConnection> OpenConnectionAsync( IShardProvider shardProvider, string connectionString, SqlCredential secureCredential, ConnectionOptions options = ConnectionOptions.Validate) { Debug.Assert(shardProvider != null, "Expecting IShardProvider."); ExceptionUtils.DisallowNullArgument(connectionString, "connectionString"); string connectionStringFinal = this.ValidateAndPrepareConnectionString( shardProvider, connectionString, secureCredential); ExceptionUtils.EnsureShardBelongsToShardMap( this.Manager, this, shardProvider.ShardInfo, "OpenConnectionAsync", "Shard"); IUserStoreConnection conn = this.Manager.StoreConnectionFactory.GetUserConnection(connectionStringFinal, secureCredential); Tracer.TraceInfo( TraceSourceConstants.ComponentNames.ShardMap, "OpenConnectionAsync", "Start; Shard: {0}; Options: {1}; ConnectionString: {2}", shardProvider.ShardInfo.Location, options, connectionStringFinal); using (ConditionalDisposable <IUserStoreConnection> cd = new ConditionalDisposable <IUserStoreConnection>(conn)) { Stopwatch stopwatch = Stopwatch.StartNew(); await conn.OpenAsync().ConfigureAwait(false); stopwatch.Stop(); // If validation is requested. if ((options & ConnectionOptions.Validate) == ConnectionOptions.Validate) { await shardProvider.ValidateAsync(this.StoreShardMap, conn.Connection).ConfigureAwait(false); } cd.DoNotDispose = true; Tracer.TraceInfo( TraceSourceConstants.ComponentNames.ShardMap, "OpenConnectionAsync", "Complete; Shard: {0}; Options: {1}; Open Duration: {2}", shardProvider.ShardInfo.Location, options, stopwatch.Elapsed); } return(conn.Connection); }
/// <summary> /// Gets all the mappings that exist within given range. /// </summary> /// <param name="range">Optional range value, if null, we cover everything.</param> /// <param name="shard">Optional shard parameter, if null, we cover all shards.</param> /// <param name="constructMapping">Delegate to construct a mapping object.</param> /// <param name="errorCategory">Category under which errors will be posted.</param> /// <param name="mappingType">Name of mapping type.</param> /// <returns>Read-only collection of mappings that overlap with given range.</returns> protected IReadOnlyList <TMapping> GetMappingsForRange <TMapping, TKey>( Range <TKey> range, Shard shard, Func <ShardMapManager, ShardMap, IStoreMapping, TMapping> constructMapping, ShardManagementErrorCategory errorCategory, string mappingType) where TMapping : class { ShardRange sr = null; if (shard != null) { ExceptionUtils.EnsureShardBelongsToShardMap( this.Manager, this.ShardMap, shard, "GetMappings", mappingType); } if (range != null) { sr = new ShardRange( new ShardKey(ShardKey.ShardKeyTypeFromType(typeof(TKey)), range.Low), new ShardKey(ShardKey.ShardKeyTypeFromType(typeof(TKey)), range.HighIsMax ? null : (object)range.High)); } IStoreResults result; using (IStoreOperationGlobal op = this.Manager.StoreOperationFactory.CreateGetMappingsByRangeGlobalOperation( this.Manager, "GetMappingsForRange", this.ShardMap.StoreShardMap, shard != null ? shard.StoreShard : null, sr, errorCategory, true, // Always cache. false)) { result = op.Do(); } return(result.StoreMappings .Select(sm => constructMapping(this.Manager, this.ShardMap, sm)) .ToList() .AsReadOnly()); }
/// <summary> /// Adds a mapping to shard map. /// </summary> /// <typeparam name="TMapping">Mapping type.</typeparam> /// <param name="mapping">Mapping being added.</param> /// <param name="constructMapping">Delegate to construct a mapping object.</param> /// <returns>The added mapping object.</returns> protected TMapping Add <TMapping>( TMapping mapping, Func <ShardMapManager, ShardMap, IStoreMapping, TMapping> constructMapping) where TMapping : class, IShardProvider, IMappingInfoProvider { ExceptionUtils.EnsureShardBelongsToShardMap( this.Manager, this.ShardMap, mapping.ShardInfo, "CreateMapping", mapping.Kind == MappingKind.PointMapping ? "PointMapping" : "RangeMapping"); this.EnsureMappingBelongsToShardMap(mapping, "Add", "mapping"); TMapping newMapping = constructMapping( this.Manager, this.ShardMap, new DefaultStoreMapping( mapping.StoreMapping.Id, mapping.StoreMapping.ShardMapId, new DefaultStoreShard( mapping.ShardInfo.StoreShard.Id, Guid.NewGuid(), mapping.ShardInfo.StoreShard.ShardMapId, mapping.ShardInfo.StoreShard.Location, mapping.ShardInfo.StoreShard.Status), mapping.StoreMapping.MinValue, mapping.StoreMapping.MaxValue, mapping.StoreMapping.Status, mapping.StoreMapping.LockOwnerId)); using (IStoreOperation op = this.Manager.StoreOperationFactory.CreateAddMappingOperation( this.Manager, mapping.Kind == MappingKind.RangeMapping ? StoreOperationCode.AddRangeMapping : StoreOperationCode.AddPointMapping, this.ShardMap.StoreShardMap, newMapping.StoreMapping)) { op.Do(); } return(newMapping); }
public void Remove(Shard shard, Guid lockOwnerId = default(Guid)) { Debug.Assert(shard != null); ExceptionUtils.EnsureShardBelongsToShardMap( this.Manager, this.ShardMap, shard, "DeleteShard", "Shard"); using (IStoreOperation op = this.Manager.StoreOperationFactory.CreateRemoveShardOperation( this.Manager, this.ShardMap.StoreShardMap, shard.StoreShard)) { op.Do(); } }
public Shard Add(Shard shard) { Debug.Assert(shard != null); ExceptionUtils.EnsureShardBelongsToShardMap( this.Manager, this.ShardMap, shard, "CreateShard", "Shard"); using (IStoreOperation op = this.Manager.StoreOperationFactory.CreateAddShardOperation( this.Manager, this.ShardMap.StoreShardMap, shard.StoreShard)) { op.Do(); } return(shard); }
/// <summary> /// Allows for update to a shard with the updates provided in the <paramref name="update"/> parameter. /// </summary> /// <param name="currentShard">Shard to be updated.</param> /// <param name="update">Updated properties of the Shard.</param> /// <returns>New Shard instance with updated information.</returns> internal Shard UpdateShard(Shard currentShard, ShardUpdate update) { Debug.Assert(currentShard != null); Debug.Assert(update != null); ExceptionUtils.EnsureShardBelongsToShardMap( this.Manager, this.ShardMap, currentShard, "UpdateShard", "Shard"); // CONSIDER(wbasheer): Have refresh semantics for trivial case when nothing is modified. if (!update.IsAnyPropertySet(ShardUpdatedProperties.All)) { return(currentShard); } DefaultStoreShard sNew = new DefaultStoreShard( currentShard.Id, Guid.NewGuid(), currentShard.ShardMapId, currentShard.Location, update.IsAnyPropertySet(ShardUpdatedProperties.Status) ? (int)update.Status : currentShard.StoreShard.Status); using (IStoreOperation op = this.Manager.StoreOperationFactory.CreateUpdateShardOperation( this.Manager, this.ShardMap.StoreShardMap, currentShard.StoreShard, sNew)) { op.Do(); } return(new Shard(this.Manager, this.ShardMap, sNew)); }
/// <summary> /// Allows for update to a mapping with the updates provided in /// the <paramref name="update"/> parameter. /// </summary> /// <param name="currentMapping">Mapping being updated.</param> /// <param name="update">Updated properties of the Shard.</param> /// <param name="constructMapping">Delegate to construct a mapping object.</param> /// <param name="statusAsInt">Delegate to get the mapping status as an integer value.</param> /// <param name="intAsStatus">Delegate to get the mapping status from an integer value.</param> /// <param name="lockOwnerId">Lock owner id of this mapping</param> /// <param name="options">Options for validation operations to perform on opened connection to affected shard.</param> /// <returns>New instance of mapping with updated information.</returns> protected TMapping Update <TMapping, TUpdate, TStatus>( TMapping currentMapping, TUpdate update, Func <ShardMapManager, ShardMap, IStoreMapping, TMapping> constructMapping, Func <TStatus, int> statusAsInt, Func <int, TStatus> intAsStatus, Guid lockOwnerId = default(Guid), MappingOptions options = MappingOptions.Validate) where TUpdate : class, IMappingUpdate <TStatus> where TMapping : class, IShardProvider, IMappingInfoProvider where TStatus : struct { Debug.Assert(currentMapping != null); Debug.Assert(update != null); this.EnsureMappingBelongsToShardMap <TMapping>(currentMapping, "Update", "currentMapping"); IMappingUpdate <TStatus> mu = update as IMappingUpdate <TStatus>; // CONSIDER(wbasheer): Have refresh semantics for trivial case when nothing is modified. if (!mu.IsAnyPropertySet(MappingUpdatedProperties.All)) { return(currentMapping); } bool shardChanged = mu.IsAnyPropertySet(MappingUpdatedProperties.Shard) && !mu.Shard.Equals(currentMapping.ShardInfo); // Ensure that shard belongs to current shard map. if (shardChanged) { ExceptionUtils.EnsureShardBelongsToShardMap( this.Manager, this.ShardMap, mu.Shard, "UpdateMapping", currentMapping.Kind == MappingKind.PointMapping ? "PointMapping" : "RangeMapping"); } IStoreShard originalShard = new DefaultStoreShard( currentMapping.ShardInfo.Id, Guid.NewGuid(), currentMapping.ShardInfo.StoreShard.ShardMapId, currentMapping.ShardInfo.StoreShard.Location, currentMapping.ShardInfo.StoreShard.Status); IStoreMapping originalMapping = new DefaultStoreMapping( currentMapping.StoreMapping.Id, currentMapping.ShardMapId, originalShard, currentMapping.StoreMapping.MinValue, currentMapping.StoreMapping.MaxValue, currentMapping.StoreMapping.Status, lockOwnerId); IStoreShard updatedShard; if (shardChanged) { updatedShard = new DefaultStoreShard( update.Shard.ShardInfo.Id, Guid.NewGuid(), update.Shard.ShardInfo.StoreShard.ShardMapId, update.Shard.ShardInfo.StoreShard.Location, update.Shard.ShardInfo.StoreShard.Status); } else { updatedShard = originalShard; } IStoreMapping updatedMapping = new DefaultStoreMapping( Guid.NewGuid(), currentMapping.ShardMapId, updatedShard, currentMapping.StoreMapping.MinValue, currentMapping.StoreMapping.MaxValue, mu.IsAnyPropertySet(MappingUpdatedProperties.Status) ? statusAsInt(update.Status) : currentMapping.StoreMapping.Status, lockOwnerId); bool fromOnlineToOffline = mu.IsMappingBeingTakenOffline(intAsStatus(currentMapping.StoreMapping.Status)); StoreOperationCode opCode; if (fromOnlineToOffline) { opCode = currentMapping.Kind == MappingKind.PointMapping ? StoreOperationCode.UpdatePointMappingWithOffline : StoreOperationCode.UpdateRangeMappingWithOffline; } else { opCode = currentMapping.Kind == MappingKind.PointMapping ? StoreOperationCode.UpdatePointMapping : StoreOperationCode.UpdateRangeMapping; } var killConnection = options == MappingOptions.Validate; using (IStoreOperation op = this.Manager.StoreOperationFactory.CreateUpdateMappingOperation( this.Manager, opCode, this.ShardMap.StoreShardMap, originalMapping, updatedMapping, this.ShardMap.ApplicationNameSuffix, lockOwnerId, killConnection)) { op.Do(); } return(constructMapping(this.Manager, this.ShardMap, updatedMapping)); }