/// <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 void AttachShard(ShardLocation location, string shardMapName) { ExceptionUtils.DisallowNullArgument(location, "location"); IStoreResults result; using (IStoreOperationLocal op = this.Manager.StoreOperationFactory.CreateGetShardsLocalOperation( this.Manager, location, "AttachShard")) { result = op.Do(); } Debug.Assert(result.Result == StoreResult.Success); IEnumerable <IStoreShardMap> shardMaps = shardMapName == null ? result.StoreShardMaps : result.StoreShardMaps.Where(s => s.Name == shardMapName); shardMaps.ToList <IStoreShardMap>().ForEach((sm) => { IStoreShard shard = result.StoreShards.SingleOrDefault(s => s.ShardMapId == sm.Id); // construct a new store shard with correct location DefaultStoreShard sNew = new DefaultStoreShard( shard.Id, shard.Version, shard.ShardMapId, location, shard.Status); using (IStoreOperation op = this.Manager.StoreOperationFactory.CreateAttachShardOperation( this.Manager, sm, sNew)) { 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> /// Removes a mapping from shard map. /// </summary> /// <typeparam name="TMapping">Mapping type.</typeparam> /// <param name="mapping">Mapping being removed.</param> /// <param name="constructMapping">Delegate to construct a mapping object.</param> /// <param name="lockOwnerId">Lock owner id of this mapping</param> protected void Remove <TMapping>( TMapping mapping, Func <ShardMapManager, ShardMap, IStoreMapping, TMapping> constructMapping, Guid lockOwnerId) where TMapping : class, IShardProvider, IMappingInfoProvider { this.EnsureMappingBelongsToShardMap <TMapping>(mapping, "Remove", "mapping"); TMapping newMapping = constructMapping( this.Manager, this.ShardMap, new DefaultStoreMapping( mapping.StoreMapping.Id, mapping.StoreMapping.ShardMapId, new DefaultStoreShard( mapping.ShardInfo.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.CreateRemoveMappingOperation( this.Manager, mapping.Kind == MappingKind.RangeMapping ? StoreOperationCode.RemoveRangeMapping : StoreOperationCode.RemovePointMapping, this.ShardMap.StoreShardMap, newMapping.StoreMapping, lockOwnerId)) { op.Do(); } }
/// <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)); }
internal RangeMapping <TKey> Merge(RangeMapping <TKey> left, RangeMapping <TKey> right, Guid leftLockOwnerId, Guid rightLockOwnerId) { this.EnsureMappingBelongsToShardMap <RangeMapping <TKey> >(left, "Merge", "left"); this.EnsureMappingBelongsToShardMap <RangeMapping <TKey> >(right, "Merge", "right"); if (!left.Shard.Location.Equals(right.Shard.Location)) { throw new ArgumentException( StringUtils.FormatInvariant( Errors._ShardMapping_MergeDifferentShards, this.ShardMap.Name, left.Shard.Location, right.Shard.Location), "left"); } if (left.Range.Intersects(right.Range) || left.Range.High != right.Range.Low) { throw new ArgumentOutOfRangeException( "left", Errors._ShardMapping_MergeNotAdjacent); } if (left.Status != right.Status) { throw new ArgumentException( StringUtils.FormatInvariant( Errors._ShardMapping_DifferentStatus, this.ShardMap.Name), "left"); } IStoreShard newShard = new DefaultStoreShard( left.Shard.StoreShard.Id, Guid.NewGuid(), left.Shard.StoreShard.ShardMapId, left.Shard.StoreShard.Location, left.Shard.StoreShard.Status); IStoreMapping mappingToRemoveLeft = new DefaultStoreMapping( left.StoreMapping.Id, left.StoreMapping.ShardMapId, newShard, left.StoreMapping.MinValue, left.StoreMapping.MaxValue, left.StoreMapping.Status, left.StoreMapping.LockOwnerId); IStoreMapping mappingToRemoveRight = new DefaultStoreMapping( right.StoreMapping.Id, right.StoreMapping.ShardMapId, newShard, right.StoreMapping.MinValue, right.StoreMapping.MaxValue, right.StoreMapping.Status, right.StoreMapping.LockOwnerId); IStoreMapping mappingToAdd = new DefaultStoreMapping( Guid.NewGuid(), newShard.ShardMapId, newShard, left.Range.Low.RawValue, right.Range.High.RawValue, (int)left.Status, leftLockOwnerId); using (IStoreOperation op = this.Manager.StoreOperationFactory.CreateReplaceMappingsOperation( this.Manager, StoreOperationCode.MergeMappings, this.ShardMap.StoreShardMap, new[] { new Tuple <IStoreMapping, Guid> (mappingToRemoveLeft, leftLockOwnerId), new Tuple <IStoreMapping, Guid> (mappingToRemoveRight, rightLockOwnerId) }, new[] { new Tuple <IStoreMapping, Guid>(mappingToAdd, leftLockOwnerId) })) { op.Do(); } return(new RangeMapping <TKey>(this.Manager, this.ShardMap, mappingToAdd)); }
/// <summary> /// Splits the given mapping into 2 at the given key. The new mappings point to the same shard /// as the existing mapping. /// </summary> /// <param name="existingMapping">Given existing mapping.</param> /// <param name="splitAt">Split point.</param> /// <param name="lockOwnerId">Lock owner id of this mapping</param> /// <returns>Read-only collection of 2 new mappings thus created.</returns> internal IReadOnlyList <RangeMapping <TKey> > Split(RangeMapping <TKey> existingMapping, TKey splitAt, Guid lockOwnerId) { this.EnsureMappingBelongsToShardMap <RangeMapping <TKey> >( existingMapping, "Split", "existingMapping"); ShardKey shardKey = new ShardKey(ShardKey.ShardKeyTypeFromType(typeof(TKey)), splitAt); if (!existingMapping.Range.Contains(shardKey) || existingMapping.Range.Low == shardKey || existingMapping.Range.High == shardKey) { throw new ArgumentOutOfRangeException( "splitAt", Errors._ShardMapping_SplitPointOutOfRange); } IStoreShard newShard = new DefaultStoreShard( existingMapping.Shard.StoreShard.Id, Guid.NewGuid(), existingMapping.ShardMapId, existingMapping.Shard.StoreShard.Location, existingMapping.Shard.StoreShard.Status); IStoreMapping mappingToRemove = new DefaultStoreMapping( existingMapping.StoreMapping.Id, existingMapping.StoreMapping.ShardMapId, newShard, existingMapping.StoreMapping.MinValue, existingMapping.StoreMapping.MaxValue, existingMapping.StoreMapping.Status, existingMapping.StoreMapping.LockOwnerId); IStoreMapping[] mappingsToAdd = new IStoreMapping[2] { new DefaultStoreMapping( Guid.NewGuid(), newShard.ShardMapId, newShard, existingMapping.Range.Low.RawValue, shardKey.RawValue, (int)existingMapping.Status, lockOwnerId), new DefaultStoreMapping( Guid.NewGuid(), newShard.ShardMapId, newShard, shardKey.RawValue, existingMapping.Range.High.RawValue, (int)existingMapping.Status, lockOwnerId) }; using (IStoreOperation op = this.Manager.StoreOperationFactory.CreateReplaceMappingsOperation( this.Manager, StoreOperationCode.SplitMapping, this.ShardMap.StoreShardMap, new[] { new Tuple <IStoreMapping, Guid>(mappingToRemove, lockOwnerId) }, mappingsToAdd.Select(mappingToAdd => new Tuple <IStoreMapping, Guid>(mappingToAdd, lockOwnerId)).ToArray())) { op.Do(); } return(mappingsToAdd .Select(m => new RangeMapping <TKey>(this.Manager, this.ShardMap, m)) .ToList() .AsReadOnly()); }
/// <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)); }