/// <summary> /// Performs the undo of LSM operation on the source shard. /// </summary> /// <param name="ts">Transaction scope.</param> /// <returns>Result of the operation.</returns> public override IStoreResults UndoLocalSourceExecute(IStoreTransactionScope ts) { DefaultStoreShard dssOriginal = new DefaultStoreShard( _mappingsSource[0].Item1.StoreShard.Id, this.OriginalShardVersionAdds, _mappingsSource[0].Item1.ShardMapId, _mappingsSource[0].Item1.StoreShard.Location, _mappingsSource[0].Item1.StoreShard.Status); DefaultStoreMapping dsmSource = new DefaultStoreMapping( _mappingsSource[0].Item1.Id, _mappingsSource[0].Item1.ShardMapId, dssOriginal, _mappingsSource[0].Item1.MinValue, _mappingsSource[0].Item1.MaxValue, _mappingsSource[0].Item1.Status, _mappingsSource[0].Item2); DefaultStoreMapping dsmTarget = new DefaultStoreMapping( _mappingsTarget[0].Item1.Id, _mappingsTarget[0].Item1.ShardMapId, dssOriginal, _mappingsTarget[0].Item1.MinValue, _mappingsTarget[0].Item1.MaxValue, _mappingsTarget[0].Item1.Status, _mappingsTarget[0].Item2); IStoreMapping[] ms = new[] { dsmSource }; IStoreMapping[] mt = new[] { dsmTarget }; return(ts.ExecuteOperation( StoreOperationRequestBuilder.SpBulkOperationShardMappingsLocal, StoreOperationRequestBuilder.ReplaceShardMappingsLocal( this.Id, true, _shardMap, mt.Concat(_mappingsTarget.Skip(1).Select(m => m.Item1)).ToArray(), ms.Concat(_mappingsSource.Skip(1).Select(m => m.Item1)).ToArray()))); }
/// <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> /// <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)) 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; } using (IStoreOperation op = this.Manager.StoreOperationFactory.CreateUpdateMappingOperation( this.Manager, opCode, this.ShardMap.StoreShardMap, originalMapping, updatedMapping, this.ShardMap.ApplicationNameSuffix, lockOwnerId)) { op.Do(); } return(constructMapping(this.Manager, this.ShardMap, updatedMapping)); }