Example #1
0
        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);
        }
Example #2
0
        /// <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());
        }
Example #3
0
        /// <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));
        }
Example #7
0
        /// <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));
        }