Ejemplo n.º 1
0
        /// <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())));
        }
Ejemplo n.º 2
0
        /// <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));
        }
Ejemplo n.º 3
0
        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));
        }
Ejemplo n.º 4
0
        /// <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));
        }